main() sliced argv at the first occurrence of a known subcommand name,
so a value-flag pair whose value names a subcommand (e.g. login's
--server given `search`) made argparse dispatch the wrong subparser:
`jellyfin --server search browse ...` errored inside the `search`
sub-parser instead of running browse.
Dispatch now splits such misplaced pairs out of the top-level argv
(find_subcommand_token + split_misplaced_value_pairs) and re-attaches
them to the command tail, where each handler's parse_known_args already
tolerates unknown flags. A properly placed occurrence of the same flag
later in the tail still wins. Any other pre-command token (unknown
flags, stray positionals, `--`, dangling value flags) is untouched, so
argparse errors stay byte-identical to the pre-hardening CLI.
Also dedupe the twice-repeated "Bundled CLI --dry-run and exit-code
contract" section in references/worked-recipes.md (user-testing round 1
finding); content merged into one section.
Adds DispatchHardeningTests: the mis-slice scenario for every
subcommand shape, clean-argv dispatch for all 11 subcommands, flag
priority, argparse-owned error paths, and unit pinning of both helper
return-value tables.
Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
2026-08-30 00:45:16 -04:00
Magnus Hedemarkandfactory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
jellyfin: send the access token over exactly ONE channel per request (drop
the simultaneous X-Emby-Token header; the MediaBrowser Token= parameter is
the sole transport, legacy fallback remains documented as substitute-never-
stack and is request-capture tested); remove the dead no-op conditional in
JellyfinClient.__init__; make the login error-path test exception-safe with
patch.object; document the test-pinned dry-run plan keys and the actual
0/1/2 exit-code mapping in worked-recipes and SKILL.md.
peertube: replace the stale dry-run shape prose ('url'/'form') with the
test-pinned {dry_run, method, path, params} / form_fields keys; harden
cmd_me against a non-dict role (no AttributeError) with regression tests;
remove the dead client facade, the unused cmd_channels variable, and the
unused List/Tuple imports (ruff F401/F841 clean).
ghost: fold the 5 nested with-statements (ruff SIM117) in test_ghost.py
into single with-statements.
All three skills double-runner + proxy-trap green (25/56/37 tests);
validate-evals, paired smoke, quality validator, core gates, and catalog
check modes green.
Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
2026-08-29 20:32:06 -04:00
Magnus Hedemarkandfactory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
Full lastfm-model rebuild of the jellyfin skill against the 12.0-era
OpenAPI spec, core-dev authorization guidance, and server source:
- Document the researched auth sequence end to end: complete pre-token
Authorization: MediaBrowser Client/Device/DeviceId/Version header
required by POST /Users/AuthenticateByName (400 "Error processing
request." without it), AccessToken returned, then Token= on the same
header (legacy X-Emby-Token deprecated, disableable since 10.11,
targeted for removal at 12.0).
- Extend scripts/jellyfin: new `login` subcommand demonstrating the
pre-token header and printing session exports (password via
stdin/prompt/env only), seasons/episodes TV navigation, next-up
--series-id, browse --user-id (userId is required on non-API-key
auth per the ItemsController guard), modern Token= header transport
with X-Emby-Token fallback, 503 Retry-After handling, search
Id/deprecated-ItemId fallback.
- Add 5 cited reference files (auth/sessions, endpoint catalog,
user-scoping matrix, gotchas field guide, worked recipes) plus
quick-connect; all cite api.jellyfin.org and live-verified sources.
- Upgrade relocated scripts/test_jellyfin_cli.py to the double-runner
standard: 24 tests (was 8) covering help, argument errors, dry-run,
mocked login header sequence, TV navigation, search-id fallback, and
jq-executed pipeline-consumability chains; zero egress proven via
proxy-trap rerun.
- Add evals/evals.json (6 cases incl. emby-install-not-for-jellyfin
negative probe); rewrite SKILL.md (224 lines) and README; sync root
README blurb and skill-triggers row; regenerate marketplace.json and
llms.txt (description-embedding artifacts).
Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>