Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
214 commits
Select commit Hold shift + click to select a range
870a610
docs: add anonymous telemetry consent dialog design
lawrenceching Aug 15, 2026
36447c9
docs: add anonymous telemetry consent implementation plan
lawrenceching Aug 15, 2026
ddf6699
feat(core): add anonymousTelemetryConsent to UserConfig
lawrenceching Aug 15, 2026
4d3e6d5
feat(ui): add consent helper and i18n for anonymous telemetry
lawrenceching Aug 15, 2026
2bf70d0
feat(ui): add AnonymousTelemetryConsentDialog
lawrenceching Aug 15, 2026
b9c5f3c
feat(ui): show anonymous telemetry consent on first launch
lawrenceching Aug 15, 2026
92e2689
feat(ui): add anonymous telemetry toggle in General Settings
lawrenceching Aug 15, 2026
12f3d5c
docs: mark anonymous telemetry consent design as implemented
lawrenceching Aug 15, 2026
836ab18
docs: add apps/core importFolder design spec
lawrenceching Aug 16, 2026
e345b00
feat(core-app): scaffold apps/core (package.json, tsconfig, vitest)
lawrenceching Aug 16, 2026
2306798
feat(core-app): add Ports interfaces and network/logger adapters
lawrenceching Aug 16, 2026
15f54c4
feat(core-app): add NodejsFsAdapter and path helpers
lawrenceching Aug 16, 2026
9c43157
feat(core-app): add NetworkFsAdapter mapping FsPort to internal HTTP …
lawrenceching Aug 16, 2026
e715812
feat(core-app): add userConfig and metadata cache path resolution
lawrenceching Aug 16, 2026
b2b9ec5
feat(core-app): add ImportJob model and in-memory JobStore
lawrenceching Aug 17, 2026
b5c3485
feat(core-app): add runtime-agnostic NFO parser
lawrenceching Aug 17, 2026
750a046
feat(core-app): add TmdbClient on NetworkPort
lawrenceching Aug 17, 2026
7108971
test(core-app): cover TmdbClient Authorization header and guard seasons
lawrenceching Aug 17, 2026
054f2c2
feat(core-app): add TvdbClient wrapping @smm/tvdb4 on NetworkPort
lawrenceching Aug 17, 2026
22d6adb
feat(core-app): port episode filename pattern matching to core
lawrenceching Aug 17, 2026
1833af1
test(core-app): cover recognizeEpisodes fallthrough ordering
lawrenceching Aug 17, 2026
51b2cc7
feat(core-app): add media folder recognition orchestrator (NFO → id →…
lawrenceching Aug 17, 2026
6b56ce6
fix(core-app): swallow id-fetch errors so recognition falls through p…
lawrenceching Aug 17, 2026
5f0ea6d
feat(core-app): add importFolder pipeline orchestration (config→persist)
lawrenceching Aug 17, 2026
4a2a554
feat(core-app): add Core class with importFolder API and job lifecycle
lawrenceching Aug 17, 2026
0f92c92
feat(core-app): export public API and register apps/core scripts at r…
lawrenceching Aug 17, 2026
1f6cb3d
fix(core-app): apply final review findings (TVDB search lang, per-ite…
lawrenceching Aug 17, 2026
202bb08
docs: mark apps/core importFolder implementation plan as implemented
lawrenceching Aug 17, 2026
51eb44c
docs: add apps/core read/query and unimport API design spec
lawrenceching Aug 17, 2026
146c088
feat(core-app): add deleteFile to FsPort and both fs adapters
lawrenceching Aug 17, 2026
13cf7c5
feat(core-app): add getAppConfig/getUserConfig/getFolders/getMediaMet…
lawrenceching Aug 17, 2026
1b9f165
docs: mark apps/core read/query and unimport API design as implemented
lawrenceching Aug 17, 2026
bc3200c
docs: add display-folders V3 design (get-folders + useFoldersQuery)
lawrenceching Aug 17, 2026
1ff84f3
docs: add display-folders V3 implementation plan
lawrenceching Aug 17, 2026
0ea4f5e
feat(cli): wire core-app and lazy Core singleton for getFolders
lawrenceching Aug 17, 2026
be9d6eb
feat(cli): add POST /api/get-folders via Core.getFolders
lawrenceching Aug 17, 2026
66f1eac
feat(ui): add useFoldersQuery gated by smm.v3.enabled
lawrenceching Aug 17, 2026
1bf7aa6
feat(ui): Sidebar uses useFoldersQuery paths when smm.v3.enabled
lawrenceching Aug 17, 2026
6d28212
feat(ui): invalidate folders query when UserConfig.folders changes (v3)
lawrenceching Aug 17, 2026
77b910b
docs: mark display-folders V3 design/plan as implemented
lawrenceching Aug 17, 2026
6e8fe15
fix(ui): invalidate folders query on single-folder import (v3)
lawrenceching Aug 17, 2026
ae9c119
feat: route folder delete through Core.unimportFolder when v3 is enabled
lawrenceching Aug 18, 2026
2414fe0
fix(ui): register anonymousTelemetryConsent keys in i18next types
lawrenceching Aug 18, 2026
a1ec21c
docs: add design for smm list CLI command
lawrenceching Aug 18, 2026
772fde5
feat(cli): add smm list to print imported folder paths
lawrenceching Aug 18, 2026
fb2644f
fix(core): serialize smm.json reads and writes with a UserConfig mutex
lawrenceching Aug 18, 2026
70a3237
feat(cli): add smm add to import a folder and wait for init
lawrenceching Aug 18, 2026
7523e50
feat(cli): add smm show and smm metadata for folder inspection
lawrenceching Aug 18, 2026
efe902c
feat(cli): add smm rm to unimport a media folder
lawrenceching Aug 18, 2026
37bc4fd
feat(core): failover TMDB/TVDB hosts and print honest smm add recogni…
lawrenceching Aug 18, 2026
8feb5e0
feat(cli): add --skip-init and CLI e2e for folder commands
lawrenceching Aug 18, 2026
203146d
feat(cli): add HTTP APIs matching smm folder commands
lawrenceching Aug 18, 2026
fae8892
feat(cli): add smm config list/get/set with Core key validation
lawrenceching Aug 18, 2026
cfc5b6a
docs: add Core.renameFolder design for Sidebar rename migration
lawrenceching Aug 18, 2026
b81661a
docs: add Core.renameFolder implementation plan
lawrenceching Aug 18, 2026
845b28e
feat(core): add FsPort.rename for NodejsFsAdapter
lawrenceching Aug 18, 2026
ea26d98
feat(core): stub NetworkFsAdapter.rename as Not Implemented
lawrenceching Aug 18, 2026
1651c4b
feat(core): add Core.renameFolder happy path
lawrenceching Aug 18, 2026
09c371c
test(core): cover renameFolder unmanaged and missing metadata
lawrenceching Aug 18, 2026
22042d6
docs: add UI v3 rename-folder design
lawrenceching Aug 19, 2026
7d53aca
feat: wire v3 folder rename through Core.renameFolder
lawrenceching Aug 19, 2026
c45e78d
docs: add Core tryToRecognizeFolder / applyPlan design
lawrenceching Aug 19, 2026
443b20b
docs: add Core tryToRecognizeFolder implementation plan
lawrenceching Aug 19, 2026
de0fb74
feat(core): add updateMediaFileMetadatas for recognize apply
lawrenceching Aug 19, 2026
71a309f
feat(core): add plan file storage helpers
lawrenceching Aug 19, 2026
352f735
feat(core): add Core.tryToRecognizeFolder
lawrenceching Aug 19, 2026
d6427b2
feat(core): add Core.getPlan and applyPlan for recognize
lawrenceching Aug 19, 2026
310a59f
feat(cli): add smm try-to-recognize and apply
lawrenceching Aug 19, 2026
a925adb
fix(cli): register try-to-recognize and apply in index dispatcher
lawrenceching Aug 19, 2026
43bfa26
docs: add Core tryToRenameFolder / applyPlan rename-files design
lawrenceching Aug 19, 2026
3388cb7
docs: add Core tryToRenameFolder implementation plan
lawrenceching Aug 19, 2026
0d65937
feat(core): add plex/emby TV renameRules
lawrenceching Aug 19, 2026
d44bcb5
feat(core): build TV rename plan file entries
lawrenceching Aug 19, 2026
aa3c710
feat(core): expand rename plan with associated files
lawrenceching Aug 19, 2026
b23bb34
feat(core): add FsPort.mkdir for rename parents
lawrenceching Aug 19, 2026
05221d7
feat(core): add Core.tryToRenameFolder
lawrenceching Aug 19, 2026
beda3c9
feat(core): applyPlan supports rename-files
lawrenceching Aug 19, 2026
3ededf4
feat(cli): add smm try-to-rename and apply rename-files
lawrenceching Aug 19, 2026
83d1c58
test(cli): expand recognize and rename-files e2e coverage
lawrenceching Aug 19, 2026
3610150
feat(core): add FsPort.writeBinaryFile and tmdbImageUrl
lawrenceching Aug 19, 2026
04155a6
feat(core): add checkScrapeCompletion for scrape skip
lawrenceching Aug 19, 2026
9e9700e
feat(core): add downloadScrapeImage for scrape pipeline
lawrenceching Aug 19, 2026
f3a1537
feat(core): add TMDB TV NFO build and XML for scrape
lawrenceching Aug 19, 2026
d9fae8d
feat(core): add TMDB TV scrape task runners
lawrenceching Aug 19, 2026
e56530e
feat(core): add Core.scrapeFolder
lawrenceching Aug 19, 2026
7f6bd44
feat(cli): add smm scrape for TV folders
lawrenceching Aug 19, 2026
2d60457
docs: add Core.scrapeFolder spec and implementation plan
lawrenceching Aug 19, 2026
d46aead
test(cli): expand scrape e2e coverage
lawrenceching Aug 19, 2026
700eae1
test(cli): adopt .e2e.ts suffix for CLI e2e tests
lawrenceching Aug 19, 2026
52ba6ee
feat(scrape): Core media/DB parity, HTTP job API, and UI v3 path
lawrenceching Aug 20, 2026
9d0abf7
feat(cli): print matched mediaFiles tree in smm show
lawrenceching Aug 20, 2026
f0e0bda
feat(core): add renameEpisodeFile with shared rename preflight
lawrenceching Aug 20, 2026
fe09ce7
feat: expose renameEpisodeFile via CLI, AI tool, and MCP
lawrenceching Aug 20, 2026
2b4b74d
feat(cli): support smm --help and unified rename dispatch
lawrenceching Aug 20, 2026
ff2e3a0
feat(scrape): wire AI and MCP scrape/get-job tools with e2e
lawrenceching Aug 21, 2026
8ff3599
feat(core): add platform NetworkPort adapters with proxy and abort
lawrenceching Aug 22, 2026
bdd2417
feat(cli): add smm tmdb search with offline lang validation
lawrenceching Aug 22, 2026
808c3f1
feat(tmdb): add AI and MCP tools via Core v3 with e2e tests
lawrenceching Aug 22, 2026
d1bef6b
feat(mcp): migrate MCP tool tests to MCP Inspector against smm mcp start
lawrenceching Aug 22, 2026
42f69c7
docs(mcp): add README for test/mcp suite
lawrenceching Aug 22, 2026
6daf12a
ci: add e2e:mcp script to run mcp e2e tests
lawrenceching Aug 23, 2026
62a2e78
feat(mcp): move MCP lifecycle into Core and add CLI start/stop tests
lawrenceching Aug 23, 2026
8d4b195
feat(mcp): align Web UI with Core MCP APIs and honor local e2e ports
lawrenceching Aug 23, 2026
7f7edc6
feat(mcp): add Core-style MCP RPC routes for HarmonyOS via core-routes
lawrenceching Aug 23, 2026
06e841e
docs(mcp): update status from draft to done in MCP server documentation
lawrenceching Aug 23, 2026
14b52a7
feat(tmdb): route Web UI and AI tools through Core HTTP APIs
lawrenceching Aug 24, 2026
4f615d7
feat(core): add TVDB supported languages snapshot and offline validation
lawrenceching Aug 24, 2026
26fd0ac
refactor(core): TvdbClient language contract to ISO 639-3 + getLanguages
lawrenceching Aug 24, 2026
466c7d1
feat(core): add searchInTvdb/getTvShowInTvdb/getMovieInTvdb/getTvdbLa…
lawrenceching Aug 24, 2026
a5ce761
feat(cli): add TVDB internal HTTP routes
lawrenceching Aug 24, 2026
6e9a417
feat(cli): add smm tvdb search command
lawrenceching Aug 24, 2026
90b16ed
feat(core-routes): add TVDB AI tool types and execution
lawrenceching Aug 24, 2026
f8e7bd8
feat(core-routes): register TVDB AI tools in chat toolset
lawrenceching Aug 24, 2026
9289f4c
feat(core-routes): register TVDB MCP tools
lawrenceching Aug 24, 2026
743c255
feat(cli): wire TVDB Core runners into MCP and chat hosts
lawrenceching Aug 24, 2026
e6e9702
test(cli): add smm tvdb search e2e
lawrenceching Aug 24, 2026
e8531f9
test(cli): fix tvdb e2e series title regex
lawrenceching Aug 24, 2026
f9ea728
feat(core): TVDB JWT login for custom hosts in media-database transport
lawrenceching Aug 24, 2026
3a89872
test(cli): add end-to-end tests for importing folders in CLI
lawrenceching Aug 24, 2026
e365158
docs: document TVDB internal HTTP routes
lawrenceching Aug 24, 2026
b619c2a
fix(core-routes): wire TVDB AI tools into chat streamText and address…
lawrenceching Aug 24, 2026
7479960
docs(tvdb): mark implemented entry status and gate pending MCP e2e co…
lawrenceching Aug 24, 2026
ff774b7
fix(core): register TVDB tools in AI tool registry (backend-only)
lawrenceching Aug 24, 2026
6b1cdee
docs: add docs for TVDB
lawrenceching Aug 24, 2026
f8b07d7
feat(hello): add smm hello CLI and migrate bootstrap to GET /api/hello
lawrenceching Aug 24, 2026
b0ff197
test(e2e): migrate CLI e2e tests to apps/e2e/cli and add design docs
lawrenceching Aug 24, 2026
ea783d5
refactor: update media metadata handling and improve test coverage
lawrenceching Aug 24, 2026
4b97730
docs: update recognize and rename folder documentation
lawrenceching Aug 24, 2026
f39f768
docs: add design for smm tmdb tv/movie CLI commands
lawrenceching Aug 25, 2026
de97e16
feat(cli): add TMDB details tree formatter for tmdb tv/movie
lawrenceching Aug 25, 2026
bee044c
feat(cli): add smm tmdb tv and tmdb movie get-by-id commands
lawrenceching Aug 25, 2026
9fcce8f
test(e2e): cover smm tmdb tv/movie get and update TMDB docs
lawrenceching Aug 25, 2026
70bb332
docs: add design for smm tvdb tv/movie raw API CLI commands
lawrenceching Aug 25, 2026
1c6c820
feat(core): add getTvdbSeriesById/getTvdbMovieById raw API helpers
lawrenceching Aug 25, 2026
a45c530
feat(cli): add smm tvdb tv and tvdb movie raw get-by-id commands
lawrenceching Aug 25, 2026
03a947d
test(e2e): cover smm tvdb tv/movie get and update TVDB docs
lawrenceching Aug 25, 2026
ffae863
chore(e2e): finish CLI testbed split and expand tmdb get coverage
lawrenceching Aug 25, 2026
cff57d1
docs: add design for CLI manage-plan commands
lawrenceching Aug 25, 2026
d9f0956
feat: align rename-episodes with try/reject/apply plan APIs
lawrenceching Aug 25, 2026
b01996e
docs: add docs recognize-folder.md
lawrenceching Aug 25, 2026
566be7a
docs: add design for CLI smm recognize (folder)
lawrenceching Aug 25, 2026
6b4a98d
docs: add implementation plan for smm recognize folder
lawrenceching Aug 25, 2026
07ef593
feat(core): add recognizeFolder pipelines
lawrenceching Aug 25, 2026
6704188
feat(core): expose tryToRecognizeFolder and recognizeFolder
lawrenceching Aug 25, 2026
a8a9bea
refactor(core): rename tryToRecognizeFolder episodes pipeline to tryT…
lawrenceching Aug 25, 2026
921f729
feat(cli): add smm recognize command
lawrenceching Aug 25, 2026
16209d7
test(e2e): cover smm recognize folder
lawrenceching Aug 25, 2026
7328cde
fix(cli): register recognize in cliCommands dispatch set
lawrenceching Aug 25, 2026
d8ae856
docs: document smm recognize --yes
lawrenceching Aug 25, 2026
8968169
docs: update docs
lawrenceching Aug 26, 2026
a93e625
feat(ui): wire folder recognition to POST /api/recognize-folder
lawrenceching Aug 26, 2026
1de41f8
feat(ui): route TVDB search through POST /api/search-in-tvdb
lawrenceching Aug 26, 2026
abcc163
feat(core): add config/metadata helpers and import library flow
lawrenceching Aug 27, 2026
a9c087d
feat(core): two-phase importLibrary with batch folder registration
lawrenceching Aug 27, 2026
4f2f03e
feat: import-library per-folder tasks with live UI metadata refresh
lawrenceching Aug 27, 2026
34f3d8a
fix(e2e): wait for import-library job before metadata assertions
lawrenceching Aug 27, 2026
e01b642
feat(core): move TMDB asset scrape failover into core with unit tests
lawrenceching Aug 27, 2026
9351fc5
feat(core): add TMDB/TVDB host speed tests, selection, and TCP-only f…
lawrenceching Aug 27, 2026
e75a8f0
fix(e2e): deprecate removeDirInSidebar option in setup function
lawrenceching Aug 27, 2026
a00a3df
fix(ui): map preferMediaLanguage to ISO 639-3 for TVDB v3 search
lawrenceching Aug 27, 2026
b146878
ci: add GitHub Actions job for CLI bun:test e2e
lawrenceching Aug 28, 2026
f475609
ci: extract CLI e2e into reusable workflow with standalone dispatch
lawrenceching Aug 28, 2026
3a0bd9f
fix(ui): resolve eslint react-hooks lint errors
lawrenceching Aug 28, 2026
57029ec
fix: make pnpm run typecheck pass across all packages
lawrenceching Aug 28, 2026
ce49e6c
fix(docker): copy apps/core into cli build context
lawrenceching Aug 28, 2026
057706e
fix(core): extend rename-episode-file to support movie folders
lawrenceching Aug 28, 2026
59962dc
test: remove deprecated test
lawrenceching Aug 28, 2026
d1deff2
fix(ci): restore CLI executable bit after artifact download
lawrenceching Aug 28, 2026
21c50e7
fix(test): create user config directory before reset on CI
lawrenceching Aug 28, 2026
c8a992a
fix(e2e): align CLI test metadata paths with Core userDataDir on Linux
lawrenceching Aug 28, 2026
78ad8f0
test: clean up test cases
lawrenceching Aug 28, 2026
f77b67e
docs: design create-rename-episode-plan Core API and single AI/MCP tool
lawrenceching Aug 29, 2026
46c0254
docs: add create-rename-episode-plan implementation plan
lawrenceching Aug 29, 2026
56717f8
feat(core): add createRenameEpisodePlanPipeline
lawrenceching Aug 29, 2026
030103a
feat(core): expose createRenameEpisodePlan; tryToRenameFolder reuses it
lawrenceching Aug 29, 2026
fa063cc
fix(cli): use Core userDataDir for plan HTTP routes on Linux
lawrenceching Aug 29, 2026
c3e98a2
fix(cli): align remaining plan hosts with userDataDir
lawrenceching Aug 29, 2026
371eb95
feat(core): replace rename begin/add/end tool types with create-renam…
lawrenceching Aug 29, 2026
035d438
feat(cli): HTTP/debug create-rename-episode-plan via Core; remove V2 …
lawrenceching Aug 29, 2026
17f4577
fix(cli): avoid double Error Reason prefix on create-rename-episode-plan
lawrenceching Aug 29, 2026
27e5ff4
feat(core-routes): single create-rename-episode-plan MCP tool
lawrenceching Aug 29, 2026
743ad14
fix(core-routes): always broadcast RenameFilesPlanReady from create-r…
lawrenceching Aug 29, 2026
f20a24d
feat(ui): single CreateRenameEpisodePlan AI tool
lawrenceching Aug 29, 2026
74d1be9
test(e2e): AiTool-RenameTool uses create-rename-episode-plan
lawrenceching Aug 29, 2026
14b9806
docs: document create-rename-episode-plan; remove begin/add/end renam…
lawrenceching Aug 29, 2026
2ede545
docs: show populated files in createRenameEpisodePlan debug example
lawrenceching Aug 29, 2026
6a2cff5
fix(e2e): migrate MCP rename specs to create-rename-episode-plan
lawrenceching Aug 29, 2026
133afd6
test: fix test failure
lawrenceching Aug 29, 2026
27d6dc1
fix(cli): resolve core-app subpath imports in vitest
lawrenceching Aug 29, 2026
7525116
fix(core-routes): narrow createRenameEpisodePlan test result for tsc
lawrenceching Aug 29, 2026
e321aa1
fix(cli): type response.json() in create-rename-episode-plan tests
lawrenceching Aug 29, 2026
3486fdb
docs: add Core media metadata CRUD design
lawrenceching Aug 29, 2026
5bca562
docs: add Core media metadata CRUD implementation plan
lawrenceching Aug 29, 2026
0955236
refactor(core): drop MediaMetadata.files and add metadata RPC types
lawrenceching Aug 29, 2026
e92334e
feat(core): add metadata patch whitelist helper and typed errors
lawrenceching Aug 29, 2026
048af3f
feat(core): metadata CRUD API and separate config/data dirs
lawrenceching Aug 29, 2026
d1bb0cc
fix(core): use metadata root for scrape/recognize pipelines
lawrenceching Aug 29, 2026
a69a2db
feat(cli): add get/create/set/delete-metadata RPC bridges
lawrenceching Aug 29, 2026
1cd3551
fix(cli): map metadata RPC validation failures to 400
lawrenceching Aug 29, 2026
90e72cf
fix(cli): validate metadata RPC field types
lawrenceching Aug 29, 2026
e851c71
feat(ui): read/write media metadata via Core HTTP RPCs
lawrenceching Aug 29, 2026
80ef8c5
refactor(ui): stop persisting metadata via writeFile cache paths
lawrenceching Aug 29, 2026
c95bb10
test(e2e): add browser helpers for metadata HTTP CRUD
lawrenceching Aug 29, 2026
9bf4064
chore(cli): remove legacy read/write MediaMetadata file routes
lawrenceching Aug 29, 2026
6f37b44
fix(e2e): stabilize movie rename context menu on Windows
lawrenceching Aug 29, 2026
5678e3a
fix(core): strip legacy files on metadata read; strict create schema
lawrenceching Aug 29, 2026
fa25b0e
ci: fix ci failure
lawrenceching Aug 30, 2026
b6a07ce
docs: update AGENTS.md
lawrenceching Aug 30, 2026
0d08c7b
ci: fix ci failure
lawrenceching Aug 30, 2026
3863646
fix(ci): resolve create-metadata strict schema and plan path mismatches
lawrenceching Aug 30, 2026
df2e72b
fix(docker): copy apps/core into UI build image
lawrenceching Aug 30, 2026
b8a314b
fix(cli): point MCP, chat, and plan routes at appDataDir
lawrenceching Aug 30, 2026
97c5f49
fix(ui): keep live folder files after metadata persist
lawrenceching Aug 30, 2026
b70792c
fix(ci): drop stale httpproxy specs and files assert
lawrenceching Aug 30, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
88 changes: 88 additions & 0 deletions .github/workflows/_e2e-cli.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
name: E2E Tests for CLI (reusable)

# Bun:test suites under apps/e2e/cli against apps/cli/dist/cli.
# Called by:
# - CI (full run, after build-cli)
# - E2E Tests for CLI (manual workflow_dispatch, after build-cli)
# Expects artifact `cli-dist` from the caller.

on:
workflow_call:
inputs:
test_filter:
description: 'Optional bun test path under apps/e2e/cli (e.g. ./cli/tmdb.test.ts). Empty runs all CLI e2e tests.'
required: false
type: string
default: ''

permissions:
contents: read

jobs:
e2e-cli:
name: E2E Tests for CLI
runs-on: ubuntu-latest
timeout-minutes: 30
env:
TMDB_API_KEY: ${{ secrets.TMDB_API_KEY }}
TVDB_API_KEY: ${{ secrets.TVDB_API_KEY }}
TMDB_HOST: https://api.themoviedb.org/3
TVDB_HOST: https://api4.thetvdb.com/v4
USE_EMBEDDED_HTTP_PROXY: 'true'

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Install pnpm
uses: pnpm/action-setup@v4

- name: Setup Bun
uses: oven-sh/setup-bun@v2
with:
bun-version: latest

- name: Install all dependencies
run: pnpm install --frozen-lockfile

- name: Download CLI build
uses: actions/download-artifact@v4
with:
name: cli-dist
path: apps/cli/dist

- name: Require API key secrets
run: |
missing=0
if [ -z "${TMDB_API_KEY:-}" ]; then
echo "::error::Secret TMDB_API_KEY is empty. Add it under Settings → Secrets and variables → Actions."
missing=1
fi
if [ -z "${TVDB_API_KEY:-}" ]; then
echo "::error::Secret TVDB_API_KEY is empty. Add it under Settings → Secrets and variables → Actions."
missing=1
fi
exit "$missing"

- name: Run CLI E2E tests
run: |
if [ -n "${{ inputs.test_filter }}" ]; then
bun ci/run-cli-e2e-test.ts "${{ inputs.test_filter }}"
else
bun ci/run-cli-e2e-test.ts
fi

e2e-cli-gate:
name: cli-e2e / gate
needs: [e2e-cli]
if: always()
runs-on: ubuntu-latest
steps:
- name: Require CLI E2E job passed
run: |
set -euo pipefail
if [ "${{ needs.e2e-cli.result }}" != "success" ]; then
echo "::error::cli e2e: ${{ needs.e2e-cli.result }}"
exit 1
fi
echo "CLI E2E job passed."
28 changes: 22 additions & 6 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,13 @@ name: CI

# Merged from build.yml + e2e-test.yml + e2e-docker.yml + e2e-http-proxy.yml.
# E2E groups run only after the build pipeline (test / lint / typecheck / build) succeeds.
#
# CLI bun:test e2e: reusable _e2e-cli.yml (also callable via "E2E Tests for CLI" workflow).
#
# Required check names (RELEASE_REQUIRED_CHECKS) must stay stable:
# Run Unit Tests, Lint UI, Typecheck, Build UI, Build CLI,
# host-e2e / gate, docker-e2e / gate, http-proxy-e2e / gate
# (cli-e2e / gate is optional for release until added to RELEASE_REQUIRED_CHECKS)
on:
push:
branches: [ main, develop ]
Expand All @@ -15,6 +19,8 @@ on:
- 'pnpm-workspace.yaml'
- 'pnpm-lock.yaml'
- '.github/workflows/ci.yml'
- '.github/workflows/_e2e-cli.yml'
- '.github/workflows/e2e-cli.yml'
pull_request:
branches: [ main, develop ]
paths:
Expand All @@ -24,6 +30,8 @@ on:
- 'pnpm-workspace.yaml'
- 'pnpm-lock.yaml'
- '.github/workflows/ci.yml'
- '.github/workflows/_e2e-cli.yml'
- '.github/workflows/e2e-cli.yml'
workflow_dispatch:

permissions:
Expand Down Expand Up @@ -169,7 +177,9 @@ jobs:
spec: "./test/specs/ai/*.e2e.ts"
artifact_prefix: ai
- name: Run Config and HTTP Proxy Tests
spec: "./common/config/*.e2e.ts ./common/httpproxy/*.e2e.ts"
# Proxy-through-custom-host specs live under common/config (*WithHttpProxy).
# common/httpproxy/* was removed in 78ad8f00.
spec: "./common/config/*.e2e.ts"
artifact_prefix: config-httpproxy
- name: Run MCP Tests
spec: "./common/mcp/*.e2e.ts"
Expand Down Expand Up @@ -319,7 +329,7 @@ jobs:

e2e-docker:
name: ${{ matrix.name }}
needs: build-image
needs: [build-image]
runs-on: ubuntu-latest
timeout-minutes: 90
env:
Expand All @@ -341,11 +351,9 @@ jobs:
matrix:
include:
- name: Docker E2E (config)
# Includes *WithHttpProxy specs (former common/httpproxy suite).
spec: "./common/config/*.e2e.ts"
artifact_prefix: docker-config
- name: Docker E2E (httpproxy)
spec: "./common/httpproxy/*.e2e.ts"
artifact_prefix: docker-httpproxy
- name: Docker E2E (mcp)
spec: "./common/mcp/*.e2e.ts"
artifact_prefix: docker-mcp
Expand Down Expand Up @@ -411,7 +419,7 @@ jobs:
run: gunzip -c smm-latest.tar.gz | docker load

- name: Require API key secrets for suites that need them
if: matrix.artifact_prefix == 'docker-httpproxy' || matrix.artifact_prefix == 'docker-media-init'
if: matrix.artifact_prefix == 'docker-config' || matrix.artifact_prefix == 'docker-media-init'
run: |
missing=0
if [ -z "${TMDB_API_KEY:-}" ]; then
Expand Down Expand Up @@ -556,3 +564,11 @@ jobs:
exit 1
fi
echo "All HTTP Proxy E2E jobs passed."

# ------------------------------------------------------------------
# CLI E2E (bun:test under apps/e2e/cli) — reusable _e2e-cli.yml
# ------------------------------------------------------------------
e2e-cli:
needs: [build-cli]
uses: ./.github/workflows/_e2e-cli.yml
secrets: inherit
55 changes: 55 additions & 0 deletions .github/workflows/e2e-cli.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
name: E2E Tests for CLI

# Manual-only entry for CLI bun:test e2e (apps/e2e/cli).
# Builds CLI, then calls reusable _e2e-cli.yml (same job used by CI).
#
# For full CI (unit + host/docker/http-proxy + CLI e2e), use the CI workflow.

on:
workflow_dispatch:
inputs:
test_filter:
description: 'Optional bun test path under apps/e2e/cli (e.g. ./cli/tmdb.test.ts). Empty runs all CLI e2e tests.'
required: false
type: string
default: ''

permissions:
contents: read

jobs:
build-cli:
name: Build CLI
runs-on: ubuntu-latest

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Install pnpm
uses: pnpm/action-setup@v4

- name: Setup Bun
uses: oven-sh/setup-bun@v2
with:
bun-version: latest

- name: Install all dependencies
run: pnpm install --frozen-lockfile

- name: Build CLI
run: cd apps/cli && pnpm run build

- name: Upload build artifacts
uses: actions/upload-artifact@v4
with:
name: cli-dist
path: apps/cli/dist
retention-days: 7

e2e-cli:
needs: [build-cli]
uses: ./.github/workflows/_e2e-cli.yml
with:
test_filter: ${{ inputs.test_filter }}
secrets: inherit
25 changes: 25 additions & 0 deletions .superpowers/sdd/task-3-fix-report.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Task 3 Important Findings Fix Report

## Status

Fixed metadata-root propagation and made Core metadata create/update operations atomic within the existing `MediaMetadataHelper` path mutex.

## Changes

- Added `Core.getMetadataRoot()` and used it for metadata helpers, scrape/recognition/rename/import pipelines, and plan persistence operations.
- Added `MediaMetadataHelper.createIfAbsent()` so existence check and write share one path lock.
- Added `MediaMetadataHelper.updateIfPresent()` so read-modify-write patches share one path lock.
- Added focused regressions for distinct metadata roots, concurrent creates, and concurrent non-overlapping patches.

## Verification

- Red phase: all three new regressions failed for the expected reasons.
- `pnpm exec vitest run src/Core.metadataCrud.test.ts`: 11 tests passed.
- `pnpm test` in `apps/core`: 45 files and 313 tests passed.
- `pnpm typecheck` in `apps/core`: passed.
- IDE lint diagnostics for changed TypeScript files: none.

## Residual

- Locking remains process-local, matching the existing helper design; no distributed or cross-process lock was added.
- A corrupt existing cache is not overwritten: create reports already-exists based on the physical file, while update reports not-found because the helper cannot read valid metadata.
109 changes: 109 additions & 0 deletions .superpowers/sdd/task-3-report.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
# Task 3 Report: Core metadata CRUD and separate roots

## Status

Implemented the requested Core metadata CRUD API and separated user configuration storage from application metadata storage.

## Changes

- Added `Core.getMetadata(folderPath)`, which returns persisted metadata or throws `MetadataNotFoundError`.
- Added `Core.createMetadata(mm)`, which writes new metadata or throws `MetadataAlreadyExistsError`.
- Replaced the old full-document `setMetadata(mm)` API with `setMetadata(folderPath, patch)`, using Task 2's `applyMetadataPatch`.
- Added idempotent `Core.deleteMetadata(folderPath)`.
- Kept null-if-missing reads and full-document writes private to Core through `MediaMetadataHelper`.
- Wired `UserConfigHelper` to `userDataDir` and `MediaMetadataHelper` to `reportedAppDataDir ?? appDataDir`.
- Wired CLI `getCore()` with `getAppDataDir()` for application data and `getUserDataDir()` for configuration.
- Passed the split roots through the import pipeline so imports continue to read/write configuration and metadata in their respective locations.
- Migrated Core and CLI consumers away from the removed public `getMediaMetadata` and full-document `setMetadata` methods.

## TDD evidence

### RED

Command:

```bash
cd apps/core && pnpm exec vitest run src/Core.metadataCrud.test.ts
```

Result: failed as expected — 8 tests failed. The new methods were absent (`core.getMetadata is not a function`, `core.createMetadata is not a function`), and the old `setMetadata` signature rejected the new call shape.

The failing tests covered:

- get missing metadata
- create then get
- duplicate create
- patch merge
- patch missing metadata
- illegal patch key
- idempotent delete
- separate metadata/config roots

### GREEN

Command:

```bash
cd apps/core && pnpm exec vitest run src/Core.metadataCrud.test.ts
```

Result: passed — 8/8 tests.

The separate-root CLI integration test initially exposed that `ImportFolderPipeline` still used one root for both stores. After passing `userDataDir` separately, the previously failing `FolderMetadata.test.ts` passed.

## Verification

- `cd apps/core && pnpm test && pnpm typecheck`: passed, 45 files / 310 tests, followed by a clean Core TypeScript check.
- `cd apps/core && pnpm exec vitest run src/Core.metadataCrud.test.ts src/Core.test.ts`: passed, 80 tests in the required Task 3 suites.
- `cd apps/cli && pnpm exec vitest run src/cli/folderDisplay.test.ts src/route/FolderMetadata.test.ts src/route/Scrape.test.ts`: passed, 3 files / 14 tests.
- IDE lint diagnostics for edited files: no errors.

## Known concern

`apps/cli` typecheck remains blocked by existing Task 1 migration debt: several unrelated files still reference the removed `MediaMetadata.files` property. The Task 3 Core typecheck passes; Task 3 did not reimplement the prior migration.

## Commit

Planned commit message: `feat(core): metadata CRUD API and separate config/data dirs`
# Task 3 Report: Align plan HTTP appDataDir with Core

## Status

Completed and committed as `fa063cc4` (`fix(cli): use Core userDataDir for plan HTTP routes on Linux`).

## Changes

- `apps/cli/src/route/Plans.ts`: plan HTTP routes now use `getUserDataDir()`.
- `apps/cli/src/mcp/mcp.ts`: MCP plan-writing tools now use `getUserDataDir()`.
- `apps/cli/server.ts`: chat plan-writing tools now use `getUserDataDir()`.
- `apps/cli/src/route/Plans.test.ts`: added a split-directory regression test proving `/api/createPlan` writes only under `USER_DATA_DIR/plans`.

## Audit

- `apps/cli/src/route/coreRoutesConfig.ts` retains `getAppDataDir()` because its callers perform list-files, get-episodes, rename-folder, and rename-files HTTP operations rather than plan persistence. Changing it would relocate metadata-cache reads outside this task.
- Plan persistence hosts in `Plans.ts`, `mcp.ts`, and `server.ts` now match `getCore().appDataDir`.
- No second plan store was introduced.

## TDD and Verification

- RED: the focused test failed because no plan existed under `USER_DATA_DIR/plans`.
- GREEN: focused regression passed (1 test).
- Full CLI suite passed: 73 files and 474 tests; 2 files and 13 tests skipped.
- CLI `tsc --noEmit` passed.
- Changed-file lint diagnostics and `git show --check` passed.

## Self-review

- Commit contains only the three plan-host wiring changes and regression test.
- Unrelated dirty E2E and documentation files were not staged or committed.
- No correctness issues found. The core-routes `appDataDir` field is overloaded for plan and metadata dependencies in chat/MCP, but Core's directory is the required compatibility behavior for these plan-producing hosts.

## Important review follow-up

- `apps/cli/src/coreRoutesServer.ts` now supplies `getUserDataDir()` to the shared core-routes handler.
- Startup and shutdown stale-plan cleanup in `apps/cli/index.ts` now scan `userDataDir`.
- The legacy rename and recognition plan writers now store plans under `getUserDataDir()/plans`.
- Added `apps/cli/src/coreRoutesServer.test.ts`; its RED run received `/metadata/app-data`, and its GREEN run received `/core/user-data`.
- Focused plan-route tests passed: 2 files and 2 tests.
- Full CLI tests passed: 74 files and 475 tests; 2 files and 13 tests skipped.
- CLI `tsc --noEmit` and changed-file lint diagnostics passed.
23 changes: 23 additions & 0 deletions .superpowers/sdd/task-4-fix-report.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Task 4 Important Findings Fix Report

## Status

Fixed metadata RPC request validation so malformed JSON, invalid Zod input, and invalid Core metadata patches return 400 validation ProblemDetails.

## Changes

- Mapped `ZodError` and malformed-JSON `SyntaxError` to `urn:smm:problem:metadata-validation`.
- Exported and matched Core metadata errors with `instanceof` instead of error-name strings.
- Required create requests to contain a plain-object `data` with `mediaFolderPath: string`.
- Restricted set patches to a strict plain object containing only `type`, `mediaFiles`, `tvShow`, and `movie`.
- Added regressions for malformed JSON, missing `mediaFolderPath`, array patches, and complete 404 ProblemDetails fields.

## Verification

- Red phase: three regressions failed as expected (malformed JSON returned 500, missing `mediaFolderPath` returned 500, and `patch: []` returned 200).
- `pnpm exec vitest run src/route/metadata`: 4 files and 8 tests passed.
- IDE lint diagnostics for changed TypeScript files: none.

## Scope

No Task 5+ code or unrelated E2E/log artifacts were changed.
Loading
Loading