Common startup rules live in [AGENTS.md](../../AGENTS.md). This document holds
procedures and conventions to read when they apply, not extra startup imports.
## Maintaining canonical knowledge
After meaningful changes, assess documentation before declaring completion.
Meaningful changes include user-visible behavior, architecture/data flow,
maintenance/setup/debugging workflows, and subsystem contracts. Formatting,
behavior-preserving refactors and isolated test changes need no doc update.
Prefer the existing authoritative architecture doc or nearest module README;
README.md owns top-level user/developer entry points. Update stale routes,
paths, commands and contracts you encounter, or explicitly flag unresolved
claims in the final summary. Repo docs remain canonical regardless of authorship.
Keep AGENTS.md limited to repository-wide constraints and task routing. Do not
add feature histories, method lists, schema inventories or troubleshooting
procedures to it. CLAUDE.md imports AGENTS.md; do not mirror common prose by hand.
Use [the context map](../maintenance/agent-context-map.md) for the owning document
and relevant skill. Read multiple contracts for cross-domain work. Add a new
canonical document only when no existing owner fits; link it from the map.
When relocating knowledge, compare both sources and the destination, retain
unique exceptions and rationale, and record corrections with code evidence.
The [2026-09 migration ledger](../maintenance/agent-guidance-migration.md) records
the initial move; it is an audit artifact, not required reading for feature work.
Later normal edits maintain the canonical docs, not duplicate historical prose.
Run `pnpm run agents:validate` after guidance changes. It checks line/byte budgets,
root imports and local navigation links/anchors, including migration destinations.
Line budgets count LF, CRLF and standalone CR endings consistently.
Markdown navigation is parsed with the already-declared `marked` dependency;
undefined explicit references (including shortcut images) are errors, and code examples are excluded.
Backticked concrete paths in root guidance and the context map are checked from
the repository root, including unknown top-level directories and filenames.
Write generic filenames as prose; commands, templates, globs, URLs, package
aliases and dotted code symbols are excluded. Bare dotted names with conventional
file suffixes (such as .md, .json or .ts) are treated as filenames. Document formats
share the suffix set used by package-import guards, including PDF and AsciiDoc. Use a `./`
prefix or Markdown link for other ambiguous filenames that resemble code symbols.
Explicit relative literals denote paths, including spaces, filesystem punctuation and hyphenated words.
Put executable command examples in fenced code when their syntax also looks like a path.
Multi-part dotfiles are path candidates too.
Conventional extensionless filenames such as Dockerfile, Makefile and LICENSE
are also path candidates; use an explicit `./` prefix for other extensionless files.
Link paths and fragments are decoded separately so encoded filename delimiters
stay in the filename. Fenced and indented examples
do not count as root guidance imports or satisfy the required Claude import.
The required Claude import must be an unformatted standalone line in a top-level
paragraph; headings, quotes and list items do not satisfy it.
The parsed HTML tree also verifies that this paragraph is outside HTML containers,
including templates split across Markdown tokens. Generated HTML is inspected
in memory only; it is never executed or emitted.
Heading anchors decode HTML character references in text and use `github-slugger`
for GitHub-compatible character filtering and duplicate suffixes.
Only headings present outside inert HTML containers contribute slugs or duplicate counters.
Explicit HTML anchors use `parse5`, excluding comments, scripts, styles and template contents.
Rendered HTML anchor and image-map area hrefs and image sources use the same local-reference checks
as Markdown links, including decoded attributes and fragment validation.
URL attributes remove ASCII tabs/newlines throughout and discard surrounding
ASCII control/space characters before resolution.
Iframe/embed sources and object data attributes are document references and retain Markdown-target anchor checks.
Inline iframe srcdoc documents are traversed too, with their own fragment anchors.
The first active HTML base href sets reference resolution, including nested srcdoc bases.
Resolved file URLs use native filesystem conversion, including Windows drive paths.
Explicit srcset attributes must contain at least one parsed candidate.
Image and media references require a nonempty path that resolves to a file, not a directory.
Direct file URLs, Windows drive paths and HTML bases using either form are rejected; use portable repository-relative paths.
Image references check file existence without interpreting image fragments as
Markdown headings; document links keep anchor checks even when sharing a target.
SVG image/use hrefs (including xlink), HTML image-input, video, audio, source and track `src` assets and video posters use the same
existence checks as images. Entity decoding uses full HTML text/attribute rules,
including references whose semicolon may be omitted.
Inline guidance imports are rejected after punctuation as well as whitespace.
At-signs inside external URIs (including www autolinks and explicit opaque autolinks such as mailto) are excluded
per HTML text node, preserving adjacent imports. A colon directly before an import
does not make that import a URI. Opaque schemes are excluded only in parsed links
whose visible text equals their URI, so colon-labeled prose remains checked.
A closing bracket or matching enclosing quote followed by punctuation and an at-sign terminates a bare URL exclusion.
Extensionless inline candidates are also imports when they resolve to repository files,
checking the full filename before prefixes at ASCII/Unicode prose separators,
including opening parentheses, brackets and braces. Each at-sign candidate is
checked independently, including imports nested next to a package mention.
An at-sign inside a word (for example, foo@INSTRUCTIONS or an email address)
is not an import boundary, including within parenthetical prose.
Declared scoped dependencies, scope wildcards and matching TypeScript path aliases
are recognized as package/alias mentions. Traversal and document-file imports are
rejected before those exemptions, including document paths with fragments or queries.
All recognized Markdown extensions share the document-import guard; reStructuredText
and AsciiDoc, PDF, Word, OpenDocument, RTF, Org and TeX documents are also excluded
from package exemptions. Recognized extensionless guidance names (including AGENTS,
CLAUDE, INSTRUCTIONS, README, CONTRIBUTING and SECURITY, case-insensitively) are excluded in package subpaths too. URL-encoded
paths do not receive package exemptions. TypeScript configuration is parsed as JSONC.
Declared packages also permit safe subpaths; exact aliases stay exact.
Federated handles in the @user@host form are prose, not imports; trailing closing
ASCII/Unicode punctuation and possessive apostrophe-s suffixes are ignored. Opening
delimiters separate adjacent prose; nested imports remain checked. Extra at-signs do not qualify for that exemption.
Exact declared packages remain exempt after version normalization.
Declared package mentions may include a version (including semver comparators and wildcard ranges) or dist-tag qualifier.
Qualifier handling includes unscoped names; terminal sentence punctuation is
removed before matching a declared package, as are straight/curly apostrophe possessives.
Unicode punctuation and ASCII opening delimiters, commas, semicolons, colons, question/exclamation marks
separate package mentions from adjacent prose.
Markdown destinations decode HTML entities before URI parsing, matching rendered links.
Heading-anchor lookup is limited to Markdown targets. Source-file line fragments,
PDF page fragments and other non-Markdown fragments retain file-existence checks.
The import scan separates HTML block/table elements and includes visible text and literal backticks; it excludes parsed code nodes and non-rendered containers.
Navigation uses the parsed rendered tree too. Temporary in-memory markers retain
definition, unresolved-reference and literal-path metadata, so Markdown inside
inert templates is excluded consistently with raw HTML navigation.
Image source sets use `parse-srcset` to check each candidate URL. Root-relative
literals never suppress source-relative definition checks.
The Nx test hash includes `marked`, `parse5`, `github-slugger`, `parse-srcset` and `typescript`
so dependency changes invalidate parser coverage.
It cannot prove semantic equivalence; review changed contracts as well.
## Protected Markdown edits
Never run whole-file `prettier --write` on AGENTS.md, CLAUDE.md or docs/**.
Upstream formatting is not uniformly Prettier-clean: whole-file writes can
corrupt nested list indentation or change a literal continuation into a bullet.
Format only intended new lines. If accidental formatting occurred, reconstruct
from the pre-edit version and reapply only intended changes; preserve unrelated
user edits. Use the merge-base version only if it actually represents that
pre-edit state. Review the diff rather than blindly restoring an older branch.
## Plans and completion reports
Save only finalized plans in `.plans/YYYY-MM-DD-short-topic.md`; use numeric
suffixes for collisions. Do not save drafts or questions there. If an active
mode forbids writes, save the approved plan on entering execution.
Completion reports list changed docs, tests added/updated, commands and results,
skipped validation with reasons, and release-note status. A docs-only task needs
Markdown/link validation, not app unit/E2E tests. Tooling changes need their own tests.
## Repository skills
Repository skills live under `.codex/skills/`. Descriptions are trigger-only,
begin with `Use when`, and each skill is at most 500 words. Frontmatter owns
trigger descriptions; avoid copying them into navigation prose. Skills provide
workflow and links to authoritative contracts, not a second contract copy.
`release-cut` and `release-notes` have byte-identical `.claude/skills/` mirrors.
Run `pnpm run skills:validate` after changing a committed skill or a literal
path it documents. New guidance tooling belongs to the existing
`repository-skills` Nx project; no new project is needed for another validator.
## Angular conventions
Use signal-based queries (`viewChild`, `viewChildren`, `contentChild`,
`contentChildren`) and inputs/outputs (`input`, `output`). For required queries,
use `viewChild.required`. Unwrap signals when passing values in templates:
```typescript
readonly menu = viewChild.required<MatMenu>('menuRef');
Use this procedure for Electron/CDP tasks. Read the available `electron` skill
when automating the desktop app. These commands assume a bootstrapped worktree.
## Start and attach
- Start the Electron development app with: `pnpm nx serve electron-backend`
- Package-script equivalent: `pnpm run serve:backend`
- Electron is configured to start with: `--remote-debugging-port=9222`
- Connect Chrome DevTools Protocol tools to: `127.0.0.1:9222`
- For Electron automation/debugging tasks, use the `electron` skill
- Do not auto-open DevTools during normal CDP automation. In development, DevTools is opt-in via `ELECTRON_OPEN_DEVTOOLS=1`.
- If DevTools is open, `agent-browser --cdp 9222 ...` may attach to the DevTools page instead of the IPTVnator window. Symptoms: `tab list` shows `about:blank`, snapshots are empty, and screenshots are black.
- If that happens, inspect targets with `curl http://127.0.0.1:9222/json/list` and connect directly to the IPTVnator page websocket from the `webSocketDebuggerUrl` field.
- The app holds a single-instance lock (`acquireSingleInstanceLock` in `apps/electron-backend/src/app/services/single-instance.ts`): a second launch against the same `userData` quits immediately and focuses the running window. To attach a second CDP-enabled instance to the same profile, set `IPTVNATOR_ALLOW_MULTIPLE_INSTANCES=1` — knowing that only one of the two processes will own the renderer's IndexedDB, so settings written by the other are lost. Before focusing, the guard forwards the second launch's argv to `onSecondInstance`, which is how a playlist path handed to an already-running app reaches the open queue.
- `IPTVNATOR_TRACE_RENDERER_CONSOLE=1` mirrors renderer console output into the Electron terminal
- `IPTVNATOR_PERF_CAPTURE=1` enables development/test-only, redacted M3U and Xtream preload IPC request/completion markers plus count-only M3U acquire/parse/normalize, Xtream main network/JSON-transform/success-response-ready/cancel-dispatch, and renderer store phase capture; renderer wrappers emit only while the benchmark installs its Symbol hook, benchmark tooling sets the flag explicitly, and production launches must leave it unset
- `IPTVNATOR_PERF_WORKER_PROFILING=1` enables development/test-only, request-scoped worker receive/work/response-post timestamps, thread CPU, event-loop utilization/delay, count-only playlist serialization/SQLite write/read/deserialization plus Xtream category/content/cache-clear/delete/in-source-search phase events, profiling-only worker cancel-receipt acknowledgements, valid-sample-counted isolate peak memory, and the database worker's idle-only one-shot post-GC heap probe; overlapping database requests are explicitly invalidated instead of misattributed, the performance benchmark sets the flag automatically, and production launches must leave it unset
- Settings, portal request/response, and trace payloads must use
`@iptvnator/shared/logging` or the redacting portal logger before reaching
`console.*`; never log raw credentials while debugging.
| Angular conventions; docs and skills maintenance | [Agent workflow](../development/agent-workflow.md) | Use the area's skill below |
| Unit, E2E, lint and coverage; `tools/coverage` | [Validation map](../architecture/validation-map.md) | Use the area's validation section |
| Electron entry/events/preload and CDP; `apps/electron-backend` | [Debugging and trace flags](../development/electron-debugging.md), [Electron security](../architecture/electron-security.md) | Use the available global electron skill for automation |
| Stalker/Ministra protocol, identity, sessions and routed views; `libs/portal/stalker` | [Stalker portal](../architecture/stalker-portal.md), [Stalker EPG](../architecture/stalker-epg.md) for EPG work, [store API baseline](../architecture/stalker-store-api-baseline.md) for store API changes | [Stalker](../../.codex/skills/stalker-portal/SKILL.md) |
| Browser runtime, HTTP proxies, redirects and backend networking; `apps/web-backend`, `libs/shared/host-health` | [PWA/self-hosting](../architecture/pwa-self-hosted.md), [connectivity guard](../architecture/host-connectivity-guard.md), [Electron security](../architecture/electron-security.md) for desktop boundary changes | Read the affected runtime contract |
| Source health and selective cleanup; portal shared data access | [Desktop source health](../architecture/m3u-playlist-module.md#desktop-source-health), [subscription expiry](../architecture/workspace-dashboard.md#source-subscription-expiry) | Read the affected provider skill |
| Backup and restore; playlist persistence | [Backup/restore](../architecture/playlist-backup-restore.md), [database migrations](../../libs/shared/database/README.md) | Read the affected persistence skill |
Original files: [AGENTS.md](https://github.com/4gray/iptvnator/blob/d4df0fd81a71f0bf196ceac2b45efe3697feb973/AGENTS.md)
(1,217 lines, 88,565 bytes) and [CLAUDE.md](https://github.com/4gray/iptvnator/blob/d4df0fd81a71f0bf196ceac2b45efe3697feb973/CLAUDE.md)
(2,022 lines, 231,858 bytes). Table coordinates refer to these immutable files,
not the shortened roots. This is audit evidence; it is not a required startup document.
## Method and coverage
Every non-empty source block was inventoried. Headings, standalone labels,
separator lines and Nx markers are structural; their contents are represented
below. Lists are split at each top-level item; code fences stay intact. The
17,847-character CLAUDE.md line 1315 is split into sentence-level entries so
individual constraints do not disappear behind one row. Repeated entries from
the two agents intentionally retain separate source references.
716 content entries are accounted for below; there are no unassigned
source blocks. "Existing contract" means the canonical document already carries
the behavior and was reviewed instead of copying another summary. "Added" and
"Moved" identify knowledge incorporated during this change. Destination sections
are entry points into the owning contract; adjacent subheadings cover supporting
exceptions and examples. The [context map](agent-context-map.md) is the live
navigation surface; this ledger records the one-time relocation.
## Corrections and consolidation decisions
- Root growth/mirroring requirements are replaced by one source of common rules
and topic-specific maintenance in [agent workflow](../development/agent-workflow.md#maintaining-canonical-knowledge).
Root limits do not apply to canonical reference docs; those load on demand.
- Stalker static URL wording was oversimplified. Missing flag evidence still
requires minting a link (with the directly playable radio exception), as
specified in [playback link resolution](../architecture/stalker-portal.md#playback-link-resolution)
and implemented by the existing Stalker link-semantics utilities. Keep the
authoritative decision table, not the old "otherwise static" shorthand.
- Generic Electron detection is not an individual capability gate. Desktop also
has Chromium settings storage, PWA supports browser-selected uploads, and SQL
and IndexedDB schemas are not identical. Preserve the existing DataFactory
boundary with these corrections in [service factory and build bases](../architecture/pwa-self-hosted.md#service-factory-and-build-bases).
- Browser wake-lock auto-release clears the sentinel; the next media/visibility/
PiP sync reacquires. Preserve actual renderer behavior, not an implication of
immediate unconditional reacquisition; see [display sleep](../architecture/player-controls-contract.md#display-sleep-during-playback).
- Full-file formatting recovery must preserve unrelated user edits. Replace the
unconditional merge-base overwrite recipe with [safe reconstruction](../development/agent-workflow.md#protected-markdown-edits).
- The TypeScript hard limit is 400, not a variable 350–400; target under 300.
HostBinding/HostListener conventions are retained, not silently modernized.
- Nx tools and global skills are optional. Retain discovery fallbacks and the
managed markers in [AGENTS.md](../../AGENTS.md#general-guidelines-for-working-with-nx).
- Build/serve examples use local pnpm Nx or package scripts. Packaging uses
`package:app` (`make --prepackageOnly`), not the obsolete `electron-backend:package`
target suggested in the old alternative command.
- Version-specific signing patch rationale was missing from canonical docs and
now lives in [the dependency contract](../architecture/nx-workspace-boundaries.md#electron-builder-signing-patch).
- Exhaustive trees, diagrams and code examples are consolidated into the owning
architecture/maintenance sections; they do not become a second project map.
Existing snapshot inventories are navigation aids, not instructions to duplicate
every new project in the root. Plan saving respects active no-write modes.
## Block inventory
| Original source | Section and contract / example | Canonical destination | Disposition |
| --- | --- | --- | --- |
| AGENTS.md:3–3 | AGENTS.md — This file provides guidance to coding agents working in this repository. | [Plans and completion reports](../development/agent-workflow.md#plans-and-completion-reports) | Moved / consolidated |
| AGENTS.md:7–7 | Plan Mode — When an agent is in Plan Mode and produces a final <proposed_plan>, it must also save that finalized plan… | [Plans and completion reports](../development/agent-workflow.md#plans-and-completion-reports) | Moved / consolidated |
| AGENTS.md:8–8 | Plan Mode — Save only finalized plans. Do not write interim exploration, questions, or draft revisions to .plans/. | [Plans and completion reports](../development/agent-workflow.md#plans-and-completion-reports) | Moved / consolidated |
| AGENTS.md:9–9 | Plan Mode — Use the filename pattern YYYY-MM-DD-short-topic.md such as .plans/2026-03-12-channel-filtering.md. | [Plans and completion reports](../development/agent-workflow.md#plans-and-completion-reports) | Moved / consolidated |
| AGENTS.md:10–10 | Plan Mode — If the intended filename already exists, append a numeric suffix such as -2, -3, and so on. | [Plans and completion reports](../development/agent-workflow.md#plans-and-completion-reports) | Moved / consolidated |
| AGENTS.md:14–14 | Agent Bootstrap — In a fresh worktree, run pnpm install --frozen-lockfile before relying on Nx project discovery, lint,… | [Fresh Worktree Bootstrap and Discovery](../architecture/nx-workspace-boundaries.md#fresh-worktree-bootstrap-and-discovery) | Existing contract |
| AGENTS.md:15–15 | Agent Bootstrap — Re-run the install whenever the checkout moves — git pull, git reset --hard, a rebase, or a worktree… | [Fresh Worktree Bootstrap and Discovery](../architecture/nx-workspace-boundaries.md#fresh-worktree-bootstrap-and-discovery) | Existing contract |
| AGENTS.md:16–16 | Agent Bootstrap — Never run prettier --write on CLAUDE.md, AGENTS.md or docs/. These files are not Prettier-clean upstream,… | [Protected Markdown edits](../development/agent-workflow.md#protected-markdown-edits) | Corrected safe restore |
| AGENTS.md:17–17 | Agent Bootstrap — After dependencies are installed, verify workspace discovery with pnpm nx show projects. | [Fresh Worktree Bootstrap and Discovery](../architecture/nx-workspace-boundaries.md#fresh-worktree-bootstrap-and-discovery) | Existing contract |
| AGENTS.md:18–18 | Agent Bootstrap — Use scoped path aliases from tsconfig.base.json such as @iptvnator/services, @iptvnator/shared/interfaces,… | [Import Aliases and Public APIs](../architecture/nx-workspace-boundaries.md#import-aliases-and-public-apis) | Existing contract |
| AGENTS.md:19–19 | Agent Bootstrap — Every Nx project should keep scope:, domain:, and type: tags in project.json so… | [Project Tags](../architecture/nx-workspace-boundaries.md#project-tags) | Existing contract |
| AGENTS.md:20–20 | Agent Bootstrap — See docs/architecture/nx-workspace-boundaries.md for the current Nx tag and alias policy. | [Import Aliases and Public APIs](../architecture/nx-workspace-boundaries.md#import-aliases-and-public-apis) | Existing contract |
| AGENTS.md:21–22 | Agent Bootstrap — Keep nx and every official @nx/ package on the same exact version; run pnpm run deps:nx:validate after… | [Nx Dependency Updates](../architecture/nx-workspace-boundaries.md#nx-dependency-updates) | Existing contract |
| AGENTS.md:23–24 | Agent Bootstrap — Use the Node version in .nvmrc for development and CI. Angular 22 requires Node ^22.22.3 || ^24.15.0 and… | [Angular 22 Toolchain Compatibility](../architecture/nx-workspace-boundaries.md#angular-22-toolchain-compatibility) | Existing contract |
| AGENTS.md:25–29 | Agent Bootstrap — Vite 8.1.5, resolved through Angular's build tooling, retains upstream precise matchers and adds bounded… | [Vite Dev-Server Patch](../architecture/nx-workspace-boundaries.md#vite-dev-server-patch) | Existing contract |
| AGENTS.md:41–47 | Agent Bootstrap — node-gyp is a declared root devDependency because apps/electron-backend/build-embedded-mpv.js resolves it… | [Packaging State](../architecture/embedded-mpv-native.md#packaging-state) | Existing contract |
| AGENTS.md:48–52 | Agent Bootstrap — nx-electron@22.0.0 uses a local Nx 23 export-path patch and an explicit webpack-node-externals package… | [Angular 22 Toolchain Compatibility](../architecture/nx-workspace-boundaries.md#angular-22-toolchain-compatibility) | Existing contract |
| AGENTS.md:53–59 | Agent Bootstrap — A directory holding files consumed by other projects must be an Nx project. Nx builds its graph from… | [Shared Stylesheets and Cache Inputs](../architecture/nx-workspace-boundaries.md#shared-stylesheets-and-cache-inputs) | Existing contract |
| AGENTS.md:60–63 | Agent Bootstrap — Update Nx with pnpm nx migrate nx@<target> --skipInstall, regenerate the lockfile, run generated… | [Nx Dependency Updates](../architecture/nx-workspace-boundaries.md#nx-dependency-updates) | Existing contract |
| AGENTS.md:64–64 | Agent Bootstrap — ESLint enforces max-lines on TypeScript files: production code targets under 300 with a hard maximum of… | [TypeScript File Size](../architecture/nx-workspace-boundaries.md#typescript-file-size) | Existing contract |
| AGENTS.md:65–65 | Agent Bootstrap — Project lint targets that shell out to eslint must quote the glob, e.g. eslint "apps/<project>//.ts". An… | [Command-Based Lint Targets](../architecture/nx-workspace-boundaries.md#command-based-lint-targets) | Existing contract |
| AGENTS.md:66–66 | Agent Bootstrap — Repository-specific skills live under .codex/skills/. | [Repository skills](../development/agent-workflow.md#repository-skills) | Moved / consolidated |
| AGENTS.md:67–68 | Agent Bootstrap — Frontmatter descriptions are trigger-only and begin with Use when; keep each skill at or below 500 words. | [Repository skills](../development/agent-workflow.md#repository-skills) | Moved / consolidated |
| AGENTS.md:69–70 | Agent Bootstrap — Run pnpm run skills:validate after editing a committed skill or a literal path it documents. | [Repository skills](../development/agent-workflow.md#repository-skills) | Moved / consolidated |
| AGENTS.md:71–72 | Agent Bootstrap — Keep .codex and .claude copies of release-notes and release-cut byte-identical. | [Repository skills](../development/agent-workflow.md#repository-skills) | Moved / consolidated |
| AGENTS.md:76–76 | Documentation After Changes — After implementing a meaningful change, agents must assess whether canonical repo docs need updates before… | [Maintaining canonical knowledge](../development/agent-workflow.md#maintaining-canonical-knowledge) | Moved / consolidated |
| AGENTS.md:77–77 | Documentation After Changes — Meaningful changes include new or changed user-visible behavior, architecture or data-flow changes,… | [Maintaining canonical knowledge](../development/agent-workflow.md#maintaining-canonical-knowledge) | Moved / consolidated |
| AGENTS.md:78–78 | Documentation After Changes — Skip doc updates for trivial refactors with unchanged behavior, formatting-only edits, and isolated… | [Maintaining canonical knowledge](../development/agent-workflow.md#maintaining-canonical-knowledge) | Moved / consolidated |
| AGENTS.md:79–82 | Documentation After Changes — Prefer updating an existing authoritative doc before creating a new one: 1. README.md for top-level… | [Maintaining canonical knowledge](../development/agent-workflow.md#maintaining-canonical-knowledge) | Moved / consolidated |
| AGENTS.md:83–83 | Documentation After Changes — Keep the root CLAUDE.md and this file up to date. They are living documents: whenever a change touches… | [Maintaining canonical knowledge](../development/agent-workflow.md#maintaining-canonical-knowledge) | Moved / consolidated |
| AGENTS.md:84–84 | Documentation After Changes — When adding a new feature area, check whether the Architecture or Key Features sections of CLAUDE.md… | [Maintaining canonical knowledge](../development/agent-workflow.md#maintaining-canonical-knowledge) | Moved / consolidated |
| AGENTS.md:85–85 | Documentation After Changes — Do not let CLAUDE.md or AGENTS.md drift: a stale path or route in these files poisons the context of every… | [Maintaining canonical knowledge](../development/agent-workflow.md#maintaining-canonical-knowledge) | Moved / consolidated |
| AGENTS.md:86–86 | Documentation After Changes — Repo docs are canonical even when they were originally drafted by an LLM. | [Maintaining canonical knowledge](../development/agent-workflow.md#maintaining-canonical-knowledge) | Moved / consolidated |
| AGENTS.md:87–87 | Documentation After Changes — Final task summaries should state whether docs were updated and which doc changed. | [Maintaining canonical knowledge](../development/agent-workflow.md#maintaining-canonical-knowledge) | Moved / consolidated |
| AGENTS.md:91–91 | Release Notes For User-Visible Changes — Any change a user could notice — new behavior, changed behavior, bug fix, performance win, breaking change… | [File](../../.changes/README.md#file) | Existing contract |
| AGENTS.md:92–92 | Release Notes For User-Visible Changes — Name it <area>-<short-slug>.md; area matches the conventional-commit scope. There is no version field —… | [File](../../.changes/README.md#file) | Existing contract |
| AGENTS.md:93–93 | Release Notes For User-Visible Changes — Write the body for a user, not a reviewer: "the player now remembers volume between episodes", not "hoist… | [Writing the body](../../.changes/README.md#writing-the-body) | Existing contract |
| AGENTS.md:94–94 | Release Notes For User-Visible Changes — type: internal records invisible maintenance. Internal notes stay collapsed in CHANGELOG.md, are omitted… | [Writing the body](../../.changes/README.md#writing-the-body) | Existing contract |
| AGENTS.md:95–95 | Release Notes For User-Visible Changes — highlight: <short headline> (max 60 characters, rejected on type: internal) marks a note as one of the… | [Writing the body](../../.changes/README.md#writing-the-body) | Existing contract |
| AGENTS.md:96–96 | Release Notes For User-Visible Changes — Skip the note for test-only changes, docs, CI/workflow plumbing, and pure refactors with no behavior… | [When a note is not needed](../../.changes/README.md#when-a-note-is-not-needed) | Existing contract |
| AGENTS.md:97–97 | Release Notes For User-Visible Changes — CI enforces this: the "Release note gate" job in .github/workflows/ci.yml fails PRs that change runtime… | [Surfaces built from one set of notes](../architecture/release-pipeline.md#surfaces-built-from-one-set-of-notes) | Existing contract |
| AGENTS.md:98–98 | Release Notes For User-Visible Changes — The release-notes skill covers writing notes; the release-cut skill covers the full release sequence.… | [Surfaces built from one set of notes](../architecture/release-pipeline.md#surfaces-built-from-one-set-of-notes) | Existing contract |
| AGENTS.md:99–99 | Release Notes For User-Visible Changes — Validate before finishing: pnpm run release:notes:validate. | [Commands](../../.changes/README.md#commands) | Existing contract |
| AGENTS.md:100–100 | Release Notes For User-Visible Changes — Announcement drafts and highlight cards are built from the same notes: pnpm --silent run… | [Writing the body](../../.changes/README.md#writing-the-body) | Existing contract |
| AGENTS.md:101–101 | Release Notes For User-Visible Changes — Pushes to master and v can publish Docker images. A v tag build creates a draft GitHub release. | [Two phases](../architecture/release-pipeline.md#two-phases) | Existing contract |
| AGENTS.md:102–102 | Release Notes For User-Visible Changes — pnpm run release:verify:draft waits for that tag build (polling until the run is indexed, then gh run… | [Draft verification](../architecture/release-pipeline.md#draft-verification) | Existing contract |
| AGENTS.md:103–103 | Release Notes For User-Visible Changes — Publishing the GitHub release verifies its Snap assets and automatically uploads them to edge;… | [After verification](../architecture/release-pipeline.md#after-verification) | Existing contract |
| AGENTS.md:104–104 | Release Notes For User-Visible Changes — Release-post screenshots come only from the release capture script running against the mock servers. Never… | [Screenshots](../../.changes/README.md#screenshots) | Existing contract |
| AGENTS.md:105–105 | Release Notes For User-Visible Changes — Final task summaries should state whether a release note was added or why it was skipped. | [Plans and completion reports](../development/agent-workflow.md#plans-and-completion-reports) | Moved / consolidated |
| AGENTS.md:109–114 | AppImage Manager Metadata — AppManager full-download discovery uses appImage.desktop.entry URL fields. Electron Builder generates the… | [Surfaces built from one set of notes](../architecture/release-pipeline.md#surfaces-built-from-one-set-of-notes) | Existing contract |
| AGENTS.md:118–118 | Upgrade And Migration Compatibility — Users may skip releases. The application must apply all required migrations in dependency order when… | [Upgrade Compatibility And Migrations](../../libs/shared/database/README.md#upgrade-compatibility-and-migrations) | Existing contract |
| AGENTS.md:119–119 | Upgrade And Migration Compatibility — Preserve migration paths for existing persisted data. Do not make deleting a database/profile or… | [Upgrade Compatibility And Migrations](../../libs/shared/database/README.md#upgrade-compatibility-and-migrations) | Existing contract |
| AGENTS.md:120–120 | Upgrade And Migration Compatibility — Create required tables first, add missing columns before dependent indexes/triggers/queries, and make… | [Upgrade Compatibility And Migrations](../../libs/shared/database/README.md#upgrade-compatibility-and-migrations) | Existing contract |
| AGENTS.md:121–121 | Upgrade And Migration Compatibility — For persistence changes, test real SQLite initialization with representative historical schemas and data,… | [Upgrade Compatibility And Migrations](../../libs/shared/database/README.md#upgrade-compatibility-and-migrations) | Existing contract |
| AGENTS.md:122–122 | Upgrade And Migration Compatibility — See libs/shared/database/README.md for SQLite migration ownership and validation guidance. | [Upgrade Compatibility And Migrations](../../libs/shared/database/README.md#upgrade-compatibility-and-migrations) | Existing contract |
| AGENTS.md:126–126 | Regression Prevention And Test Updates — Before the final summary for any feature, behavior change, bug fix, data-flow change, Electron… | [Test impact and completion](../architecture/validation-map.md#test-impact-and-completion) | Existing contract |
| AGENTS.md:127–127 | Regression Prevention And Test Updates — Bug fixes must normally include regression coverage that fails on the old behavior and passes with the… | [Test impact and completion](../architecture/validation-map.md#test-impact-and-completion) | Existing contract |
| AGENTS.md:128–128 | Regression Prevention And Test Updates — Feature work and behavior changes must update existing tests when assertions, fixtures, mocks, routes, or… | [Test impact and completion](../architecture/validation-map.md#test-impact-and-completion) | Existing contract |
| AGENTS.md:129–133 | Regression Prevention And Test Updates — Default validation ladder: 1. Run targeted unit tests for directly affected projects with pnpm nx test… | [Test impact and completion](../architecture/validation-map.md#test-impact-and-completion) | Existing contract |
| AGENTS.md:134–134 | Regression Prevention And Test Updates — Electron-specific changes affecting IPC, SQLite, packaged runtime, external players, native file access,… | [Test impact and completion](../architecture/validation-map.md#test-impact-and-completion) | Existing contract |
| AGENTS.md:135–135 | Regression Prevention And Test Updates — Final task summaries must list tests added or updated, validation commands run with results, and any… | [Test impact and completion](../architecture/validation-map.md#test-impact-and-completion) | Existing contract |
| AGENTS.md:139–146 | Legacy Desktop Profile Migration — electron-profile-bootstrap.ts selects the known v0.19 electron-backend profile before eager main-process… | [Desktop upgrades from legacy profiles](../architecture/m3u-playlist-module.md#desktop-upgrades-from-legacy-profiles) | Existing contract |
| AGENTS.md:148–154 | Legacy Desktop Profile Migration — Startup shows AppStartupStatusComponent until the initial route and source inventory are ready, including… | [Desktop upgrades from legacy profiles](../architecture/m3u-playlist-module.md#desktop-upgrades-from-legacy-profiles) | Existing contract |
| AGENTS.md:158–158 | Electron Debugging (CDP) — Start the Electron development app with: nx serve electron-backend | [Start and attach](../development/electron-debugging.md#start-and-attach) | Moved / consolidated |
| AGENTS.md:159–159 | Electron Debugging (CDP) — Package-script equivalent: pnpm run serve:backend | [Start and attach](../development/electron-debugging.md#start-and-attach) | Moved / consolidated |
| AGENTS.md:160–160 | Electron Debugging (CDP) — Electron is configured to start with: --remote-debugging-port=9222 | [Start and attach](../development/electron-debugging.md#start-and-attach) | Moved / consolidated |
| AGENTS.md:161–161 | Electron Debugging (CDP) — Connect Chrome DevTools Protocol tools to: 127.0.0.1:9222 | [Start and attach](../development/electron-debugging.md#start-and-attach) | Moved / consolidated |
| AGENTS.md:162–162 | Electron Debugging (CDP) — For Electron automation/debugging tasks, use the electron skill | [Start and attach](../development/electron-debugging.md#start-and-attach) | Moved / consolidated |
| AGENTS.md:163–163 | Electron Debugging (CDP) — Do not auto-open DevTools during normal CDP automation. In development, DevTools is opt-in via… | [Start and attach](../development/electron-debugging.md#start-and-attach) | Moved / consolidated |
| AGENTS.md:164–164 | Electron Debugging (CDP) — If DevTools is open, agent-browser --cdp 9222 ... may attach to the DevTools page instead of the IPTVnator… | [Start and attach](../development/electron-debugging.md#start-and-attach) | Moved / consolidated |
| AGENTS.md:165–165 | Electron Debugging (CDP) — If that happens, inspect targets with curl http://127.0.0.1:9222/json/list and connect directly to the… | [Start and attach](../development/electron-debugging.md#start-and-attach) | Moved / consolidated |
| AGENTS.md:166–166 | Electron Debugging (CDP) — The app holds a single-instance lock (acquireSingleInstanceLock in… | [Start and attach](../development/electron-debugging.md#start-and-attach) | Moved / consolidated |
| AGENTS.md:170–170 | Trace / Debug Startup — Full startup tracing: | [Start and attach](../development/electron-debugging.md#start-and-attach) | Moved / consolidated |
| AGENTS.md:186–188 | Trace / Debug Startup — Settings, portal request/response, and trace payloads must use @iptvnator/shared/logging or the redacting… | [Start and attach](../development/electron-debugging.md#start-and-attach) | Moved / consolidated |
| AGENTS.md:190–190 | Trace / Debug Startup — If local Nx state gets weird before a rerun: | [Start and attach](../development/electron-debugging.md#start-and-attach) | Moved / consolidated |
| AGENTS.md:222–226 | Xtream Category Management — The Electron Live TV, Movies, and Series category dialog applies Select/Deselect to search results while a… | [Behavior Notes](../architecture/category-management.md#behavior-notes) | Existing contract |
| AGENTS.md:230–234 | XMLTV Response Compression — Electron decodes HTTP compression before the gzip file layer. For .gz/gzip metadata plus HTTP gzip, a… | [XMLTV response compression](../architecture/m3u-playlist-module.md#xmltv-response-compression) | Existing contract |
| AGENTS.md:238–256 | XMLTV Source Removal — Saving Settings → EPG reconciles cached XMLTV with committed global URLs and all enabled M3U playlist… | [XMLTV source lifecycle](../architecture/m3u-playlist-module.md#xmltv-source-lifecycle) | Existing contract |
| AGENTS.md:260–269 | Web Backend Provider Redirects — All four provider proxy routes use ValidatedHttpClient: automatic redirects are disabled, the initial URL… | [Web Backend](../architecture/pwa-self-hosted.md#web-backend) | Existing contract |
| AGENTS.md:273–278 | Portal Connectivity Preference — Half-open trial slots follow the complete request lifetime with no elapsed-time expiry. All four… | [Desktop preference and account feedback](../architecture/host-connectivity-guard.md#desktop-preference-and-account-feedback) | Existing contract |
| AGENTS.md:287–289 | Portal Connectivity Preference — Both account-info dialogs explain guard refusals with localized paused-request copy and Retry now; Stalker… | [Desktop preference and account feedback](../architecture/host-connectivity-guard.md#desktop-preference-and-account-feedback) | Existing contract |
| AGENTS.md:293–299 | Live Channel Return — Xtream and Stalker (including radio) capture displayed playback order on explicit selection. Remote… | [Live channel return and playback order](../architecture/remote-control.md#live-channel-return-and-playback-order) | Existing contract |
| AGENTS.md:303–309 | Stalker Live Search — ITV sidebar and fullscreen searches independently filter the complete selected category; only All Items… | [Full ITV Channel List Cache](../architecture/stalker-portal.md#full-itv-channel-list-cache) | Existing contract |
| AGENTS.md:313–339 | Live TV Panel Levels — Portal live layouts (Xtream live, Stalker itv/radio) fold their panels from the outside in, in three… | [Collapsible Live Sidebar](../architecture/iptvnator-ui-guidelines.md#collapsible-live-sidebar) | Existing contract |
| AGENTS.md:343–358 | Channel and Detail Keyboard Scrolling — Channel scroll owners use ChannelScrollFocusDirective; pointer selection focuses the viewport, native… | [Detail Scroll and Focus](../architecture/portal-detail-navigation.md#detail-scroll-and-focus) | Existing contract |
| AGENTS.md:362–370 | Xtream Connection Test — Add/Edit source Test HTTPS and HTTP discloses plaintext credential use before the click and can replace an… | [Explicit protocol discovery](../architecture/xtream-portal-compatibility.md#explicit-protocol-discovery) | Existing contract |
| AGENTS.md:374–382 | Xtream Live Auto Format — The routed Xtream live host supplies liveAutoTsUrl only for Auto with explicit HLS+TS account evidence,… | [Initial Auto HLS failure](../architecture/xtream-portal-compatibility.md#initial-auto-hls-failure) | Existing contract |
| AGENTS.md:386–402 | Xtream Catch-Up Server Timezone — The {Y-m-d:H-M} segment of a timeshift URL is read by the panel in ITS timezone (server_info.timezone),… | [Catch-Up Playback URLs](../architecture/xtream-portal-compatibility.md#catch-up-playback-urls) | Existing contract |
| AGENTS.md:406–406 | Radio / Audio Player — M3U playlists can contain radio channels identified by the radio="true" attribute on #EXTINF lines. When a… | [Radio audio player](../architecture/player-controls-contract.md#radio-audio-player) | Existing contract |
| AGENTS.md:408–408 | Radio / Audio Player — The dedicated AudioPlayerComponent (libs/ui/playback/src/lib/audio-player/) renders instead of a video player | [Radio audio player](../architecture/player-controls-contract.md#radio-audio-player) | Existing contract |
| AGENTS.md:409–409 | Radio / Audio Player — The audio player always uses the built-in inline player — external player settings (MPV/VLC) are ignored | [Radio audio player](../architecture/player-controls-contract.md#radio-audio-player) | Existing contract |
| AGENTS.md:410–410 | Radio / Audio Player — The EPG panel is hidden (radio streams have no EPG data) | [Radio audio player](../architecture/player-controls-contract.md#radio-audio-player) | Existing contract |
| AGENTS.md:411–411 | Radio / Audio Player — The layout uses a cinematic hero pattern: the station logo is blurred as a full-area backdrop with a… | [Radio audio player](../architecture/player-controls-contract.md#radio-audio-player) | Existing contract |
| AGENTS.md:412–412 | Radio / Audio Player — Volume is shared with the video player via localStorage key 'volume' | [Radio audio player](../architecture/player-controls-contract.md#radio-audio-player) | Existing contract |
| AGENTS.md:413–413 | Radio / Audio Player — Keyboard shortcuts: ArrowUp/ArrowDown (volume +/-5%), M (mute toggle) | [Radio audio player](../architecture/player-controls-contract.md#radio-audio-player) | Existing contract |
| AGENTS.md:414–414 | Radio / Audio Player — Radio detection in the video player template: activeChannel.radio === 'true' — this is a string… | [Radio audio player](../architecture/player-controls-contract.md#radio-audio-player) | Existing contract |
| AGENTS.md:416–416 | Radio / Audio Player — Key files: | [Radio audio player](../architecture/player-controls-contract.md#radio-audio-player) | Existing contract |
| AGENTS.md:418–418 | Radio / Audio Player — libs/ui/playback/src/lib/audio-player/audio-player.component.ts — the audio player component | [Radio audio player](../architecture/player-controls-contract.md#radio-audio-player) | Existing contract |
| AGENTS.md:438–440 | M3U URL User-Agent — PlaylistsService.getPlaylist() joins the per-playlist mutation queue so a route opened during refresh… | [User-Agent for URL sources](../architecture/m3u-playlist-module.md#user-agent-for-url-sources) | Existing contract |
| AGENTS.md:441–445 | M3U URL User-Agent — The URL import form accepts an optional User-Agent and stores it as Playlist.userAgent. Electron sends it… | [User-Agent for URL sources](../architecture/m3u-playlist-module.md#user-agent-for-url-sources) | Existing contract |
| AGENTS.md:446–448 | M3U URL User-Agent — Reuse the existing source editor and channel-over-playlist playback header precedence. Contract:… | [User-Agent for URL sources](../architecture/m3u-playlist-module.md#user-agent-for-url-sources) | Existing contract |
| AGENTS.md:452–466 | Shared Player Controls — Stream info popover: an info button in the top-right corner of the shared controls overlay shows live… | [Stream info popover](../architecture/player-controls-contract.md#stream-info-popover) | Existing contract |
| AGENTS.md:468–473 | Shared Player Controls — The Embedded MPV native-view dock follows app theme tokens as a solid app surface, including Material… | [Player And EPG Theme Boundaries](../architecture/iptvnator-ui-guidelines.md#player-and-epg-theme-boundaries) | Existing contract |
| AGENTS.md:479–494 | Shared Player Controls — The subtitle menu carries capability-gated advanced subtitle support (#1408): external subtitle file… | [Advanced subtitle support](../architecture/player-controls-contract.md#advanced-subtitle-support) | Existing contract |
| AGENTS.md:495–501 | Shared Player Controls — In fullscreen, app-player-controls shows a pointer-transparent media-title overlay at the top while… | [Fullscreen media title](../architecture/player-controls-contract.md#fullscreen-media-title) | Existing contract |
| AGENTS.md:502–524 | Shared Player Controls — Auto-hide pauses while the pointer is over the controls bar or keyboard focus is inside it, but only… | [Keyboard ownership](../architecture/player-controls-contract.md#keyboard-ownership) | Existing contract |
| AGENTS.md:525–534 | Shared Player Controls — Persisted Settings.webPlayerSharedControls is default-ON (absent stored values coerce with !== false; only… | [Current status](../architecture/player-controls-contract.md#current-status) | Added missing detail |
| AGENTS.md:535–543 | Shared Player Controls — Settings.showCaptions is deliberately outside this rollout gate: it is engine state, not controls UI.… | [Current status](../architecture/player-controls-contract.md#current-status) | Existing contract |
| AGENTS.md:544–554 | Shared Player Controls — The modes differ in how long the preference is enforced. Shared controls are authoritative for the… | [Caption preference in both modes](../architecture/player-controls-contract.md#caption-preference-in-both-modes) | Existing contract |
| AGENTS.md:555–563 | Shared Player Controls — Shared controls include a per-session quality menu (Auto + "1080p"-style levels via setQualityLevel;… | [Quality (bitrate/level) selection](../architecture/player-controls-contract.md#quality-bitratelevel-selection) | Existing contract |
| AGENTS.md:564–568 | Shared Player Controls — Embedded MPV ignores the web-player preference. Frame-copy always uses shared DOM controls through its… | [Embedded MPV rendering constraints](../architecture/player-controls-contract.md#embedded-mpv-rendering-constraints) | Existing contract |
| AGENTS.md:569–576 | Shared Player Controls — Frame-copy shared controls own DOM surface interactions, shortcuts, fullscreen, and recording feedback.… | [Embedded MPV rendering constraints](../architecture/player-controls-contract.md#embedded-mpv-rendering-constraints) | Existing contract |
| AGENTS.md:661–670 | Shared Player Controls — Embedded MPV seek steps (arrow keys, ±10 s buttons, PlayerController.seekBy) go through the relative… | [Resume And Track Handling](../architecture/embedded-mpv-native.md#resume-and-track-handling) | Existing contract |
| AGENTS.md:671–676 | Shared Player Controls — M3U Favorites and Recently Viewed resolve Channel.drm into ResolvedPortalPlayback.drm through… | [DASH + ClearKey Playback](../architecture/m3u-playlist-module.md#dash--clearkey-playback) | Existing contract |
| AGENTS.md:677–694 | Shared Player Controls — DASH (.mpd) sources play through a lazily imported Shaka Player source engine… | [DASH + ClearKey Playback](../architecture/m3u-playlist-module.md#dash--clearkey-playback) | Existing contract |
| AGENTS.md:695–701 | Shared Player Controls — mpegts.js 1.8.1 errors from HTML5, Video.js, and ArtPlayer cross one version-locked structured evidence… | [Codec And Container Diagnostics](../architecture/embedded-inline-playback.md#codec-and-container-diagnostics) | Existing contract |
| AGENTS.md:702–834 | Shared Player Controls — Browser playback diagnostics and recovery policy live in libs/playback/util and are exported by… | [Codec And Container Diagnostics](../architecture/embedded-inline-playback.md#codec-and-container-diagnostics) | Existing contract |
| AGENTS.md:835–852 | Shared Player Controls — The built-in HTML5/hls.js player is the second guarded consumer. HtmlVideoPlayerComponent provides a… | [Web adapter and web-engine bridges](../architecture/player-controls-contract.md#web-adapter-and-web-engine-bridges) | Existing contract |
| AGENTS.md:853–886 | Shared Player Controls — Video.js is the third guarded consumer. VjsPlayerComponent provides a component-scoped… | [Web adapter and web-engine bridges](../architecture/player-controls-contract.md#web-adapter-and-web-engine-bridges) | Existing contract |
| AGENTS.md:887–904 | Shared Player Controls — ArtPlayer is the fourth guarded consumer. ArtPlayerComponent provides a component-scoped… | [Web adapter and web-engine bridges](../architecture/player-controls-contract.md#web-adapter-and-web-engine-bridges) | Existing contract |
| AGENTS.md:905–914 | Shared Player Controls — Shared web picture-in-picture stays inside that default-on rollout. PlayerController exposes capability… | [Standard element picture-in-picture](../architecture/player-controls-contract.md#standard-element-picture-in-picture) | Existing contract |
| AGENTS.md:915–933 | Shared Player Controls — WebVideoControlsAdapter supplies its current video and binding generation to… | [Standard element picture-in-picture](../architecture/player-controls-contract.md#standard-element-picture-in-picture) | Existing contract |
| AGENTS.md:934–935 | Shared Player Controls — Canonical docs: docs/architecture/player-controls-contract.md and docs/architecture/embedded-mpv-native.md | [Web adapter and web-engine bridges](../architecture/player-controls-contract.md#web-adapter-and-web-engine-bridges) | Existing contract |
| AGENTS.md:939–946 | Display Sleep During Playback — PlaybackKeepAwakeService (apps/web/src/app/services/playback-keep-awake.service.ts) watches every <video>… | [Display sleep during playback](../architecture/player-controls-contract.md#display-sleep-during-playback) | Added missing detail |
| AGENTS.md:947–953 | Display Sleep During Playback — Electron: a main-process powerSaveBlocker behind window.electron.setPlaybackKeepAwake… | [Display sleep during playback](../architecture/player-controls-contract.md#display-sleep-during-playback) | Added missing detail |
| AGENTS.md:954–956 | Display Sleep During Playback — Radio's <audio> deliberately never blocks display sleep. Embedded MPV holds its own blocker in… | [Display sleep during playback](../architecture/player-controls-contract.md#display-sleep-during-playback) | Added missing detail |
| AGENTS.md:960–962 | Windows Embedded MPV Pin Maintenance — PR, master, and tag builds resolve the Windows runtime only from… | [Windows CI pin lifecycle](../../tools/embedded-mpv/README.md#windows-ci-pin-lifecycle) | Existing contract |
| AGENTS.md:963–964 | Windows Embedded MPV Pin Maintenance — Validate the checked-in schema and provenance with pnpm embedded-mpv:windows-runtime-pin:check. | [Windows CI pin lifecycle](../../tools/embedded-mpv/README.md#windows-ci-pin-lifecycle) | Existing contract |
| AGENTS.md:965–968 | Windows Embedded MPV Pin Maintenance — Prepare a manual rotation with pnpm embedded-mpv:windows-runtime-pin:refresh -- --force. The weekly… | [Windows CI pin lifecycle](../../tools/embedded-mpv/README.md#windows-ci-pin-lifecycle) | Existing contract |
| AGENTS.md:969–972 | Windows Embedded MPV Pin Maintenance — The PAT-backed refresh job must keep every third-party action pinned to a full commit. Do not mirror the… | [Windows CI pin lifecycle](../../tools/embedded-mpv/README.md#windows-ci-pin-lifecycle) | Added missing detail |
| AGENTS.md:976–979 | Linux Embedded MPV Packaging — Official Linux frame-copy artifacts are x64-only. AppImage, DEB, RPM, Pacman, Snap, and Flatpak are… | [Linux Support Matrix](../architecture/embedded-mpv-native.md#linux-support-matrix) | Existing contract |
| AGENTS.md:980–986 | Linux Embedded MPV Packaging — Packaging runs three isolated profiles: - system: DEB/RPM/Pacman, no private native/lib, with package… | [Linux Support Matrix](../architecture/embedded-mpv-native.md#linux-support-matrix) | Existing contract |
| AGENTS.md:987–990 | Linux Embedded MPV Packaging — Flatpak is an isolated packaging pass and keeps iptvnator as the real Electron ELF so Electron Builder's… | [Linux Support Matrix](../architecture/embedded-mpv-native.md#linux-support-matrix) | Existing contract |
| AGENTS.md:991–993 | Linux Embedded MPV Packaging — The DEB system-runtime contract is Ubuntu 24.04+ (libmpv2). Ubuntu 22.04 provides libmpv1, so use the x64… | [Linux Support Matrix](../architecture/embedded-mpv-native.md#linux-support-matrix) | Existing contract |
| AGENTS.md:994–997 | Linux Embedded MPV Packaging — Only iptvnator_mpv_helper may link libmpv. The Electron executable, Electron libraries, embedded_mpv.node,… | [Linux Support Matrix](../architecture/embedded-mpv-native.md#linux-support-matrix) | Existing contract |
| AGENTS.md:998–1002 | Linux Embedded MPV Packaging — electron-backend/native{,//} is excluded from app.asar; afterPack exclusively writes the… | [Linux Support Matrix](../architecture/embedded-mpv-native.md#linux-support-matrix) | Existing contract |
| AGENTS.md:1003–1005 | Linux Embedded MPV Packaging — Packaged addon, frame-reader, and helper discovery is package-owned app.asar.unpacked only. Writable… | [Linux Support Matrix](../architecture/embedded-mpv-native.md#linux-support-matrix) | Existing contract |
| AGENTS.md:1006–1010 | Linux Embedded MPV Packaging — Pristine afterPack/unpacked layouts scan Electron libraries recursively. Extracted Snap payloads exclude… | [Linux Support Matrix](../architecture/embedded-mpv-native.md#linux-support-matrix) | Existing contract |
| AGENTS.md:1011–1015 | Linux Embedded MPV Packaging — Linux frame-copy availability is fail-closed. The packaged manifest, artifact modes, declared bundled… | [Linux Support Matrix](../architecture/embedded-mpv-native.md#linux-support-matrix) | Existing contract |
| AGENTS.md:1016–1027 | Linux Embedded MPV Packaging — Snap is core22/strict and uses an exact private shared-memory plug plus the graphics-core22 content plug… | [Frame-Copy Engine (Experimental, Apple Silicon, Linux and Windows)](../architecture/embedded-mpv-native.md#frame-copy-engine-experimental-apple-silicon-linux-and-windows) | Existing contract |
| AGENTS.md:1028–1054 | Linux Embedded MPV Packaging — The probe and playback helper share one sanitized loader environment: ambient audit, preload, library,… | [Frame-Copy Engine (Experimental, Apple Silicon, Linux and Windows)](../architecture/embedded-mpv-native.md#frame-copy-engine-experimental-apple-silicon-linux-and-windows) | Existing contract |
| AGENTS.md:1055–1059 | Linux Embedded MPV Packaging — In the exact packaged Flatpak /app context, reconstruct only Freedesktop Platform 24.08's immutable… | [Frame-Copy Engine (Experimental, Apple Silicon, Linux and Windows)](../architecture/embedded-mpv-native.md#frame-copy-engine-experimental-apple-silicon-linux-and-windows) | Existing contract |
| AGENTS.md:1060–1063 | Linux Embedded MPV Packaging — The packaged x64 Playwright smoke runs its fixture-contract target first and passes Chromium… | [Same-Version Desktop Release Gate](../architecture/embedded-mpv-native.md#same-version-desktop-release-gate) | Existing contract |
| AGENTS.md:1064–1116 | Linux Embedded MPV Packaging — Bundled Linux releases must publish the exact source archives/git records, checksums, licenses, flags,… | [Same-Version Desktop Release Gate](../architecture/embedded-mpv-native.md#same-version-desktop-release-gate) | Existing contract |
| AGENTS.md:1129–1130 | Repo Skills — Descriptions and trigger conditions are canonical in each skill's frontmatter; do not duplicate them here. | [Repository skills](../development/agent-workflow.md#repository-skills) | Moved / consolidated |
| AGENTS.md:1137–1137 | General Guidelines for working with Nx — For navigating/exploring the workspace, invoke the nx-workspace skill first when it is available - it has… | [General Guidelines for working with Nx](../../AGENTS.md#general-guidelines-for-working-with-nx) | Retained; tools conditional |
| AGENTS.md:1138–1138 | General Guidelines for working with Nx — When running tasks (for example build, lint, test, e2e, etc.), always prefer running the task through nx… | [General Guidelines for working with Nx](../../AGENTS.md#general-guidelines-for-working-with-nx) | Retained; tools conditional |
| AGENTS.md:1139–1139 | General Guidelines for working with Nx — Prefix nx commands with the workspace's package manager (e.g., pnpm nx build, npm exec nx test) - avoids… | [General Guidelines for working with Nx](../../AGENTS.md#general-guidelines-for-working-with-nx) | Retained; tools conditional |
| AGENTS.md:1140–1140 | General Guidelines for working with Nx — You have access to the Nx MCP server and its tools, use them to help the user | [General Guidelines for working with Nx](../../AGENTS.md#general-guidelines-for-working-with-nx) | Retained; tools conditional |
| AGENTS.md:1141–1141 | General Guidelines for working with Nx — For Nx plugin best practices, check node_modules/@nx/<plugin>/PLUGIN.md. Not all plugins have this file -… | [General Guidelines for working with Nx](../../AGENTS.md#general-guidelines-for-working-with-nx) | Retained; tools conditional |
| AGENTS.md:1142–1142 | General Guidelines for working with Nx — NEVER guess CLI flags - always check nx_docs or --help first when unsure | [General Guidelines for working with Nx](../../AGENTS.md#general-guidelines-for-working-with-nx) | Retained; tools conditional |
| AGENTS.md:1146–1146 | Scaffolding & Generators — For scaffolding tasks (creating apps, libs, project structure, setup), ALWAYS invoke the nx-generate skill… | [General Guidelines for working with Nx](../../AGENTS.md#general-guidelines-for-working-with-nx) | Retained; tools conditional |
| AGENTS.md:1150–1150 | When to use nx_docs — USE for: advanced config options, unfamiliar flags, migration guides, plugin configuration, edge cases | [General Guidelines for working with Nx](../../AGENTS.md#general-guidelines-for-working-with-nx) | Retained; tools conditional |
| AGENTS.md:1151–1151 | When to use nx_docs — DON'T USE for: basic generator syntax (nx g @nx/react:app), standard commands, things you already know | [General Guidelines for working with Nx](../../AGENTS.md#general-guidelines-for-working-with-nx) | Retained; tools conditional |
| AGENTS.md:1152–1152 | When to use nx_docs — The nx-generate skill handles generator discovery internally - don't call nx_docs just to look up… | [General Guidelines for working with Nx](../../AGENTS.md#general-guidelines-for-working-with-nx) | Retained; tools conditional |
| AGENTS.md:1207–1213 | Desktop Source Health — Desktop Sources also offers library-wide selective cleanup through dialog-scoped SourceCleanupService.… | [Desktop inactive-source cleanup](../architecture/m3u-playlist-module.md#desktop-inactive-source-cleanup) | Existing contract |
| AGENTS.md:1215–1217 | Desktop Source Health — Startup source auto-refresh uses SourceActivityService to protect busy IDs from cleanup. Late batch… | [Desktop inactive-source cleanup](../architecture/m3u-playlist-module.md#desktop-inactive-source-cleanup) | Existing contract |
| CLAUDE.md:3–3 | CLAUDE.md — This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. | [Maintaining canonical knowledge](../development/agent-workflow.md#maintaining-canonical-knowledge) | Moved / consolidated |
| CLAUDE.md:5–5 | CLAUDE.md — > The process sections below (Plan Mode, Documentation After Changes, Upgrade And Migration Compatibility,… | [Maintaining canonical knowledge](../development/agent-workflow.md#maintaining-canonical-knowledge) | Moved / consolidated |
| CLAUDE.md:9–9 | Plan Mode — When Claude Code is in Plan Mode and produces a final <proposed_plan>, it must also save that finalized… | [Maintaining canonical knowledge](../development/agent-workflow.md#maintaining-canonical-knowledge) | Moved / consolidated |
| CLAUDE.md:10–10 | Plan Mode — Save only finalized plans. Do not write interim exploration, question turns, or draft revisions to .plans/. | [Maintaining canonical knowledge](../development/agent-workflow.md#maintaining-canonical-knowledge) | Moved / consolidated |
| CLAUDE.md:11–11 | Plan Mode — Use the filename pattern YYYY-MM-DD-short-topic.md such as .plans/2026-03-12-channel-filtering.md. | [Maintaining canonical knowledge](../development/agent-workflow.md#maintaining-canonical-knowledge) | Moved / consolidated |
| CLAUDE.md:12–12 | Plan Mode — If the intended filename already exists, append a numeric suffix such as -2, -3, and so on. | [Maintaining canonical knowledge](../development/agent-workflow.md#maintaining-canonical-knowledge) | Moved / consolidated |
| CLAUDE.md:16–16 | Documentation After Changes — After implementing a meaningful change, Claude Code must assess whether canonical repo docs need updates… | [Maintaining canonical knowledge](../development/agent-workflow.md#maintaining-canonical-knowledge) | Moved / consolidated |
| CLAUDE.md:17–17 | Documentation After Changes — Meaningful changes include new or changed user-visible behavior, architecture or data-flow changes,… | [Maintaining canonical knowledge](../development/agent-workflow.md#maintaining-canonical-knowledge) | Moved / consolidated |
| CLAUDE.md:18–18 | Documentation After Changes — Skip doc updates for trivial refactors with unchanged behavior, formatting-only edits, and isolated… | [Maintaining canonical knowledge](../development/agent-workflow.md#maintaining-canonical-knowledge) | Moved / consolidated |
| CLAUDE.md:19–22 | Documentation After Changes — Prefer updating an existing authoritative doc before creating a new one: 1. README.md for top-level… | [Maintaining canonical knowledge](../development/agent-workflow.md#maintaining-canonical-knowledge) | Moved / consolidated |
| CLAUDE.md:23–23 | Documentation After Changes — Keep this file (CLAUDE.md) itself up to date. It is a living document: whenever a change touches something… | [Maintaining canonical knowledge](../development/agent-workflow.md#maintaining-canonical-knowledge) | Moved / consolidated |
| CLAUDE.md:24–24 | Documentation After Changes — When adding a new feature area, check whether the Architecture or Key Features sections of CLAUDE.md… | [Maintaining canonical knowledge](../development/agent-workflow.md#maintaining-canonical-knowledge) | Moved / consolidated |
| CLAUDE.md:25–25 | Documentation After Changes — Do not let CLAUDE.md drift: a stale path or route in this file poisons the context of every future agent… | [Maintaining canonical knowledge](../development/agent-workflow.md#maintaining-canonical-knowledge) | Moved / consolidated |
| CLAUDE.md:26–26 | Documentation After Changes — Repo docs are canonical even when they were originally drafted by an LLM. | [Maintaining canonical knowledge](../development/agent-workflow.md#maintaining-canonical-knowledge) | Moved / consolidated |
| CLAUDE.md:27–27 | Documentation After Changes — Final task summaries should state whether docs were updated and which doc changed. | [Maintaining canonical knowledge](../development/agent-workflow.md#maintaining-canonical-knowledge) | Moved / consolidated |
| CLAUDE.md:31–31 | Release Notes For User-Visible Changes — Any change a user could notice — new behavior, changed behavior, bug fix, performance win, breaking change… | [File](../../.changes/README.md#file) | Existing contract |
| CLAUDE.md:32–32 | Release Notes For User-Visible Changes — Name it <area>-<short-slug>.md; area matches the conventional-commit scope. There is no version field —… | [File](../../.changes/README.md#file) | Existing contract |
| CLAUDE.md:33–33 | Release Notes For User-Visible Changes — Write the body for a user, not a reviewer: "the player now remembers volume between episodes", not "hoist… | [Writing the body](../../.changes/README.md#writing-the-body) | Existing contract |
| CLAUDE.md:34–34 | Release Notes For User-Visible Changes — type: internal records invisible maintenance. Internal notes stay collapsed in CHANGELOG.md, are omitted… | [Writing the body](../../.changes/README.md#writing-the-body) | Existing contract |
| CLAUDE.md:35–35 | Release Notes For User-Visible Changes — highlight: <short headline> (max 60 characters, rejected on type: internal) marks a note as one of the… | [Writing the body](../../.changes/README.md#writing-the-body) | Existing contract |
| CLAUDE.md:36–36 | Release Notes For User-Visible Changes — Skip the note for test-only changes, docs, CI/workflow plumbing, and pure refactors with no behavior… | [When a note is not needed](../../.changes/README.md#when-a-note-is-not-needed) | Existing contract |
| CLAUDE.md:37–37 | Release Notes For User-Visible Changes — CI enforces this: the "Release note gate" job in .github/workflows/ci.yml fails PRs that change runtime… | [Surfaces built from one set of notes](../architecture/release-pipeline.md#surfaces-built-from-one-set-of-notes) | Existing contract |
| CLAUDE.md:38–38 | Release Notes For User-Visible Changes — The release-notes skill covers writing notes; the release-cut skill covers the full release sequence.… | [Surfaces built from one set of notes](../architecture/release-pipeline.md#surfaces-built-from-one-set-of-notes) | Existing contract |
| CLAUDE.md:39–39 | Release Notes For User-Visible Changes — Validate before finishing: pnpm run release:notes:validate. | [Commands](../../.changes/README.md#commands) | Existing contract |
| CLAUDE.md:40–40 | Release Notes For User-Visible Changes — Announcement drafts and highlight cards are built from the same notes: pnpm --silent run… | [Writing the body](../../.changes/README.md#writing-the-body) | Existing contract |
| CLAUDE.md:41–41 | Release Notes For User-Visible Changes — Pushes to master and v can publish Docker images. A v tag build creates a draft GitHub release. | [Two phases](../architecture/release-pipeline.md#two-phases) | Existing contract |
| CLAUDE.md:42–42 | Release Notes For User-Visible Changes — pnpm run release:verify:draft waits for that tag build (polling until the run is indexed, then gh run… | [Draft verification](../architecture/release-pipeline.md#draft-verification) | Existing contract |
| CLAUDE.md:43–43 | Release Notes For User-Visible Changes — Publishing the GitHub release verifies its Snap assets and automatically uploads them to edge;… | [After verification](../architecture/release-pipeline.md#after-verification) | Existing contract |
| CLAUDE.md:44–44 | Release Notes For User-Visible Changes — Release-post screenshots come only from the release capture script running against the mock servers. Never… | [Screenshots](../../.changes/README.md#screenshots) | Existing contract |
| CLAUDE.md:45–45 | Release Notes For User-Visible Changes — Final task summaries should state whether a release note was added or why it was skipped. | [Plans and completion reports](../development/agent-workflow.md#plans-and-completion-reports) | Moved / consolidated |
| CLAUDE.md:49–54 | AppImage Manager Metadata — AppManager full-download discovery uses appImage.desktop.entry URL fields. Electron Builder generates the… | [Surfaces built from one set of notes](../architecture/release-pipeline.md#surfaces-built-from-one-set-of-notes) | Existing contract |
| CLAUDE.md:58–58 | Upgrade And Migration Compatibility — Users may skip releases. The application must apply all required migrations in dependency order when… | [Upgrade Compatibility And Migrations](../../libs/shared/database/README.md#upgrade-compatibility-and-migrations) | Existing contract |
| CLAUDE.md:59–59 | Upgrade And Migration Compatibility — Preserve migration paths for existing persisted data. Do not make deleting a database/profile or… | [Upgrade Compatibility And Migrations](../../libs/shared/database/README.md#upgrade-compatibility-and-migrations) | Existing contract |
| CLAUDE.md:60–60 | Upgrade And Migration Compatibility — Create required tables first, add missing columns before dependent indexes/triggers/queries, and make… | [Upgrade Compatibility And Migrations](../../libs/shared/database/README.md#upgrade-compatibility-and-migrations) | Existing contract |
| CLAUDE.md:61–61 | Upgrade And Migration Compatibility — For persistence changes, test real SQLite initialization with representative historical schemas and data,… | [Upgrade Compatibility And Migrations](../../libs/shared/database/README.md#upgrade-compatibility-and-migrations) | Existing contract |
| CLAUDE.md:62–62 | Upgrade And Migration Compatibility — See libs/shared/database/README.md for SQLite migration ownership and validation guidance. | [Upgrade Compatibility And Migrations](../../libs/shared/database/README.md#upgrade-compatibility-and-migrations) | Existing contract |
| CLAUDE.md:66–66 | Regression Prevention And Test Updates — Before the final summary for any feature, behavior change, bug fix, data-flow change, Electron… | [Test impact and completion](../architecture/validation-map.md#test-impact-and-completion) | Existing contract |
| CLAUDE.md:67–67 | Regression Prevention And Test Updates — Bug fixes must normally include regression coverage that fails on the old behavior and passes with the… | [Test impact and completion](../architecture/validation-map.md#test-impact-and-completion) | Existing contract |
| CLAUDE.md:68–68 | Regression Prevention And Test Updates — Feature work and behavior changes must update existing tests when assertions, fixtures, mocks, routes, or… | [Test impact and completion](../architecture/validation-map.md#test-impact-and-completion) | Existing contract |
| CLAUDE.md:69–73 | Regression Prevention And Test Updates — Default validation ladder: 1. Run targeted unit tests for directly affected projects with pnpm nx test… | [Test impact and completion](../architecture/validation-map.md#test-impact-and-completion) | Existing contract |
| CLAUDE.md:74–74 | Regression Prevention And Test Updates — Electron-specific changes affecting IPC, SQLite, packaged runtime, external players, native file access,… | [Test impact and completion](../architecture/validation-map.md#test-impact-and-completion) | Existing contract |
| CLAUDE.md:75–75 | Regression Prevention And Test Updates — Final task summaries must list tests added or updated, validation commands run with results, and any… | [Test impact and completion](../architecture/validation-map.md#test-impact-and-completion) | Existing contract |
| CLAUDE.md:79–79 | Project Overview — IPTVnator is a cross-platform IPTV player application built with Angular and Electron, supporting M3U/M3U8… | [Service factory and build bases](../architecture/pwa-self-hosted.md#service-factory-and-build-bases) | Existing contract |
| CLAUDE.md:81–81 | Project Overview — Dual Environment Support: The application is designed to work in both Electron and as a Progressive Web… | [Service factory and build bases](../architecture/pwa-self-hosted.md#service-factory-and-build-bases) | Existing contract |
| CLAUDE.md:92–92 | Agent Bootstrap — Run the install step in a fresh worktree before relying on Nx discovery, lint, test, or build commands.… | [Fresh Worktree Bootstrap and Discovery](../architecture/nx-workspace-boundaries.md#fresh-worktree-bootstrap-and-discovery) | Existing contract |
| CLAUDE.md:93–93 | Agent Bootstrap — Re-run the install whenever the checkout moves — git pull, git reset --hard, a rebase, or a worktree… | [Fresh Worktree Bootstrap and Discovery](../architecture/nx-workspace-boundaries.md#fresh-worktree-bootstrap-and-discovery) | Existing contract |
| CLAUDE.md:94–94 | Agent Bootstrap — Never run prettier --write on CLAUDE.md, AGENTS.md or docs/. These files are not Prettier-clean upstream,… | [Protected Markdown edits](../development/agent-workflow.md#protected-markdown-edits) | Corrected safe restore |
| CLAUDE.md:95–95 | Agent Bootstrap — Use scoped path aliases from tsconfig.base.json such as @iptvnator/services, @iptvnator/shared/interfaces,… | [Import Aliases and Public APIs](../architecture/nx-workspace-boundaries.md#import-aliases-and-public-apis) | Existing contract |
| CLAUDE.md:96–96 | Agent Bootstrap — Do not add new imports from legacy bare aliases such as services, shared-interfaces, components,… | [Import Aliases and Public APIs](../architecture/nx-workspace-boundaries.md#import-aliases-and-public-apis) | Existing contract |
| CLAUDE.md:97–97 | Agent Bootstrap — Every Nx project should keep scope:, domain:, and type: tags in project.json. | [Project Tags](../architecture/nx-workspace-boundaries.md#project-tags) | Existing contract |
| CLAUDE.md:98–98 | Agent Bootstrap — See docs/architecture/nx-workspace-boundaries.md for the current Nx tag and alias policy. | [Import Aliases and Public APIs](../architecture/nx-workspace-boundaries.md#import-aliases-and-public-apis) | Existing contract |
| CLAUDE.md:99–100 | Agent Bootstrap — Keep nx and every official @nx/ package on the same exact version; run pnpm run deps:nx:validate after… | [Nx Dependency Updates](../architecture/nx-workspace-boundaries.md#nx-dependency-updates) | Existing contract |
| CLAUDE.md:101–102 | Agent Bootstrap — Use the Node version in .nvmrc for development and CI. Angular 22 requires Node ^22.22.3 || ^24.15.0 and… | [Angular 22 Toolchain Compatibility](../architecture/nx-workspace-boundaries.md#angular-22-toolchain-compatibility) | Existing contract |
| CLAUDE.md:103–107 | Agent Bootstrap — Vite 8.1.5, resolved through Angular's build tooling, retains upstream precise matchers and adds bounded… | [Vite Dev-Server Patch](../architecture/nx-workspace-boundaries.md#vite-dev-server-patch) | Existing contract |
| CLAUDE.md:119–125 | Agent Bootstrap — node-gyp is a declared root devDependency because apps/electron-backend/build-embedded-mpv.js resolves it… | [Packaging State](../architecture/embedded-mpv-native.md#packaging-state) | Existing contract |
| CLAUDE.md:126–130 | Agent Bootstrap — nx-electron@22.0.0 uses a local Nx 23 export-path patch and an explicit webpack-node-externals package… | [Angular 22 Toolchain Compatibility](../architecture/nx-workspace-boundaries.md#angular-22-toolchain-compatibility) | Existing contract |
| CLAUDE.md:131–137 | Agent Bootstrap — A directory holding files consumed by other projects must be an Nx project. Nx builds its graph from… | [Shared Stylesheets and Cache Inputs](../architecture/nx-workspace-boundaries.md#shared-stylesheets-and-cache-inputs) | Existing contract |
| CLAUDE.md:138–141 | Agent Bootstrap — Update Nx with pnpm nx migrate nx@<target> --skipInstall, regenerate the lockfile, run generated… | [Nx Dependency Updates](../architecture/nx-workspace-boundaries.md#nx-dependency-updates) | Existing contract |
| CLAUDE.md:142–142 | Agent Bootstrap — Repository-specific skills live under .codex/skills/. | [Repository skills](../development/agent-workflow.md#repository-skills) | Moved / consolidated |
| CLAUDE.md:143–144 | Agent Bootstrap — Frontmatter descriptions are trigger-only and begin with Use when; keep each skill at or below 500 words. | [Repository skills](../development/agent-workflow.md#repository-skills) | Moved / consolidated |
| CLAUDE.md:145–146 | Agent Bootstrap — Run pnpm run skills:validate after editing a committed skill or a literal path it documents. | [Repository skills](../development/agent-workflow.md#repository-skills) | Moved / consolidated |
| CLAUDE.md:147–148 | Agent Bootstrap — Keep .codex and .claude copies of release-notes and release-cut byte-identical. | [Repository skills](../development/agent-workflow.md#repository-skills) | Moved / consolidated |
| CLAUDE.md:152–192 | Building and Serving — bash # Serve the Angular web app only (development mode, baseHref="/") pnpm run serve:frontend # or nx… | [Build and serve commands](../development/agent-workflow.md#build-and-serve-commands) | Moved / consolidated |
| CLAUDE.md:196–198 | Windows Embedded MPV Pin Maintenance — PR, master, and tag builds resolve the Windows runtime only from… | [Windows CI pin lifecycle](../../tools/embedded-mpv/README.md#windows-ci-pin-lifecycle) | Existing contract |
| CLAUDE.md:199–200 | Windows Embedded MPV Pin Maintenance — Validate the checked-in schema and provenance with pnpm embedded-mpv:windows-runtime-pin:check. | [Windows CI pin lifecycle](../../tools/embedded-mpv/README.md#windows-ci-pin-lifecycle) | Existing contract |
| CLAUDE.md:201–204 | Windows Embedded MPV Pin Maintenance — Prepare a manual rotation with pnpm embedded-mpv:windows-runtime-pin:refresh -- --force. The weekly… | [Windows CI pin lifecycle](../../tools/embedded-mpv/README.md#windows-ci-pin-lifecycle) | Existing contract |
| CLAUDE.md:205–208 | Windows Embedded MPV Pin Maintenance — The PAT-backed refresh job must keep every third-party action pinned to a full commit. Do not mirror the… | [Windows CI pin lifecycle](../../tools/embedded-mpv/README.md#windows-ci-pin-lifecycle) | Existing contract |
| CLAUDE.md:212–212 | Electron CDP Debugging — Start Electron in dev mode with: nx serve electron-backend | [Start and attach](../development/electron-debugging.md#start-and-attach) | Moved / consolidated |
| CLAUDE.md:213–213 | Electron CDP Debugging — Package-script equivalent: pnpm run serve:backend | [Start and attach](../development/electron-debugging.md#start-and-attach) | Moved / consolidated |
| CLAUDE.md:214–214 | Electron CDP Debugging — The workspace is configured to always launch Electron with: --remote-debugging-port=9222 | [Start and attach](../development/electron-debugging.md#start-and-attach) | Moved / consolidated |
| CLAUDE.md:215–215 | Electron CDP Debugging — Use CDP clients (Chrome DevTools Protocol tools) against: 127.0.0.1:9222 | [Start and attach](../development/electron-debugging.md#start-and-attach) | Moved / consolidated |
| CLAUDE.md:216–216 | Electron CDP Debugging — When the task is Electron automation/debugging, use the electron skill | [Start and attach](../development/electron-debugging.md#start-and-attach) | Moved / consolidated |
| CLAUDE.md:217–217 | Electron CDP Debugging — Do not auto-open DevTools during normal CDP automation. In development, DevTools is opt-in via… | [Start and attach](../development/electron-debugging.md#start-and-attach) | Moved / consolidated |
| CLAUDE.md:218–218 | Electron CDP Debugging — If DevTools is open, agent-browser --cdp 9222 ... may attach to the DevTools page instead of the IPTVnator… | [Start and attach](../development/electron-debugging.md#start-and-attach) | Moved / consolidated |
| CLAUDE.md:219–219 | Electron CDP Debugging — The app holds a single-instance lock (acquireSingleInstanceLock in… | [Start and attach](../development/electron-debugging.md#start-and-attach) | Moved / consolidated |
| CLAUDE.md:221–221 | Electron CDP Debugging — For startup tracing or white-screen debugging: | [Start and attach](../development/electron-debugging.md#start-and-attach) | Moved / consolidated |
| CLAUDE.md:223–225 | Electron CDP Debugging — bash IPTVNATOR_TRACE_STARTUP=1 nx serve electron-backend | [Start and attach](../development/electron-debugging.md#start-and-attach) | Moved / consolidated |
| CLAUDE.md:227–227 | Electron CDP Debugging — Useful narrower flags: | [Start and attach](../development/electron-debugging.md#start-and-attach) | Moved / consolidated |
| CLAUDE.md:229–229 | Electron CDP Debugging — IPTVNATOR_TRACE_IPC=1 traces renderer window.electron. bridge calls | [Start and attach](../development/electron-debugging.md#start-and-attach) | Moved / consolidated |
| CLAUDE.md:230–230 | Electron CDP Debugging — IPTVNATOR_TRACE_DB=1 traces DB worker requests and DB progress events | [Start and attach](../development/electron-debugging.md#start-and-attach) | Moved / consolidated |
| CLAUDE.md:231–231 | Electron CDP Debugging — IPTVNATOR_TRACE_SQL=1 traces SQLite statements in both main and worker connections | [Start and attach](../development/electron-debugging.md#start-and-attach) | Moved / consolidated |
| CLAUDE.md:232–232 | Electron CDP Debugging — IPTVNATOR_TRACE_WINDOW=1 traces BrowserWindow navigation/load lifecycle | [Start and attach](../development/electron-debugging.md#start-and-attach) | Moved / consolidated |
| CLAUDE.md:233–233 | Electron CDP Debugging — IPTVNATOR_TRACE_PLAYER=1 traces external-player activity, bounded Embedded MPV runtime-probe stderr, and… | [Start and attach](../development/electron-debugging.md#start-and-attach) | Moved / consolidated |
| CLAUDE.md:234–234 | Electron CDP Debugging — IPTVNATOR_TRACE_RENDERER_CONSOLE=1 mirrors renderer console logs into the Electron terminal | [Start and attach](../development/electron-debugging.md#start-and-attach) | Moved / consolidated |
| CLAUDE.md:235–235 | Electron CDP Debugging — IPTVNATOR_PERF_CAPTURE=1 enables development/test-only, redacted M3U and Xtream preload IPC… | [Start and attach](../development/electron-debugging.md#start-and-attach) | Moved / consolidated |
| CLAUDE.md:236–236 | Electron CDP Debugging — IPTVNATOR_PERF_WORKER_PROFILING=1 enables development/test-only, request-scoped worker… | [Start and attach](../development/electron-debugging.md#start-and-attach) | Moved / consolidated |
| CLAUDE.md:238–240 | Electron CDP Debugging — Settings, portal request/response, and trace payloads must use @iptvnator/shared/logging or the redacting… | [Start and attach](../development/electron-debugging.md#start-and-attach) | Moved / consolidated |
| CLAUDE.md:242–242 | Electron CDP Debugging — If the Nx daemon gets into a bad state before rerunning Electron: | [Start and attach](../development/electron-debugging.md#start-and-attach) | Moved / consolidated |
| CLAUDE.md:244–246 | Electron CDP Debugging — bash pnpm nx reset | [Start and attach](../development/electron-debugging.md#start-and-attach) | Moved / consolidated |
| CLAUDE.md:248–248 | Electron CDP Debugging — Use global agent-browser (preferred): | [Start and attach](../development/electron-debugging.md#start-and-attach) | Moved / consolidated |
| CLAUDE.md:250–263 | Electron CDP Debugging — bash # Verify CDP targets agent-browser --cdp 9222 tab list # Switch to the app tab and inspect… | [Start and attach](../development/electron-debugging.md#start-and-attach) | Moved / consolidated |
| CLAUDE.md:265–265 | Electron CDP Debugging — If agent-browser is not in PATH, use: | [Start and attach](../development/electron-debugging.md#start-and-attach) | Moved / consolidated |
| CLAUDE.md:267–269 | Electron CDP Debugging — bash npx --yes agent-browser --cdp 9222 tab list | [Start and attach](../development/electron-debugging.md#start-and-attach) | Moved / consolidated |
| CLAUDE.md:273–294 | Testing — bash # Run frontend tests pnpm run test:frontend # or pnpm nx test web # Run backend tests pnpm run… | [Unit And Type Checks](../architecture/validation-map.md#unit-and-type-checks) | Existing contract |
| CLAUDE.md:296–296 | Testing — Before finishing behavior changes or bug fixes, follow Regression Prevention And Test Updates above and… | [Unit And Type Checks](../architecture/validation-map.md#unit-and-type-checks) | Existing contract |
| CLAUDE.md:300–307 | Linting — bash # Lint all projects (CI runs this on master; PRs lint affected projects) pnpm run lint # Lint a… | [Unit And Type Checks](../architecture/validation-map.md#unit-and-type-checks) | Existing contract |
| CLAUDE.md:309–315 | Linting — CI lints affected projects on PRs (nx affected) and every project on master pushes… | [TypeScript File Size](../architecture/nx-workspace-boundaries.md#typescript-file-size) | Existing contract |
| CLAUDE.md:317–317 | Linting — Production TypeScript: hard maximum 400 lines. | [TypeScript File Size](../architecture/nx-workspace-boundaries.md#typescript-file-size) | Existing contract |
| CLAUDE.md:318–324 | Linting — Tests: 1200. /.spec.ts, /.spec-data.ts, /.e2e.ts and everything under apps/-e2e/ — a spec is a flat list… | [TypeScript File Size](../architecture/nx-workspace-boundaries.md#typescript-file-size) | Existing contract |
| CLAUDE.md:325–326 | Linting — Blank lines and comments are not counted (skipBlankLines, skipComments), so a docblock is never the reason… | [TypeScript File Size](../architecture/nx-workspace-boundaries.md#typescript-file-size) | Existing contract |
| CLAUDE.md:328–340 | Linting — Pre-existing oversized files are baselined in tools/eslint/max-lines-baseline.mjs; regenerate the baseline… | [TypeScript File Size](../architecture/nx-workspace-boundaries.md#typescript-file-size) | Existing contract |
| CLAUDE.md:342–349 | Linting — Project lint targets that shell out to eslint must quote the glob, e.g. eslint "apps/<project>//.ts". An… | [TypeScript File Size](../architecture/nx-workspace-boundaries.md#typescript-file-size) | Existing contract |
| CLAUDE.md:353–360 | Legacy Desktop Profile Migration — electron-profile-bootstrap.ts selects the known v0.19 electron-backend profile before eager main-process… | [Desktop upgrades from legacy profiles](../architecture/m3u-playlist-module.md#desktop-upgrades-from-legacy-profiles) | Existing contract |
| CLAUDE.md:362–368 | Legacy Desktop Profile Migration — Startup shows AppStartupStatusComponent until the initial route and source inventory are ready, including… | [Desktop upgrades from legacy profiles](../architecture/m3u-playlist-module.md#desktop-upgrades-from-legacy-profiles) | Existing contract |
| CLAUDE.md:374–374 | Monorepo Structure (Nx Workspace) — This is an Nx monorepo with the following structure: | [Placement Decision](../architecture/nx-workspace-boundaries.md#placement-decision) | Existing contract |
| CLAUDE.md:376–376 | Monorepo Structure (Nx Workspace) — apps/web - Angular application (frontend, shared by Electron and PWA) | [Placement Decision](../architecture/nx-workspace-boundaries.md#placement-decision) | Existing contract |
| CLAUDE.md:377–377 | Monorepo Structure (Nx Workspace) — apps/electron-backend - Electron main process | [Main-process ownership](../development/electron-debugging.md#main-process-ownership) | Moved / consolidated |
| CLAUDE.md:378–378 | Monorepo Structure (Nx Workspace) — apps/web-backend - HTTP backend for the self-hosted PWA (/parse, /parse-xml, /xtream, /stalker CORS proxy… | [Web Backend](../architecture/pwa-self-hosted.md#web-backend) | Existing contract |
| CLAUDE.md:379–379 | Monorepo Structure (Nx Workspace) — apps/remote-control-web - Mobile remote-control web app served by the Electron backend | [Remote Web App](../architecture/remote-control.md#remote-web-app) | Existing contract |
| CLAUDE.md:380–380 | Monorepo Structure (Nx Workspace) — apps/web-e2e - Playwright E2E tests against the web app | [E2E](../architecture/validation-map.md#e2e) | Existing contract |
| CLAUDE.md:381–381 | Monorepo Structure (Nx Workspace) — apps/electron-backend-e2e - Playwright E2E tests against the Electron app | [E2E](../architecture/validation-map.md#e2e) | Existing contract |
| CLAUDE.md:382–382 | Monorepo Structure (Nx Workspace) — apps/stalker-mock-server - Mock Stalker/Ministra portal for dev and E2E | [Stalker Mock Server Architecture](../architecture/stalker-mock-server.md#stalker-mock-server-architecture) | Existing contract |
| CLAUDE.md:383–383 | Monorepo Structure (Nx Workspace) — apps/xtream-mock-server - Mock Xtream Codes API for dev and E2E | [Xtream Mock Server — Architecture](../architecture/xtream-mock-server.md#xtream-mock-server--architecture) | Existing contract |
| CLAUDE.md:420–420 | Frontend Architecture (Angular) — Router store integration for route-based state | [State Management (libs/m3u-state/)](../architecture/m3u-playlist-module.md#state-management-libsm3u-state) | Existing contract |
| CLAUDE.md:422–422 | Frontend Architecture (Angular) — XtreamStore Architecture (Signal Store with Feature Composition): | [Store composition and catalog windowing](../architecture/xtream-portal-compatibility.md#store-composition-and-catalog-windowing) | Added / consolidated |
| CLAUDE.md:424–424 | Frontend Architecture (Angular) — The Xtream Codes module uses NgRx Signal Store with a layered architecture: | [Store composition and catalog windowing](../architecture/xtream-portal-compatibility.md#store-composition-and-catalog-windowing) | Added / consolidated |
| CLAUDE.md:527–527 | M3U Playlist Module Architecture: — The M3U playlist module handles traditional M3U/M3U8 playlists with support for 90,000+ channels. | [Channel List Container](../architecture/m3u-playlist-module.md#channel-list-container) | Existing contract |
| CLAUDE.md:529–543 | M3U Playlist Module Architecture: — ┌─────────────────────────────────────────────────────────────────────┐ │ VIDEO PLAYER PAGE │ │… | [Channel List Container](../architecture/m3u-playlist-module.md#channel-list-container) | Existing contract |
| CLAUDE.md:545–545 | M3U Playlist Module Architecture: — The live EPG panel is a horizontal timeline ribbon under the player (app-epg-timeline,… | [Channel List Container](../architecture/m3u-playlist-module.md#channel-list-container) | Existing contract |
| CLAUDE.md:547–547 | M3U Playlist Module Architecture: — Collapsible live channel rail (M3U player, Xtream/Stalker live layouts, unified favorites/recent live… | [Collapsible Live Sidebar](../architecture/iptvnator-ui-guidelines.md#collapsible-live-sidebar) | Existing contract |
| CLAUDE.md:572–572 | M3U Playlist Module Architecture: — The audio player always renders inline — shouldShowInlinePlayer is bypassed for radio | [Radio audio player](../architecture/player-controls-contract.md#radio-audio-player) | Added / consolidated |
| CLAUDE.md:573–573 | M3U Playlist Module Architecture: — EPG panel is conditionally hidden in the template when radio is active | [Radio audio player](../architecture/player-controls-contract.md#radio-audio-player) | Added / consolidated |
| CLAUDE.md:574–574 | M3U Playlist Module Architecture: — Volume is shared with video player via localStorage key 'volume' | [Radio audio player](../architecture/player-controls-contract.md#radio-audio-player) | Added / consolidated |
| CLAUDE.md:620–620 | M3U Playlist Module Architecture: — Infinite scroll: IntersectionObserver in groups view loads 50 items at a time | [Channel List Container](../architecture/m3u-playlist-module.md#channel-list-container) | Existing contract |
| CLAUDE.md:621–621 | M3U Playlist Module Architecture: — Global progress tick: Single 30s interval instead of per-item intervals | [Channel List Container](../architecture/m3u-playlist-module.md#channel-list-container) | Existing contract |
| CLAUDE.md:623–623 | M3U Playlist Module Architecture: — State management via NgRx (libs/m3u-state/): | [Channel List Container](../architecture/m3u-playlist-module.md#channel-list-container) | Existing contract |
| CLAUDE.md:647–647 | M3U Playlist Module Architecture: — Service Architecture (Factory Pattern): | [Service factory and build bases](../architecture/pwa-self-hosted.md#service-factory-and-build-bases) | Corrected; see decisions |
| CLAUDE.md:649–649 | M3U Playlist Module Architecture: — Abstract DataService class in libs/services/src/lib/data.service.ts defines the contract | [Service factory and build bases](../architecture/pwa-self-hosted.md#service-factory-and-build-bases) | Corrected; see decisions |
| CLAUDE.md:650–652 | M3U Playlist Module Architecture: — Two environment-specific implementations: - ElectronService… | [Service factory and build bases](../architecture/pwa-self-hosted.md#service-factory-and-build-bases) | Corrected; see decisions |
| CLAUDE.md:653–659 | M3U Playlist Module Architecture: — Factory function DataFactory() in apps/web/src/app/app.config.ts determines which implementation to… | [Service factory and build bases](../architecture/pwa-self-hosted.md#service-factory-and-build-bases) | Corrected; see decisions |
| CLAUDE.md:663–666 | Data Storage (Environment-Specific): — Electron: SQLite database via Drizzle ORM (better-sqlite3 driver) - Location:… | [Service factory and build bases](../architecture/pwa-self-hosted.md#service-factory-and-build-bases) | Corrected; see decisions |
| CLAUDE.md:667–670 | Data Storage (Environment-Specific): — PWA (Web): IndexedDB via ngx-indexed-db - Browser-based NoSQL storage - Same schema structure but… | [Service factory and build bases](../architecture/pwa-self-hosted.md#service-factory-and-build-bases) | Corrected; see decisions |
| CLAUDE.md:674–678 | TypeScript File Size Rule: — Keep production TypeScript files under 300 lines. Hard maximum is 350–400 lines, and CI enforces the 400.… | [TypeScript File Size](../architecture/nx-workspace-boundaries.md#typescript-file-size) | Existing contract |
| CLAUDE.md:680–680 | TypeScript File Size Rule: — When creating new files, design them to stay within this limit from the start. | [TypeScript File Size](../architecture/nx-workspace-boundaries.md#typescript-file-size) | Existing contract |
| CLAUDE.md:681–681 | TypeScript File Size Rule: — When adding a feature to an existing file that would push it past 350 lines, refactor first: extract… | [TypeScript File Size](../architecture/nx-workspace-boundaries.md#typescript-file-size) | Existing contract |
| CLAUDE.md:682–682 | TypeScript File Size Rule: — When you notice a file already exceeds 350 lines, proactively suggest a refactoring (or perform it if the… | [TypeScript File Size](../architecture/nx-workspace-boundaries.md#typescript-file-size) | Existing contract |
| CLAUDE.md:686–686 | TypeScript File Size Rule: — Angular components: extract child components, move logic to a dedicated service or store feature | [TypeScript File Size](../architecture/nx-workspace-boundaries.md#typescript-file-size) | Existing contract |
| CLAUDE.md:687–687 | TypeScript File Size Rule: — Signal store features: split into smaller with feature functions in separate files | [TypeScript File Size](../architecture/nx-workspace-boundaries.md#typescript-file-size) | Existing contract |
| CLAUDE.md:688–688 | TypeScript File Size Rule: — Services: split by responsibility (e.g. separate API, transformation, and state concerns) | [TypeScript File Size](../architecture/nx-workspace-boundaries.md#typescript-file-size) | Existing contract |
| CLAUDE.md:689–689 | TypeScript File Size Rule: — Utility files: group by domain and export from a barrel index.ts | [TypeScript File Size](../architecture/nx-workspace-boundaries.md#typescript-file-size) | Existing contract |
| CLAUDE.md:691–691 | TypeScript File Size Rule: — This rule exists to keep the codebase navigable and reviewable. A 150-line file is always preferable to a… | [TypeScript File Size](../architecture/nx-workspace-boundaries.md#typescript-file-size) | Existing contract |
| CLAUDE.md:697–697 | Angular Coding Standards: — This project uses modern Angular signal-based APIs and patterns. ALWAYS use the following: | [Angular conventions](../development/agent-workflow.md#angular-conventions) | Moved / consolidated |
| CLAUDE.md:711–711 | Angular Coding Standards: — Important: When using signals in templates with properties that expect non-signal values, unwrap the… | [Angular conventions](../development/agent-workflow.md#angular-conventions) | Moved / consolidated |
| CLAUDE.md:713–719 | Angular Coding Standards: — html <!-- ✅ Correct - Unwrap the signal --> <button [matMenuTriggerFor]="menu()">Open Menu</button> <!-- ❌… | [Angular conventions](../development/agent-workflow.md#angular-conventions) | Moved / consolidated |
| CLAUDE.md:721–721 | Angular Coding Standards: — Component Inputs/Outputs: Use input() and output() functions instead of @Input() and @Output() decorators | [Angular conventions](../development/agent-workflow.md#angular-conventions) | Moved / consolidated |
| CLAUDE.md:735–735 | Angular Coding Standards: — Reactive State: Use signal primitives for reactive state management | [Angular conventions](../development/agent-workflow.md#angular-conventions) | Moved / consolidated |
| CLAUDE.md:775–775 | Backend Architecture (Electron) — Main Entry: apps/electron-backend/src/main.ts | [Window Chrome And Custom Title Bar](../architecture/workspace-shell.md#window-chrome-and-custom-title-bar) | Existing contract |
| CLAUDE.md:777–777 | Backend Architecture (Electron) — Bootstraps Electron app and initializes database | [Window Chrome And Custom Title Bar](../architecture/workspace-shell.md#window-chrome-and-custom-title-bar) | Existing contract |
| CLAUDE.md:778–778 | Backend Architecture (Electron) — Registers event handlers for IPC communication | [Window Chrome And Custom Title Bar](../architecture/workspace-shell.md#window-chrome-and-custom-title-bar) | Existing contract |
| CLAUDE.md:779–779 | Backend Architecture (Electron) — Creates the main window per the startup window mode (app/app.ts initMainWindow, resolver in… | [Window Chrome And Custom Title Bar](../architecture/workspace-shell.md#window-chrome-and-custom-title-bar) | Existing contract |
| CLAUDE.md:780–780 | Backend Architecture (Electron) — Persists the app zoom level (issue #1109): the preload restores it with webFrame.setZoomLevel (temporary,… | [Window Chrome And Custom Title Bar](../architecture/workspace-shell.md#window-chrome-and-custom-title-bar) | Existing contract |
| CLAUDE.md:781–781 | Backend Architecture (Electron) — Recovers a renderer reload on an in-app route: the packaged renderer is index.html over file:// with path… | [Window Chrome And Custom Title Bar](../architecture/workspace-shell.md#window-chrome-and-custom-title-bar) | Existing contract |
| CLAUDE.md:782–782 | Backend Architecture (Electron) — Holds a single-instance lock (app/services/single-instance.ts), requested after the userData override so… | [Window Chrome And Custom Title Bar](../architecture/workspace-shell.md#window-chrome-and-custom-title-bar) | Existing contract |
| CLAUDE.md:833–837 | Xtream Category Management — The Electron Live TV, Movies, and Series category dialog applies Select/Deselect to search results while a… | [Behavior Notes](../architecture/category-management.md#behavior-notes) | Existing contract |
| CLAUDE.md:843–851 | Xtream Connection Test — Add/Edit source Test HTTPS and HTTP discloses plaintext credential use before the click and can replace an… | [Connection Input](../architecture/xtream-portal-compatibility.md#connection-input) | Existing contract |
| CLAUDE.md:855–863 | Xtream Live Auto Format — The routed Xtream live host supplies liveAutoTsUrl only for Auto with explicit HLS+TS account evidence,… | [Initial Auto HLS failure](../architecture/xtream-portal-compatibility.md#initial-auto-hls-failure) | Existing contract |
| CLAUDE.md:867–883 | Xtream Catch-Up Server Timezone — The {Y-m-d:H-M} segment of a timeshift URL is read by the panel in ITS timezone (server_info.timezone),… | [Catch-Up Playback URLs](../architecture/xtream-portal-compatibility.md#catch-up-playback-urls) | Existing contract |
| CLAUDE.md:887–889 | M3U URL User-Agent — PlaylistsService.getPlaylist() joins the per-playlist mutation queue so a route opened during refresh… | [User-Agent for URL sources](../architecture/m3u-playlist-module.md#user-agent-for-url-sources) | Existing contract |
| CLAUDE.md:890–894 | M3U URL User-Agent — The URL import form accepts an optional User-Agent and stores it as Playlist.userAgent. Electron sends it… | [User-Agent for URL sources](../architecture/m3u-playlist-module.md#user-agent-for-url-sources) | Existing contract |
| CLAUDE.md:895–897 | M3U URL User-Agent — Reuse the existing source editor and channel-over-playlist playback header precedence. Contract:… | [User-Agent for URL sources](../architecture/m3u-playlist-module.md#user-agent-for-url-sources) | Existing contract |
| CLAUDE.md:901–901 | Playlist Support: — M3U/M3U8 files (local or URL) | [User-Agent for URL sources](../architecture/m3u-playlist-module.md#user-agent-for-url-sources) | Existing contract |
| CLAUDE.md:905–920 | Playlist Support: — Stalker playback links: create_link runs only when the catalog row sets use_http_tmp_link or… | [Playback Link Resolution](../architecture/stalker-portal.md#playback-link-resolution) | Corrected; see decisions |
| CLAUDE.md:922–941 | Playlist Support: — Opening a playlist from the OS (Electron only): a .m3u/.m3u8 path passed on the command line, opened… | [Opening playlists from the operating system](../architecture/m3u-playlist-module.md#opening-playlists-from-the-operating-system) | Added / consolidated |
| CLAUDE.md:943–959 | Playlist Support: — The OS-level registration that makes those paths reachable is fileAssociations in electron-builder.json —… | [Opening playlists from the operating system](../architecture/m3u-playlist-module.md#opening-playlists-from-the-operating-system) | Added / consolidated |
| CLAUDE.md:963–968 | Video Players: — The Embedded MPV native-view dock follows app theme tokens as a solid app surface, including Material… | [Player And EPG Theme Boundaries](../architecture/iptvnator-ui-guidelines.md#player-and-epg-theme-boundaries) | Existing contract |
| CLAUDE.md:970–977 | Video Players: — Built-in web players: HTML5+hls.js, Video.js, and ArtPlayer. The HTML5 player and ArtPlayer pick their… | [Codec And Container Diagnostics](../architecture/embedded-inline-playback.md#codec-and-container-diagnostics) | Existing contract |
| CLAUDE.md:978–986 | Video Players: — mpegts.js 1.8.1 errors from all three built-in players cross one version-locked structured evidence… | [Codec And Container Diagnostics](../architecture/embedded-inline-playback.md#codec-and-container-diagnostics) | Existing contract |
| CLAUDE.md:987–1119 | Video Players: — Browser playback diagnostics and recovery policy live in libs/playback/util and are exported by… | [Codec And Container Diagnostics](../architecture/embedded-inline-playback.md#codec-and-container-diagnostics) | Existing contract |
| CLAUDE.md:1120–1125 | Video Players: — M3U Favorites and Recently Viewed resolve Channel.drm into ResolvedPortalPlayback.drm through… | [Codec And Container Diagnostics](../architecture/embedded-inline-playback.md#codec-and-container-diagnostics) | Existing contract |
| CLAUDE.md:1126–1150 | Video Players: — DASH + ClearKey (M3U module): .mpd channels play through a lazily loaded Shaka Player source engine inside… | [Codec And Container Diagnostics](../architecture/embedded-inline-playback.md#codec-and-container-diagnostics) | Existing contract |
| CLAUDE.md:1151–1165 | Video Players: — Stream info popover: an info button in the top-right corner of the shared controls overlay shows live… | [Codec And Container Diagnostics](../architecture/embedded-inline-playback.md#codec-and-container-diagnostics) | Existing contract |
| CLAUDE.md:1166–1166 | Video Players: — External players: MPV, VLC (via IPC to Electron backend) | [Codec And Container Diagnostics](../architecture/embedded-inline-playback.md#codec-and-container-diagnostics) | Existing contract |
| CLAUDE.md:1167–1181 | Video Players: — Display sleep during playback: PlaybackKeepAwakeService… | [Codec And Container Diagnostics](../architecture/embedded-inline-playback.md#codec-and-container-diagnostics) | Existing contract |
| CLAUDE.md:1182–1182 | Video Players: — Embedded MPV (experimental, macOS/Windows/Linux): renders mpv video inside the Electron window through a… | [How It Is Embedded](../architecture/embedded-mpv-native.md#how-it-is-embedded) | Existing contract |
| CLAUDE.md:1182–1182 | Video Players: — Two per-session knobs are captured at session creation from the main-process settings mirror… | [How It Is Embedded](../architecture/embedded-mpv-native.md#how-it-is-embedded) | Existing contract |
| CLAUDE.md:1182–1182 | Video Players: — Contract: docs/architecture/embedded-mpv-native.md ("Session Options", "Network Auto-Reconnect"). macOS… | [How It Is Embedded](../architecture/embedded-mpv-native.md#how-it-is-embedded) | Existing contract |
| CLAUDE.md:1182–1182 | Video Players: — Windows uses in-process libmpv with --wid against an app-owned child HWND; | [How It Is Embedded](../architecture/embedded-mpv-native.md#how-it-is-embedded) | Existing contract |
| CLAUDE.md:1182–1182 | Video Players: — Linux spawns an out-of-process mpv --wid=<x11-window> controlled over a JSON IPC socket (X11/XWayland… | [How It Is Embedded](../architecture/embedded-mpv-native.md#how-it-is-embedded) | Existing contract |
| CLAUDE.md:1182–1182 | Video Players: — Renderer bounds are CSS pixels; the service converts them to native units in the main process… | [How It Is Embedded](../architecture/embedded-mpv-native.md#how-it-is-embedded) | Existing contract |
| CLAUDE.md:1182–1182 | Video Players: — Arrow-key and ±10 s button steps go through the relative seekEmbeddedMpvBy IPC (mpv seek <delta>… | [How It Is Embedded](../architecture/embedded-mpv-native.md#how-it-is-embedded) | Existing contract |
| CLAUDE.md:1182–1182 | Video Players: — Service: apps/electron-backend/src/app/services/embedded-mpv-native.service.ts; full architecture:… | [How It Is Embedded](../architecture/embedded-mpv-native.md#how-it-is-embedded) | Existing contract |
| CLAUDE.md:1183–1314 | Video Players: — Embedded MPV frame-copy engine (experimental, macOS Apple Silicon + Linux x64 + Windows; enabled via… | [How It Is Embedded](../architecture/embedded-mpv-native.md#how-it-is-embedded) | Existing contract |
| CLAUDE.md:1315–1315 | Video Players: — Shared player-controls layer: libs/ui/playback/src/lib/player-controls/ exports the engine-neutral… | [Landed architecture](../architecture/player-controls-contract.md#landed-architecture) | Existing contract |
| CLAUDE.md:1315–1315 | Video Players: — Its subtitle menu carries capability-gated advanced subtitle support (#1408): external subtitle file… | [Landed architecture](../architecture/player-controls-contract.md#landed-architecture) | Existing contract |
| CLAUDE.md:1315–1315 | Video Players: — HTML5/ArtPlayer implement it through the neutral source bridge (.srt/.vtt via a DOM file picker with… | [Landed architecture](../architecture/player-controls-contract.md#landed-architecture) | Existing contract |
| CLAUDE.md:1315–1315 | Video Players: — Embedded MPV frame-copy implements it through new helper protocol commands… | [Landed architecture](../architecture/player-controls-contract.md#landed-architecture) | Existing contract |
| CLAUDE.md:1315–1315 | Video Players: — Video.js shared mode, vendor-chrome paths, native-view, and the Linux out-of-process path advertise no… | [Landed architecture](../architecture/player-controls-contract.md#landed-architecture) | Existing contract |
| CLAUDE.md:1315–1315 | Video Players: — Shared controls include a per-session quality menu (Auto + “1080p”-style levels via setQualityLevel; | [Landed architecture](../architecture/player-controls-contract.md#landed-architecture) | Existing contract |
| CLAUDE.md:1315–1315 | Video Players: — AUTO_QUALITY_LEVEL_ID restores ABR): the capability derives from the manifest — advertised only when the… | [Landed architecture](../architecture/player-controls-contract.md#landed-architecture) | Existing contract |
| CLAUDE.md:1315–1315 | Video Players: — In fullscreen, app-player-controls shows a pointer-transparent media-title overlay at the top while… | [Landed architecture](../architecture/player-controls-contract.md#landed-architecture) | Existing contract |
| CLAUDE.md:1315–1315 | Video Players: — Persisted Settings.webPlayerSharedControls is default-ON (absent stored values coerce with !== false in… | [Landed architecture](../architecture/player-controls-contract.md#landed-architecture) | Existing contract |
| CLAUDE.md:1315–1315 | Video Players: — The shared surface has explicit touch semantics (ControlsSurface.wasTouchInteraction): viewport taps… | [Landed architecture](../architecture/player-controls-contract.md#landed-architecture) | Existing contract |
| CLAUDE.md:1315–1315 | Video Players: — Only keyboard-originated focus pins the bar open: Chromium also focuses a clicked <button>, so… | [Landed architecture](../architecture/player-controls-contract.md#landed-architecture) | Existing contract |
| CLAUDE.md:1315–1315 | Video Players: — A completed pointer click then releases the focus it left on the control (onBarClick →… | [Landed architecture](../architecture/player-controls-contract.md#landed-architecture) | Existing contract |
| CLAUDE.md:1315–1315 | Video Players: — Keyboard activation (empty pointerType) keeps focus, only buttons and range sliders are released, Chromium… | [Landed architecture](../architecture/player-controls-contract.md#landed-architecture) | Existing contract |
| CLAUDE.md:1315–1315 | Video Players: — WebPlayerViewComponent snapshots the preference into the immutable token for each new player host. | [Landed architecture](../architecture/player-controls-contract.md#landed-architecture) | Existing contract |
| CLAUDE.md:1315–1315 | Video Players: — The parent /workspace route awaits the initial SettingsStore load, including cold-start direct links,… | [Landed architecture](../architecture/player-controls-contract.md#landed-architecture) | Existing contract |
| CLAUDE.md:1315–1315 | Video Players: — Saving applies to the next host without an application restart; an existing session never changes controls… | [Landed architecture](../architecture/player-controls-contract.md#landed-architecture) | Existing contract |
| CLAUDE.md:1315–1315 | Video Players: — Embedded MPV ignores the web-player preference: frame-copy always uses shared DOM controls through… | [Landed architecture](../architecture/player-controls-contract.md#landed-architecture) | Existing contract |
| CLAUDE.md:1315–1315 | Video Players: — The Embedded MPV host selects exactly one controls UI for its reported engine. | [Landed architecture](../architecture/player-controls-contract.md#landed-architecture) | Existing contract |
| CLAUDE.md:1315–1315 | Video Players: — Same-session IPC replies yield to a broadcast snapshot received while the command was pending, so a… | [Landed architecture](../architecture/player-controls-contract.md#landed-architecture) | Existing contract |
| CLAUDE.md:1315–1315 | Video Players: — The built-in HTML5/hls.js player is the second guarded consumer: HtmlVideoPlayerComponent provides a… | [Landed architecture](../architecture/player-controls-contract.md#landed-architecture) | Existing contract |
| CLAUDE.md:1315–1315 | Video Players: — Video.js is the third guarded consumer: VjsPlayerComponent provides a component-scoped… | [Landed architecture](../architecture/player-controls-contract.md#landed-architecture) | Existing contract |
| CLAUDE.md:1315–1315 | Video Players: — Reset-driven raw MPEG-TS changes pause first, coalesce to the latest desired source, preserve actual… | [Landed architecture](../architecture/player-controls-contract.md#landed-architecture) | Existing contract |
| CLAUDE.md:1315–1315 | Video Players: — In shared-controls mode, Video.js native controls, click/double-click/hotkey actions, and spatial… | [Landed architecture](../architecture/player-controls-contract.md#landed-architecture) | Existing contract |
| CLAUDE.md:1315–1315 | Video Players: — ArtPlayer is the fourth guarded consumer: ArtPlayerComponent provides a component-scoped… | [Landed architecture](../architecture/player-controls-contract.md#landed-architecture) | Existing contract |
| CLAUDE.md:1315–1315 | Video Players: — The view also renders app-fullscreen-channel-panel beside the engine, staged on fullscreenSurface and… | [Landed architecture](../architecture/player-controls-contract.md#landed-architecture) | Existing contract |
| CLAUDE.md:1315–1315 | Video Players: — Providers: M3U VideoPlayerComponent (app-m3u-fullscreen-channel-list, a local icon-only… | [Landed architecture](../architecture/player-controls-contract.md#landed-architecture) | Existing contract |
| CLAUDE.md:1315–1315 | Video Players: — CDK overlays follow the fullscreen element via FullscreenOverlayContainer in app.config.ts. | [Landed architecture](../architecture/player-controls-contract.md#landed-architecture) | Existing contract |
| CLAUDE.md:1315–1315 | Video Players: — Series playback gets the same panel as an episode list: PortalInlinePlayerComponent — the component both… | [Landed architecture](../architecture/player-controls-contract.md#landed-architecture) | Existing contract |
| CLAUDE.md:1315–1315 | Video Players: — Movies never get it (contentType !== 'episode' → null), external MPV/VLC never mount the inline player,… | [Landed architecture](../architecture/player-controls-contract.md#landed-architecture) | Existing contract |
| CLAUDE.md:1315–1315 | Video Players: — M3U also zaps with PageUp/PageDown, yielding to already-handled events and menu/dialog or scrollable-list… | [Landed architecture](../architecture/player-controls-contract.md#landed-architecture) | Existing contract |
| CLAUDE.md:1315–1315 | Video Players: — While the live web-player host owns fullscreen (itself, or through the nested surface a legacy player… | [Landed architecture](../architecture/player-controls-contract.md#landed-architecture) | Existing contract |
| CLAUDE.md:1315–1315 | Video Players: — Contract section "Fullscreen channel panel" in docs/architecture/player-controls-contract.md. | [Landed architecture](../architecture/player-controls-contract.md#landed-architecture) | Existing contract |
| CLAUDE.md:1315–1315 | Video Players: — On the preference-off path, all three web players retain their existing controls, source behavior, and… | [Landed architecture](../architecture/player-controls-contract.md#landed-architecture) | Existing contract |
| CLAUDE.md:1315–1315 | Video Players: — The legacy Video.js chrome also releases the focus a pointer interaction leaves on a control… | [Landed architecture](../architecture/player-controls-contract.md#landed-architecture) | Existing contract |
| CLAUDE.md:1315–1315 | Video Players: — It is driven mainly by focusin, not the click, because choosing a menu item moves focus to the menu button… | [Landed architecture](../architecture/player-controls-contract.md#landed-architecture) | Existing contract |
| CLAUDE.md:1315–1315 | Video Players: — The release is scoped to .vjs-control-bar so the caption-settings dialog (a modal sibling of the bar)… | [Landed architecture](../architecture/player-controls-contract.md#landed-architecture) | Existing contract |
| CLAUDE.md:1315–1315 | Video Players: — Settings.showCaptions is deliberately outside this rollout gate: it is engine state, so the preference-off… | [Landed architecture](../architecture/player-controls-contract.md#landed-architecture) | Existing contract |
| CLAUDE.md:1315–1315 | Video Players: — The two modes differ in how long it is enforced: shared controls are authoritative for the session (user… | [Landed architecture](../architecture/player-controls-contract.md#landed-architecture) | Existing contract |
| CLAUDE.md:1315–1315 | Video Players: — Mode selection is the optional playbackStarted probe the legacy owners pass to all three helpers (HLS,… | [Landed architecture](../architecture/player-controls-contract.md#landed-architecture) | Existing contract |
| CLAUDE.md:1315–1315 | Video Players: — WebPlayerViewComponent reads it from SettingsStore instead of a host input so every host (M3U,… | [Landed architecture](../architecture/player-controls-contract.md#landed-architecture) | Existing contract |
| CLAUDE.md:1316–1325 | Video Players: — Shared web picture-in-picture stays inside that default-on rollout. PlayerController exposes capability… | [Landed architecture](../architecture/player-controls-contract.md#landed-architecture) | Existing contract |
| CLAUDE.md:1326–1344 | Video Players: — WebVideoControlsAdapter supplies its current video and binding generation to… | [Landed architecture](../architecture/player-controls-contract.md#landed-architecture) | Existing contract |
| CLAUDE.md:1348–1376 | Download Manager: — Fresh Xtream movie and series-episode downloads propagate the playlist's User-Agent, Referer, and Origin,… | [Queuing, persistence, and UX notes](../architecture/download-manager.md#queuing-persistence-and-ux-notes) | Existing contract |
| CLAUDE.md:1377–1380 | Download Manager: — The desktop-only manager shares one global download store across the global, Xtream-scoped, and… | [Queuing, persistence, and UX notes](../architecture/download-manager.md#queuing-persistence-and-ux-notes) | Existing contract |
| CLAUDE.md:1381–1420 | Download Manager: — Series details route individual and selected-season episode downloads through the provider-neutral… | [Queuing, persistence, and UX notes](../architecture/download-manager.md#queuing-persistence-and-ux-notes) | Existing contract |
| CLAUDE.md:1421–1438 | Download Manager: — Episode ownership uses normalized episode.id as the canonical xtreamId for both providers; Stalker… | [Queuing, persistence, and UX notes](../architecture/download-manager.md#queuing-persistence-and-ux-notes) | Existing contract |
| CLAUDE.md:1439–1444 | Download Manager: — Ready cards (movies, grouped series, and standalone episodes) open a focused local detail; local file… | [Queuing, persistence, and UX notes](../architecture/download-manager.md#queuing-persistence-and-ux-notes) | Existing contract |
| CLAUDE.md:1445–1449 | Download Manager: — Downloads capture a versioned metadata snapshot from the rendered Xtream or Stalker movie/episode detail… | [Queuing, persistence, and UX notes](../architecture/download-manager.md#queuing-persistence-and-ux-notes) | Existing contract |
| CLAUDE.md:1450–1459 | Download Manager: — View in portal resolves a concrete Xtream category/item route. Stalker accepts a recently-viewed shape… | [Queuing, persistence, and UX notes](../architecture/download-manager.md#queuing-persistence-and-ux-notes) | Existing contract |
| CLAUDE.md:1460–1462 | Download Manager: — Download rows and local files survive source deletion. The global offline library remains visible with no… | [Queuing, persistence, and UX notes](../architecture/download-manager.md#queuing-persistence-and-ux-notes) | Existing contract |
| CLAUDE.md:1463–1465 | Download Manager: — If a finalized file disappears while a focused detail is open, the authoritative download list refreshes… | [Queuing, persistence, and UX notes](../architecture/download-manager.md#queuing-persistence-and-ux-notes) | Existing contract |
| CLAUDE.md:1466–1497 | Download Manager: — Live-TV recordings (Embedded MPV stream-record) are tracked beside downloads in their own recordings table… | [Queuing, persistence, and UX notes](../architecture/download-manager.md#queuing-persistence-and-ux-notes) | Existing contract |
| CLAUDE.md:1566–1566 | VOD/Series Detail Pages (two-state layout): — Xtream and Stalker detail pages use the shared PortalDetailShellComponent… | [Two-State Detail Layout (Browse ↔ Watch)](../architecture/embedded-inline-playback.md#two-state-detail-layout-browse--watch) | Existing contract |
| CLAUDE.md:1567–1567 | VOD/Series Detail Pages (two-state layout): — The inline player (PortalInlinePlayerComponent) renders a full-width theater stage… | [Two-State Detail Layout (Browse ↔ Watch)](../architecture/embedded-inline-playback.md#two-state-detail-layout-browse--watch) | Existing contract |
| CLAUDE.md:1568–1568 | VOD/Series Detail Pages (two-state layout): — For inline series playback on wide windows the stage instead docks the player left and shows an "Up Next"… | [Two-State Detail Layout (Browse ↔ Watch)](../architecture/embedded-inline-playback.md#two-state-detail-layout-browse--watch) | Existing contract |
| CLAUDE.md:1582–1582 | VOD/Series Detail Pages (two-state layout): — Finds the same movie in the user's other imported playlists and adds a "Sources N" chip to the Xtream VOD… | [VOD Multi-Source](../architecture/vod-multi-source.md#vod-multi-source) | Existing contract |
| CLAUDE.md:1582–1582 | VOD/Series Detail Pages (two-state layout): — The chip opens a 660px anchored CDK-overlay popover (libs/ui/components/src/lib/vod-sources/; not MatMenu,… | [VOD Multi-Source](../architecture/vod-multi-source.md#vod-multi-source) | Existing contract |
| CLAUDE.md:1582–1582 | VOD/Series Detail Pages (two-state layout): — It opens ABOVE the chip (right edges aligned, pressed state on the chip while open), height-capped by the… | [VOD Multi-Source](../architecture/vod-multi-source.md#vod-multi-source) | Existing contract |
| CLAUDE.md:1582–1582 | VOD/Series Detail Pages (two-state layout): — A row's language is vodSourceLanguage (libs/shared/interfaces/src/lib/vod-source-language.util.ts): the… | [VOD Multi-Source](../architecture/vod-multi-source.md#vod-multi-source) | Existing contract |
| CLAUDE.md:1582–1582 | VOD/Series Detail Pages (two-state layout): — Latin/Cyrillic 2–4 letters + MULTI; only the legacy pipe form is permissive — bracket/dash matches must… | [VOD Multi-Source](../architecture/vod-multi-source.md#vod-multi-source) | Existing contract |
| CLAUDE.md:1582–1582 | VOD/Series Detail Pages (two-state layout): — Both forms are parsed guesses: browse filter and chips only, never ranking/failover/dub-warning inputs. | [VOD Multi-Source](../architecture/vod-multi-source.md#vod-multi-source) | Existing contract |
| CLAUDE.md:1582–1582 | VOD/Series Detail Pages (two-state layout): — Recognition alone is not enough — normalizeTitleKeys must STRIP the same tag or the copy is never… | [VOD Multi-Source](../architecture/vod-multi-source.md#vod-multi-source) | Existing contract |
| CLAUDE.md:1582–1582 | VOD/Series Detail Pages (two-state layout): — It goes no further on purpose: a wrong guess costs a filter option, a wrong strip corrupts identity, and… | [VOD Multi-Source](../architecture/vod-multi-source.md#vod-multi-source) | Existing contract |
| CLAUDE.md:1582–1582 | VOD/Series Detail Pages (two-state layout): — The one shape that cannot decide itself is a strip leaving NO real word behind — decided by running the… | [VOD Multi-Source](../architecture/vod-multi-source.md#vod-multi-source) | Existing contract |
| CLAUDE.md:1582–1582 | VOD/Series Detail Pages (two-state layout): — Every vocabulary entry is one the catalog proves prefixes hundreds of ordinary titles — never one that… | [VOD Multi-Source](../architecture/vod-multi-source.md#vod-multi-source) | Existing contract |
| CLAUDE.md:1582–1582 | VOD/Series Detail Pages (two-state layout): — Verify such widenings against the real catalog before shipping them, over movies AND series: a movie-only… | [VOD Multi-Source](../architecture/vod-multi-source.md#vod-multi-source) | Existing contract |
| CLAUDE.md:1582–1582 | VOD/Series Detail Pages (two-state layout): — Checks run through a 4-slot queue and settled verdicts are cached 10 min per movie+source… | [VOD Multi-Source](../architecture/vod-multi-source.md#vod-multi-source) | Existing contract |
| CLAUDE.md:1582–1582 | VOD/Series Detail Pages (two-state layout): — Both chips are handed the same matchKind and vodAutoFailover and both write the setting back. | [VOD Multi-Source](../architecture/vod-multi-source.md#vod-multi-source) | Existing contract |
| CLAUDE.md:1582–1582 | VOD/Series Detail Pages (two-state layout): — The details-page chip badge counts TOTAL copies across all playlists (the in-player chip still counts… | [VOD Multi-Source](../architecture/vod-multi-source.md#vod-multi-source) | Existing contract |
| CLAUDE.md:1582–1582 | VOD/Series Detail Pages (two-state layout): — The action row's Favorites and Download buttons are icon-only 64px squares: filled red heart when… | [VOD Multi-Source](../architecture/vod-multi-source.md#vod-multi-source) | Existing contract |
| CLAUDE.md:1583–1583 | VOD/Series Detail Pages (two-state layout): — Scope v1 is Xtream ↔ Xtream, movies only, Electron only. Stalker never reaches the content table and M3U… | [VOD Multi-Source](../architecture/vod-multi-source.md#vod-multi-source) | Existing contract |
| CLAUDE.md:1584–1584 | VOD/Series Detail Pages (two-state layout): — Metadata provenance is the core contract. Every field is {value, provenance} where api/probe are facts… | [VOD Multi-Source](../architecture/vod-multi-source.md#vod-multi-source) | Existing contract |
| CLAUDE.md:1585–1585 | VOD/Series Detail Pages (two-state layout): — Discovery (DB_FIND_TITLE_SOURCES, trigram FTS over content_title_fts) is lazy and returns only what the… | [VOD Multi-Source](../architecture/vod-multi-source.md#vod-multi-source) | Existing contract |
| CLAUDE.md:1585–1585 | VOD/Series Detail Pages (two-state layout): — A source that is never read looks exactly like one that does not exist, so: the current playlist is… | [VOD Multi-Source](../architecture/vod-multi-source.md#vod-multi-source) | Existing contract |
| CLAUDE.md:1585–1585 | VOD/Series Detail Pages (two-state layout): — The year gate covers BOTH match tiers: normalizeTitleKeys strips bracketed segments, so "Dune (1984)"… | [VOD Multi-Source](../architecture/vod-multi-source.md#vod-multi-source) | Existing contract |
| CLAUDE.md:1585–1585 | VOD/Series Detail Pages (two-state layout): — A non-ASCII token cannot be folded by LOWER() (ASCII-only) but CAN be by a GLOB character class (UTF-8… | [VOD Multi-Source](../architecture/vod-multi-source.md#vod-multi-source) | Existing contract |
| CLAUDE.md:1585–1585 | VOD/Series Detail Pages (two-state layout): — The movie's own year comes from releaseTagYear (bracketed or trailing only), never extractYear: a year… | [VOD Multi-Source](../architecture/vod-multi-source.md#vod-multi-source) | Existing contract |
| CLAUDE.md:1585–1585 | VOD/Series Detail Pages (two-state layout): — One row inside the excluded playlist is kept when the caller names it (keepContentId), because a pin can… | [VOD Multi-Source](../architecture/vod-multi-source.md#vod-multi-source) | Existing contract |
| CLAUDE.md:1585–1585 | VOD/Series Detail Pages (two-state layout): — Resolution is deferred to click/pin/check because content stores no container_extension and… | [VOD Multi-Source](../architecture/vod-multi-source.md#vod-multi-source) | Existing contract |
| CLAUDE.md:1586–1586 | VOD/Series Detail Pages (two-state layout): — Switching = one inlinePlayback.set({...next, startTime}), never null-then-set, so the player and engine… | [VOD Multi-Source](../architecture/vod-multi-source.md#vod-multi-source) | Existing contract |
| CLAUDE.md:1588–1588 | VOD/Series Detail Pages (two-state layout): — Claims in the present tense (the "Playing from" caption and the source row's Playing badge) are gated on… | [VOD Multi-Source](../architecture/vod-multi-source.md#vod-multi-source) | Existing contract |
| CLAUDE.md:1589–1589 | VOD/Series Detail Pages (two-state layout): — Pins are included in playlist backup as the optional sourcePins collection, carried under the playlist… | [VOD Multi-Source](../architecture/vod-multi-source.md#vod-multi-source) | Existing contract |
| CLAUDE.md:1590–1590 | VOD/Series Detail Pages (two-state layout): — Auto-failover is Settings.vodAutoFailover, opt-in and off by default, web engines only — the toggle is… | [VOD Multi-Source](../architecture/vod-multi-source.md#vod-multi-source) | Existing contract |
| CLAUDE.md:1596–1596 | Radio Player: — Dedicated audio player for channels with radio="true" M3U attribute | [Radio audio player](../architecture/player-controls-contract.md#radio-audio-player) | Added / consolidated |
| CLAUDE.md:1597–1597 | Radio Player: — Cinematic layout: blurred station logo as backdrop, floating artwork card, transport controls | [Radio audio player](../architecture/player-controls-contract.md#radio-audio-player) | Added / consolidated |
| CLAUDE.md:1598–1598 | Radio Player: — Always uses the built-in inline player — external player settings (MPV/VLC) are ignored for radio | [Radio audio player](../architecture/player-controls-contract.md#radio-audio-player) | Added / consolidated |
| CLAUDE.md:1599–1599 | Radio Player: — EPG panel is hidden for radio channels (radio streams have no EPG data) | [Radio audio player](../architecture/player-controls-contract.md#radio-audio-player) | Added / consolidated |
| CLAUDE.md:1600–1600 | Radio Player: — Volume synced with video player via shared localStorage key 'volume' | [Radio audio player](../architecture/player-controls-contract.md#radio-audio-player) | Added / consolidated |
| CLAUDE.md:1606–1606 | EPG (Electronic Program Guide): — XMLTV format support, from http(s) links or local files (Electron only): a file: URL, an absolute POSIX… | [EPG Integration](../architecture/m3u-playlist-module.md#epg-integration) | Existing contract |
| CLAUDE.md:1615–1615 | EPG (Electronic Program Guide): — Enriches Xtream and Stalker VOD/series detail views with TMDB data (plot, cast with avatar chips,… | [TMDB Metadata Enrichment](../architecture/tmdb-metadata-enrichment.md#tmdb-metadata-enrichment) | Existing contract |
| CLAUDE.md:1616–1616 | EPG (Electronic Program Guide): — The M3U player consumes it too: entries recognized as movie files open in the VOD detail shell fed purely… | [TMDB Metadata Enrichment](../architecture/tmdb-metadata-enrichment.md#tmdb-metadata-enrichment) | Existing contract |
| CLAUDE.md:1617–1617 | EPG (Electronic Program Guide): — "Similar" rail in ALL detail views: TMDB recommendations matched against the provider catalog by… | [TMDB Metadata Enrichment](../architecture/tmdb-metadata-enrichment.md#tmdb-metadata-enrichment) | Existing contract |
| CLAUDE.md:1618–1618 | EPG (Electronic Program Guide): — Season/episode enrichment: opening a season lazily fetches /tv/{id}/season/{n} and overlays real episode… | [TMDB Metadata Enrichment](../architecture/tmdb-metadata-enrichment.md#tmdb-metadata-enrichment) | Existing contract |
| CLAUDE.md:1619–1619 | EPG (Electronic Program Guide): — Dashboard: opt-in "Trending this week" rail (weekly TMDB trending matched against imported Xtream… | [TMDB Metadata Enrichment](../architecture/tmdb-metadata-enrichment.md#tmdb-metadata-enrichment) | Existing contract |
| CLAUDE.md:1619–1619 | EPG (Electronic Program Guide): — Electron-only, dashboardRails.tmdbTrending toggle), a "Because you watched" recommendations rail… | [TMDB Metadata Enrichment](../architecture/tmdb-metadata-enrichment.md#tmdb-metadata-enrichment) | Existing contract |
| CLAUDE.md:1619–1619 | EPG (Electronic Program Guide): — TMDB has no account-free "for you" endpoint, so DashboardRecommendationsService seeds per-title… | [TMDB Metadata Enrichment](../architecture/tmdb-metadata-enrichment.md#tmdb-metadata-enrichment) | Existing contract |
| CLAUDE.md:1619–1619 | EPG (Electronic Program Guide): — The hero lookup must carry the same identity the detail view used, not just the display title —… | [TMDB Metadata Enrichment](../architecture/tmdb-metadata-enrichment.md#tmdb-metadata-enrichment) | Existing contract |
| CLAUDE.md:1619–1619 | EPG (Electronic Program Guide): — The lookup key is the WHOLE attempt sequence, since two rows can share title/year/id yet differ in whether… | [TMDB Metadata Enrichment](../architecture/tmdb-metadata-enrichment.md#tmdb-metadata-enrichment) | Existing contract |
| CLAUDE.md:1619–1619 | EPG (Electronic Program Guide): — Stalker items never reach the content table, so their backdrop rides in the stored entry… | [TMDB Metadata Enrichment](../architecture/tmdb-metadata-enrichment.md#tmdb-metadata-enrichment) | Existing contract |
| CLAUDE.md:1619–1619 | EPG (Electronic Program Guide): — Xtream rows carry the same identity on the content row: the detail views back-fill… | [TMDB Metadata Enrichment](../architecture/tmdb-metadata-enrichment.md#tmdb-metadata-enrichment) | Existing contract |
| CLAUDE.md:1619–1619 | EPG (Electronic Program Guide): — Writes are per-column and never overwrite (enrichment supplies the pieces at different times, so a… | [TMDB Metadata Enrichment](../architecture/tmdb-metadata-enrichment.md#tmdb-metadata-enrichment) | Existing contract |
| CLAUDE.md:1619–1619 | EPG (Electronic Program Guide): — release_year is the year the PROVIDER stated, never one read out of the title (readers still apply that… | [TMDB Metadata Enrichment](../architecture/tmdb-metadata-enrichment.md#tmdb-metadata-enrichment) | Existing contract |
| CLAUDE.md:1619–1619 | EPG (Electronic Program Guide): — Both sides validate through normalizeContentMetadataPatch (libs/shared/interfaces), so legacy rows,… | [TMDB Metadata Enrichment](../architecture/tmdb-metadata-enrichment.md#tmdb-metadata-enrichment) | Existing contract |
| CLAUDE.md:1620–1620 | EPG (Electronic Program Guide): — Series detail views show a TMDB production-status chip (tmdb_status, e.g. Ended / Returning) — TMDB sends… | [TMDB Metadata Enrichment](../architecture/tmdb-metadata-enrichment.md#tmdb-metadata-enrichment) | Existing contract |
| CLAUDE.md:1621–1621 | EPG (Electronic Program Guide): — Actor pages: cast avatar chips are clickable (TMDB person id) and open actor/:personId inside the current… | [TMDB Metadata Enrichment](../architecture/tmdb-metadata-enrichment.md#tmdb-metadata-enrichment) | Existing contract |
| CLAUDE.md:1622–1622 | EPG (Electronic Program Guide): — Discover pages (clickable metadata chips, issue #1449): year, genre, and country chips on all four detail… | [TMDB Metadata Enrichment](../architecture/tmdb-metadata-enrichment.md#tmdb-metadata-enrichment) | Existing contract |
| CLAUDE.md:1623–1623 | EPG (Electronic Program Guide): — Actor page "All portals" scope (Electron only): batched DB_MATCH_TITLES worker op (trigram FTS over all… | [TMDB Metadata Enrichment](../architecture/tmdb-metadata-enrichment.md#tmdb-metadata-enrichment) | Existing contract |
| CLAUDE.md:1624–1624 | EPG (Electronic Program Guide): — All DB_MATCH_TITLES consumers (Trending rail, "Because you watched" recommendations rail, cross-portal… | [TMDB Metadata Enrichment](../architecture/tmdb-metadata-enrichment.md#tmdb-metadata-enrichment) | Existing contract |
| CLAUDE.md:1625–1625 | EPG (Electronic Program Guide): — Opt-in via Settings > Metadata (TMDB) (sends titles to TMDB); the section also has a "check key" button… | [TMDB Metadata Enrichment](../architecture/tmdb-metadata-enrichment.md#tmdb-metadata-enrichment) | Existing contract |
| CLAUDE.md:1626–1626 | EPG (Electronic Program Guide): — Match confidence: a provider tmdb_id is a strong hint, not gospel — its payload is weighed against the… | [TMDB Metadata Enrichment](../architecture/tmdb-metadata-enrichment.md#tmdb-metadata-enrichment) | Existing contract |
| CLAUDE.md:1627–1627 | EPG (Electronic Program Guide): — Detail views render provider data immediately; enrichment patches the selection asynchronously… | [TMDB Metadata Enrichment](../architecture/tmdb-metadata-enrichment.md#tmdb-metadata-enrichment) | Existing contract |
| CLAUDE.md:1628–1628 | EPG (Electronic Program Guide): — Cached in SQLite tmdb_metadata (Electron, via DB worker ops DB_GET/SET_TMDB_METADATA, plus… | [TMDB Metadata Enrichment](../architecture/tmdb-metadata-enrichment.md#tmdb-metadata-enrichment) | Existing contract |
| CLAUDE.md:1629–1629 | EPG (Electronic Program Guide): — Service layer: libs/services/src/lib/tmdb/; store glue:… | [TMDB Metadata Enrichment](../architecture/tmdb-metadata-enrichment.md#tmdb-metadata-enrichment) | Existing contract |
| CLAUDE.md:1630–1630 | EPG (Electronic Program Guide): — TMDB attribution (logo + disclaimer) is required and shown in the settings TMDB section and About | [TMDB Metadata Enrichment](../architecture/tmdb-metadata-enrichment.md#tmdb-metadata-enrichment) | Existing contract |
| CLAUDE.md:1631–1631 | EPG (Electronic Program Guide): — See docs/architecture/tmdb-metadata-enrichment.md | [TMDB Metadata Enrichment](../architecture/tmdb-metadata-enrichment.md#tmdb-metadata-enrichment) | Existing contract |
| CLAUDE.md:1635–1635 | Portal Account Info: — Both portal types expose an account-info dialog through the same entry points: header playlist switcher… | [Account Info Dialog](../architecture/stalker-portal.md#account-info-dialog) | Existing contract |
| CLAUDE.md:1642–1642 | Stalker Portal Mode and Endpoint Discovery: — Every resolved Edit commit is guarded by the source connection authority captured when Edit began.… | [Portal Mode and Endpoint Discovery](../architecture/stalker-portal.md#portal-mode-and-endpoint-discovery) | Existing contract |
| CLAUDE.md:1643–1643 | Stalker Portal Mode and Endpoint Discovery: — Portal mode (full vs. simple) follows OBSERVED behavior, never a URL substring. The single predicate is… | [Portal Mode and Endpoint Discovery](../architecture/stalker-portal.md#portal-mode-and-endpoint-discovery) | Existing contract |
| CLAUDE.md:1644–1644 | Stalker Portal Mode and Endpoint Discovery: — Import requires an explicit HTTP(S) scheme but accepts a bare host, /c, or a concrete .php address. It… | [Portal Mode and Endpoint Discovery](../architecture/stalker-portal.md#portal-mode-and-endpoint-discovery) | Existing contract |
| CLAUDE.md:1645–1645 | Stalker Portal Mode and Endpoint Discovery: — The playlist-info Edit dialog loads the complete persisted Stalker row before enabling the form, because… | [Portal Mode and Endpoint Discovery](../architecture/stalker-portal.md#portal-mode-and-endpoint-discovery) | Existing contract |
| CLAUDE.md:1645–1645 | Stalker Portal Mode and Endpoint Discovery: — A metadata-only Save omits connection/mode fields from its queued update, so the stored connection stays… | [Portal Mode and Endpoint Discovery](../architecture/stalker-portal.md#portal-mode-and-endpoint-discovery) | Existing contract |
| CLAUDE.md:1645–1645 | Stalker Portal Mode and Endpoint Discovery: — A persisted portalUrl keeps the row on the Stalker save path even if legacy Xtream fields remain. | [Portal Mode and Endpoint Discovery](../architecture/stalker-portal.md#portal-mode-and-endpoint-discovery) | Existing contract |
| CLAUDE.md:1645–1645 | Stalker Portal Mode and Endpoint Discovery: — Before discovery, PWA acquires a shared playlist-authority barrier plus an exclusive origin-wide… | [Portal Mode and Endpoint Discovery](../architecture/stalker-portal.md#portal-mode-and-endpoint-discovery) | Existing contract |
| CLAUDE.md:1645–1645 | Stalker Portal Mode and Endpoint Discovery: — Add/delete, backup restore, and bulk replacement take the same row lock, while Delete All takes the… | [Portal Mode and Endpoint Discovery](../architecture/stalker-portal.md#portal-mode-and-endpoint-discovery) | Existing contract |
| CLAUDE.md:1645–1645 | Stalker Portal Mode and Endpoint Discovery: — A concurrent Edit or stale dialog fails before remote discovery; a replacement waits for the current owner. | [Portal Mode and Endpoint Discovery](../architecture/stalker-portal.md#portal-mode-and-endpoint-discovery) | Existing contract |
| CLAUDE.md:1645–1645 | Stalker Portal Mode and Endpoint Discovery: — Same-tab Save first publishes its local authentication owner, drains an existing lazy repair through… | [Portal Mode and Endpoint Discovery](../architecture/stalker-portal.md#portal-mode-and-endpoint-discovery) | Existing contract |
| CLAUDE.md:1645–1645 | Stalker Portal Mode and Endpoint Discovery: — PWA fails closed if Web Locks are unavailable, while Electron relies on its single-instance local owner. | [Portal Mode and Endpoint Discovery](../architecture/stalker-portal.md#portal-mode-and-endpoint-discovery) | Existing contract |
| CLAUDE.md:1645–1645 | Stalker Portal Mode and Endpoint Discovery: — The reservation blocks every new authentication (including fingerprint-equivalent URL edits) and repair,… | [Portal Mode and Endpoint Discovery](../architecture/stalker-portal.md#portal-mode-and-endpoint-discovery) | Existing contract |
| CLAUDE.md:1645–1645 | Stalker Portal Mode and Endpoint Discovery: — If discovery returns after its bounded drain while an abandoned authentication is still on the wire, that… | [Portal Mode and Endpoint Discovery](../architecture/stalker-portal.md#portal-mode-and-endpoint-discovery) | Existing contract |
| CLAUDE.md:1645–1645 | Stalker Portal Mode and Endpoint Discovery: — Once Save starts, navigation or dialog destruction does not discard a later successful result: get_profile… | [Portal Mode and Endpoint Discovery](../architecture/stalker-portal.md#portal-mode-and-endpoint-discovery) | Existing contract |
| CLAUDE.md:1645–1645 | Stalker Portal Mode and Endpoint Discovery: — That late commit uses transformPlaylistMeta() inside the per-playlist write queue to merge only… | [Portal Mode and Endpoint Discovery](../architecture/stalker-portal.md#portal-mode-and-endpoint-discovery) | Existing contract |
| CLAUDE.md:1645–1645 | Stalker Portal Mode and Endpoint Discovery: — Success uses one awaited write to atomically replace endpoint, mode, normalized identity and session… | [Portal Mode and Endpoint Discovery](../architecture/stalker-portal.md#portal-mode-and-endpoint-discovery) | Existing contract |
| CLAUDE.md:1645–1645 | Stalker Portal Mode and Endpoint Discovery: — This preserves playback headers and other metadata absent from the form. | [Portal Mode and Endpoint Discovery](../architecture/stalker-portal.md#portal-mode-and-endpoint-discovery) | Existing contract |
| CLAUDE.md:1645–1645 | Stalker Portal Mode and Endpoint Discovery: — Runtime configuration authority covers the observed full/simple mode as well as the session fingerprint,… | [Portal Mode and Endpoint Discovery](../architecture/stalker-portal.md#portal-mode-and-endpoint-discovery) | Existing contract |
| CLAUDE.md:1645–1645 | Stalker Portal Mode and Endpoint Discovery: — A changed authority may rebase only when the persisted row proves that it owns the same playlist ID,… | [Portal Mode and Endpoint Discovery](../architecture/stalker-portal.md#portal-mode-and-endpoint-discovery) | Existing contract |
| CLAUDE.md:1645–1645 | Stalker Portal Mode and Endpoint Discovery: — The transient PlaylistMetaUpdate.stalkerSessionPatch preserves on absence, clears on null, and fully… | [Portal Mode and Endpoint Discovery](../architecture/stalker-portal.md#portal-mode-and-endpoint-discovery) | Existing contract |
| CLAUDE.md:1646–1646 | Stalker Portal Mode and Endpoint Discovery: — executeStalkerRequest() (stores/utils/stalker-request.utils.ts) is the choke point for catalog, content… | [Portal Mode and Endpoint Discovery](../architecture/stalker-portal.md#portal-mode-and-endpoint-discovery) | Existing contract |
| CLAUDE.md:1646–1646 | Stalker Portal Mode and Endpoint Discovery: — Four callers are deliberately outside it because they run below or before the thing it routes on —… | [Portal Mode and Endpoint Discovery](../architecture/stalker-portal.md#portal-mode-and-endpoint-discovery) | Existing contract |
| CLAUDE.md:1646–1646 | Stalker Portal Mode and Endpoint Discovery: — They are exempt from the routing, not from the repair it hooks, but only fetchViaProfile() wires… | [Portal Mode and Endpoint Discovery](../architecture/stalker-portal.md#portal-mode-and-endpoint-discovery) | Existing contract |
| CLAUDE.md:1646–1646 | Stalker Portal Mode and Endpoint Discovery: — Anything new that is not auth or discovery belongs on executeStalkerRequest(). | [Portal Mode and Endpoint Discovery](../architecture/stalker-portal.md#portal-mode-and-endpoint-discovery) | Existing contract |
| CLAUDE.md:1646–1646 | Stalker Portal Mode and Endpoint Discovery: — Existing playlists are repaired LAZILY (StalkerPortalRepairService) — only after a request fails with a… | [Portal Mode and Endpoint Discovery](../architecture/stalker-portal.md#portal-mode-and-endpoint-discovery) | Existing contract |
| CLAUDE.md:1646–1646 | Stalker Portal Mode and Endpoint Discovery: — Before an unrecorded repair reads the persisted source or calls discovery, PWA takes the same… | [Portal Mode and Endpoint Discovery](../architecture/stalker-portal.md#portal-mode-and-endpoint-discovery) | Existing contract |
| CLAUDE.md:1646–1646 | Stalker Portal Mode and Endpoint Discovery: — This prevents repair in another tab from authenticating alongside Edit or crossing delete/restore. | [Portal Mode and Endpoint Discovery](../architecture/stalker-portal.md#portal-mode-and-endpoint-discovery) | Existing contract |
| CLAUDE.md:1646–1646 | Stalker Portal Mode and Endpoint Discovery: — The persisted-row preflight still verifies that the caller owns the failing source, so a late pre-Edit… | [Portal Mode and Endpoint Discovery](../architecture/stalker-portal.md#portal-mode-and-endpoint-discovery) | Existing contract |
| CLAUDE.md:1646–1646 | Stalker Portal Mode and Endpoint Discovery: — Its in-session override is bound to source endpoint, mode, device identity, and credentials; an Edit or… | [Portal Mode and Endpoint Discovery](../architecture/stalker-portal.md#portal-mode-and-endpoint-discovery) | Existing contract |
| CLAUDE.md:1646–1646 | Stalker Portal Mode and Endpoint Discovery: — Each repair installs a session-level authentication fence synchronously, drains the existing token slot… | [Portal Mode and Endpoint Discovery](../architecture/stalker-portal.md#portal-mode-and-endpoint-discovery) | Existing contract |
| CLAUDE.md:1646–1646 | Stalker Portal Mode and Endpoint Discovery: — There is deliberately no eager one-shot migration: a portal that works is never re-probed. | [Portal Mode and Endpoint Discovery](../architecture/stalker-portal.md#portal-mode-and-endpoint-discovery) | Existing contract |
| CLAUDE.md:1647–1647 | Stalker Portal Mode and Endpoint Discovery: — Explicit Edit advances the repair generation before installing its resolved session. Lazy repair captures… | [Portal Mode and Endpoint Discovery](../architecture/stalker-portal.md#portal-mode-and-endpoint-discovery) | Existing contract |
| CLAUDE.md:1648–1648 | Stalker Portal Mode and Endpoint Discovery: — Both transports build the wire format from the same shared builders in @iptvnator/shared/interfaces —… | [Portal Mode and Endpoint Discovery](../architecture/stalker-portal.md#portal-mode-and-endpoint-discovery) | Existing contract |
| CLAUDE.md:1649–1649 | Stalker Portal Mode and Endpoint Discovery: — Simple portals skip the auth lifecycle (no handshake, token or watchdog) but their requests are not… | [Portal Mode and Endpoint Discovery](../architecture/stalker-portal.md#portal-mode-and-endpoint-discovery) | Existing contract |
| CLAUDE.md:1650–1650 | Stalker Portal Mode and Endpoint Discovery: — Contract: docs/architecture/stalker-portal.md ("Portal Mode and Endpoint Discovery", "Request Transport… | [Portal Mode and Endpoint Discovery](../architecture/stalker-portal.md#portal-mode-and-endpoint-discovery) | Existing contract |
| CLAUDE.md:1654–1654 | Stalker Session Authentication: — Full portals authenticate through StalkerSessionService… | [Session Authentication Lifecycle](../architecture/stalker-portal.md#session-authentication-lifecycle) | Existing contract |
| CLAUDE.md:1655–1655 | Stalker Session Authentication: — get_profile's js.status decodes as: full profile/0 = OK, 1 = refused (device-conflict when the message… | [Session Authentication Lifecycle](../architecture/stalker-portal.md#session-authentication-lifecycle) | Existing contract |
| CLAUDE.md:1658–1658 | Stalker Session Authentication: — The handshake is idempotent, so Playlist.stalkerToken is re-presented and get_profile is skipped when it… | [Session Authentication Lifecycle](../architecture/stalker-portal.md#session-authentication-lifecycle) | Existing contract |
| CLAUDE.md:1659–1659 | Stalker Session Authentication: — Watchdog: get_events immediately (init=1), then every watchdog_timeout s (default 120, clamped 30–3600)… | [Session Authentication Lifecycle](../architecture/stalker-portal.md#session-authentication-lifecycle) | Existing contract |
| CLAUDE.md:1664–1664 | Stalker Identity Hardening: — The MAC is canonicalized to 00:1A:79:XX:XX:XX by normalizeStalkerMacAddress (@iptvnator/shared/interfaces)… | [Stalker Identity Policy](../architecture/stalker-portal.md#stalker-identity-policy) | Existing contract |
| CLAUDE.md:1665–1665 | Stalker Identity Hardening: — Format is enforced, the Infomir OUI is advisory only: hasInfomirMacOui drives a hint, never a rejection.… | [Stalker Identity Policy](../architecture/stalker-portal.md#stalker-identity-policy) | Existing contract |
| CLAUDE.md:1672–1672 | Favorites and Recently Viewed: — Per-playlist favorites and global favorites | [Summary](../architecture/portal-detail-navigation.md#summary) | Existing contract |
| CLAUDE.md:1673–1673 | Favorites and Recently Viewed: — Recently viewed tracks watch history | [Summary](../architecture/portal-detail-navigation.md#summary) | Existing contract |
| CLAUDE.md:1674–1690 | Favorites and Recently Viewed: — Live channels in the unified favorites/recent live tab (global collections and a portal's own tabs) carry… | [Summary](../architecture/portal-detail-navigation.md#summary) | Existing contract |
| CLAUDE.md:1694–1694 | Internationalization: — Uses @ngx-translate with 19 language files in apps/web/src/assets/i18n/ | [Features](../../README.md#features) | Existing contract |
| CLAUDE.md:1700–1700 | Environment Detection and Dual-Mode Architecture — The app determines whether it's running in Electron or as a PWA by checking: | [Service factory and build bases](../architecture/pwa-self-hosted.md#service-factory-and-build-bases) | Corrected; see decisions |
| CLAUDE.md:1702–1704 | Environment Detection and Dual-Mode Architecture — typescript window.electron; // truthy in Electron, undefined in browser | [Service factory and build bases](../architecture/pwa-self-hosted.md#service-factory-and-build-bases) | Corrected; see decisions |
| CLAUDE.md:1707–1707 | Why Dual Mode? — IPTVnator supports both Electron (desktop app) and PWA (web browser) to provide flexibility: | [Service factory and build bases](../architecture/pwa-self-hosted.md#service-factory-and-build-bases) | Corrected; see decisions |
| CLAUDE.md:1709–1709 | Why Dual Mode? — Electron: Full-featured desktop experience with local database, external player support (MPV/VLC), and… | [Service factory and build bases](../architecture/pwa-self-hosted.md#service-factory-and-build-bases) | Corrected; see decisions |
| CLAUDE.md:1710–1710 | Why Dual Mode? — PWA: Lightweight web version that runs in any browser without installation | [Service factory and build bases](../architecture/pwa-self-hosted.md#service-factory-and-build-bases) | Corrected; see decisions |
| CLAUDE.md:1714–1714 | Environment-Specific Behavior: — app.config.ts - DataFactory() selects DataService implementation based on environment | [Service factory and build bases](../architecture/pwa-self-hosted.md#service-factory-and-build-bases) | Corrected; see decisions |
| CLAUDE.md:1715–1715 | Environment-Specific Behavior: — app.routes.ts - Same /workspace/... route tree in both environments; guards keep Electron-only routes… | [Service factory and build bases](../architecture/pwa-self-hosted.md#service-factory-and-build-bases) | Corrected; see decisions |
| CLAUDE.md:1716–1718 | Environment-Specific Behavior: — Storage layer switches automatically: - Electron → SQLite/Drizzle ORM →… | [Service factory and build bases](../architecture/pwa-self-hosted.md#service-factory-and-build-bases) | Corrected; see decisions |
| CLAUDE.md:1719–1719 | Environment-Specific Behavior: — External player support (MPV/VLC) only available in Electron | [Service factory and build bases](../architecture/pwa-self-hosted.md#service-factory-and-build-bases) | Corrected; see decisions |
| CLAUDE.md:1720–1720 | Environment-Specific Behavior: — File system operations only available in Electron (uploading playlists from disk) | [Service factory and build bases](../architecture/pwa-self-hosted.md#service-factory-and-build-bases) | Corrected; see decisions |
| CLAUDE.md:1723–1723 | Base Href Configuration: — The app uses different base href values depending on the build target: | [Service factory and build bases](../architecture/pwa-self-hosted.md#service-factory-and-build-bases) | Corrected; see decisions |
| CLAUDE.md:1725–1727 | Base Href Configuration: — Development & PWA: baseHref="/" (from index.html) - Used by: pnpm run serve:frontend, pnpm run… | [Service factory and build bases](../architecture/pwa-self-hosted.md#service-factory-and-build-bases) | Corrected; see decisions |
| CLAUDE.md:1728–1730 | Base Href Configuration: — Electron Production: baseHref="./" (overridden in build config) - Used by: pnpm run build:backend, pnpm… | [Service factory and build bases](../architecture/pwa-self-hosted.md#service-factory-and-build-bases) | Corrected; see decisions |
| CLAUDE.md:1732–1732 | Base Href Configuration: — Build configurations in apps/web/project.json: | [Service factory and build bases](../architecture/pwa-self-hosted.md#service-factory-and-build-bases) | Corrected; see decisions |
| CLAUDE.md:1734–1734 | Base Href Configuration: — production: Electron build with baseHref="./" | [Service factory and build bases](../architecture/pwa-self-hosted.md#service-factory-and-build-bases) | Corrected; see decisions |
| CLAUDE.md:1735–1735 | Base Href Configuration: — pwa: Web deployment with baseHref="/" | [Service factory and build bases](../architecture/pwa-self-hosted.md#service-factory-and-build-bases) | Corrected; see decisions |
| CLAUDE.md:1736–1736 | Base Href Configuration: — development: Dev mode with baseHref="/" from index.html | [Service factory and build bases](../architecture/pwa-self-hosted.md#service-factory-and-build-bases) | Corrected; see decisions |
| CLAUDE.md:1739–1739 | Factory Pattern Implementation: — The factory pattern ensures a single codebase works in both environments without conditional checks… | [Service factory and build bases](../architecture/pwa-self-hosted.md#service-factory-and-build-bases) | Corrected; see decisions |
| CLAUDE.md:1742–1742 | Build Commit In About: — CI injects the git commit into apps/web/src/environments/build-commit.ts via… | [Nightly channel](../architecture/release-pipeline.md#nightly-channel) | Existing contract |
| CLAUDE.md:1745–1745 | Nightly Builds And Update Channel: — Master pushes are the nightly channel. | [Nightly channel](../architecture/release-pipeline.md#nightly-channel) | Existing contract |
| CLAUDE.md:1745–1745 | Nightly Builds And Update Channel: — The leading nightly-version job computes one <patch>-nightly.<commit date>.<run number> version per run… | [Nightly channel](../architecture/release-pipeline.md#nightly-channel) | Existing contract |
| CLAUDE.md:1745–1745 | Nightly Builds And Update Channel: — Settings.updateChannel (Settings → About, Electron only, default stable) is mirrored into the main-process… | [Nightly channel](../architecture/release-pipeline.md#nightly-channel) | Existing contract |
| CLAUDE.md:1745–1745 | Nightly Builds And Update Channel: — AppUpdateService applies the channel to electron-updater before every check (app-update-feed.ts: feed… | [Nightly channel](../architecture/release-pipeline.md#nightly-channel) | Existing contract |
| CLAUDE.md:1745–1745 | Nightly Builds And Update Channel: — Switching back to stable is forward-only: the nightly stays until a newer stable release exists, because a… | [Nightly channel](../architecture/release-pipeline.md#nightly-channel) | Existing contract |
| CLAUDE.md:1745–1745 | Nightly Builds And Update Channel: — The About section's status badge names the channel the verdict describes (status.verdictChannel, stamped… | [Nightly channel](../architecture/release-pipeline.md#nightly-channel) | Existing contract |
| CLAUDE.md:1745–1745 | Nightly Builds And Update Channel: — setChannel re-checks on its own) — a check against an unsaved channel is deliberately not offered. | [Nightly channel](../architecture/release-pipeline.md#nightly-channel) | Existing contract |
| CLAUDE.md:1749–1749 | Testing Strategy — Unit tests: Jest with jest-preset-angular and ng-mocks | [Unit And Type Checks](../architecture/validation-map.md#unit-and-type-checks) | Existing contract |
| CLAUDE.md:1750–1750 | Testing Strategy — E2E tests: Playwright testing the web app and Electron app | [Unit And Type Checks](../architecture/validation-map.md#unit-and-type-checks) | Existing contract |
| CLAUDE.md:1751–1751 | Testing Strategy — Backend tests use standard Jest | [Unit And Type Checks](../architecture/validation-map.md#unit-and-type-checks) | Existing contract |
| CLAUDE.md:1752–1752 | Testing Strategy — Bug fixes should add focused regression coverage unless there is a documented reason not to. | [Unit And Type Checks](../architecture/validation-map.md#unit-and-type-checks) | Existing contract |
| CLAUDE.md:1753–1753 | Testing Strategy — Use the impact-based validation policy in Regression Prevention And Test Updates to choose targeted unit… | [Unit And Type Checks](../architecture/validation-map.md#unit-and-type-checks) | Existing contract |
| CLAUDE.md:1757–1757 | Nx Commands — Use nx CLI for better performance: | [Build and serve commands](../development/agent-workflow.md#build-and-serve-commands) | Moved / consolidated |
| CLAUDE.md:1759–1763 | Nx Commands — bash pnpm nx run <project>:<target> # Example: pnpm nx run web:build # Example: pnpm nx run… | [Build and serve commands](../development/agent-workflow.md#build-and-serve-commands) | Moved / consolidated |
| CLAUDE.md:1765–1765 | Nx Commands — To run multiple projects: | [Build and serve commands](../development/agent-workflow.md#build-and-serve-commands) | Moved / consolidated |
| CLAUDE.md:1773–1773 | Electron Build Process — The Electron backend depends on the web app being built first: | [Build and serve commands](../development/agent-workflow.md#build-and-serve-commands) | Moved / consolidated |
| CLAUDE.md:1775–1775 | Electron Build Process — electron-backend:build depends on web:build | [Build and serve commands](../development/agent-workflow.md#build-and-serve-commands) | Moved / consolidated |
| CLAUDE.md:1776–1776 | Electron Build Process — Output goes to dist/apps/electron-backend (backend) and dist/apps/web (frontend) | [Build and serve commands](../development/agent-workflow.md#build-and-serve-commands) | Moved / consolidated |
| CLAUDE.md:1777–1777 | Electron Build Process — Packaging combines both into distributable | [Build and serve commands](../development/agent-workflow.md#build-and-serve-commands) | Moved / consolidated |
| CLAUDE.md:1781–1781 | Database Migrations — Database initialization is owned by libs/shared/database/src/lib/connection.ts. createTables() creates… | [Upgrade Compatibility And Migrations](../../libs/shared/database/README.md#upgrade-compatibility-and-migrations) | Existing contract |
| CLAUDE.md:1787–1790 | IPC Communication: — 1. Define handler in appropriate events file (e.g., database.events.ts) 2. Register with ipcMain.handle()… | [Adding behavior across layers](../development/agent-workflow.md#adding-behavior-across-layers) | Moved / consolidated |
| CLAUDE.md:1794–1797 | Adding New Playlist Source: — 1. Add type to libs/shared/interfaces/src/lib/playlist.interface.ts 2. Create event handler in… | [Adding behavior across layers](../development/agent-workflow.md#adding-behavior-across-layers) | Moved / consolidated |
| CLAUDE.md:1801–1801 | State Management: — Use NgRx for global application state (M3U playlists, libs/m3u-state) | [Adding behavior across layers](../development/agent-workflow.md#adding-behavior-across-layers) | Moved / consolidated |
| CLAUDE.md:1802–1802 | State Management: — Use NgRx Signal Store with signalStoreFeature() composition for portal/feature state (XtreamStore,… | [Adding behavior across layers](../development/agent-workflow.md#adding-behavior-across-layers) | Moved / consolidated |
| CLAUDE.md:1803–1803 | State Management: — Use NgRx signals for reactive data streams | [Adding behavior across layers](../development/agent-workflow.md#adding-behavior-across-layers) | Moved / consolidated |
| CLAUDE.md:1810–1810 | General Guidelines for working with Nx — For navigating/exploring the workspace, invoke the nx-workspace skill first when it is available - it has… | [General Guidelines for working with Nx](../../AGENTS.md#general-guidelines-for-working-with-nx) | Retained; tools conditional |
| CLAUDE.md:1811–1811 | General Guidelines for working with Nx — When running tasks (for example build, lint, test, e2e, etc.), always prefer running the task through nx… | [General Guidelines for working with Nx](../../AGENTS.md#general-guidelines-for-working-with-nx) | Retained; tools conditional |
| CLAUDE.md:1812–1812 | General Guidelines for working with Nx — Prefix nx commands with the workspace's package manager (e.g., pnpm nx build, npm exec nx test) - avoids… | [General Guidelines for working with Nx](../../AGENTS.md#general-guidelines-for-working-with-nx) | Retained; tools conditional |
| CLAUDE.md:1813–1813 | General Guidelines for working with Nx — You have access to the Nx MCP server and its tools, use them to help the user | [General Guidelines for working with Nx](../../AGENTS.md#general-guidelines-for-working-with-nx) | Retained; tools conditional |
| CLAUDE.md:1814–1814 | General Guidelines for working with Nx — For Nx plugin best practices, check node_modules/@nx/<plugin>/PLUGIN.md. Not all plugins have this file -… | [General Guidelines for working with Nx](../../AGENTS.md#general-guidelines-for-working-with-nx) | Retained; tools conditional |
| CLAUDE.md:1815–1815 | General Guidelines for working with Nx — NEVER guess CLI flags - always check nx_docs or --help first when unsure | [General Guidelines for working with Nx](../../AGENTS.md#general-guidelines-for-working-with-nx) | Retained; tools conditional |
| CLAUDE.md:1819–1819 | Scaffolding & Generators — For scaffolding tasks (creating apps, libs, project structure, setup), ALWAYS invoke the nx-generate skill… | [General Guidelines for working with Nx](../../AGENTS.md#general-guidelines-for-working-with-nx) | Retained; tools conditional |
| CLAUDE.md:1823–1823 | When to use nx_docs — USE for: advanced config options, unfamiliar flags, migration guides, plugin configuration, edge cases | [General Guidelines for working with Nx](../../AGENTS.md#general-guidelines-for-working-with-nx) | Retained; tools conditional |
| CLAUDE.md:1824–1824 | When to use nx_docs — DON'T USE for: basic generator syntax (nx g @nx/react:app), standard commands, things you already know | [General Guidelines for working with Nx](../../AGENTS.md#general-guidelines-for-working-with-nx) | Retained; tools conditional |
| CLAUDE.md:1825–1825 | When to use nx_docs — The nx-generate skill handles generator discovery internally - don't call nx_docs just to look up… | [General Guidelines for working with Nx](../../AGENTS.md#general-guidelines-for-working-with-nx) | Retained; tools conditional |
| CLAUDE.md:1831–1835 | XMLTV Response Compression — Electron decodes HTTP compression before the gzip file layer. For .gz/gzip metadata plus HTTP gzip, a… | [XMLTV response compression](../architecture/m3u-playlist-module.md#xmltv-response-compression) | Existing contract |
| CLAUDE.md:1839–1857 | XMLTV Source Removal — Saving Settings → EPG reconciles cached XMLTV with committed global URLs and all enabled M3U playlist… | [XMLTV source lifecycle](../architecture/m3u-playlist-module.md#xmltv-source-lifecycle) | Existing contract |
| CLAUDE.md:1861–1870 | Web Backend Provider Redirects — All four provider proxy routes use ValidatedHttpClient: automatic redirects are disabled, the initial URL… | [Web Backend](../architecture/pwa-self-hosted.md#web-backend) | Existing contract |
| CLAUDE.md:1874–1879 | Portal Connectivity Preference — Half-open trial slots follow the complete request lifetime with no elapsed-time expiry. All four… | [Desktop preference and account feedback](../architecture/host-connectivity-guard.md#desktop-preference-and-account-feedback) | Existing contract |
| CLAUDE.md:1888–1890 | Portal Connectivity Preference — Both account-info dialogs explain guard refusals with localized paused-request copy and Retry now; Stalker… | [Desktop preference and account feedback](../architecture/host-connectivity-guard.md#desktop-preference-and-account-feedback) | Existing contract |
| CLAUDE.md:1894–1920 | Live TV Panel Levels — Portal live layouts (Xtream live, Stalker itv/radio) fold their panels from the outside in, in three… | [Collapsible Live Sidebar](../architecture/iptvnator-ui-guidelines.md#collapsible-live-sidebar) | Existing contract |
| CLAUDE.md:1924–1930 | Live Channel Return — Xtream and Stalker (including radio) capture displayed playback order on explicit selection. Remote… | [Live channel return and playback order](../architecture/remote-control.md#live-channel-return-and-playback-order) | Existing contract |
| CLAUDE.md:1934–1940 | Stalker Live Search — ITV sidebar and fullscreen searches independently filter the complete selected category; only All Items… | [Full ITV Channel List Cache](../architecture/stalker-portal.md#full-itv-channel-list-cache) | Existing contract |
| CLAUDE.md:1944–1959 | Channel and Detail Keyboard Scrolling — Channel scroll owners use ChannelScrollFocusDirective; pointer selection focuses the viewport, native… | [Detail Scroll and Focus](../architecture/portal-detail-navigation.md#detail-scroll-and-focus) | Existing contract |
File diff suppressed because it is too large.
Load diff
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.