Skip to content

refactor(upload): move the upload core into its own package - #9120

Merged
NotThatKindOfDrLiz merged 28 commits into
mainfrom
dw-author-divinemobile-is8301-9b2035fc964503049a2b4e281650d5eae7a517fb
Sep 15, 2026
Merged

NotThatKindOfDrLiz merged 28 commits into
mainfrom
dw-author-divinemobile-is8301-9b2035fc964503049a2b4e281650d5eae7a517fb

Conversation

@dcadenas

@dcadenas dcadenas commented Sep 13, 2026 •

Copy link
Copy Markdown
Member

Description

The upload core had already been decomposed inside the app, but it could not be reused or tested as a package of its own, and its tests could not run without the full app. This change moves the upload core (orchestration, persistence, retry, recovery, and the pending-upload model) into mobile/packages/upload_repository, leaving the Flutter, plugin, and lifecycle wiring in the app as a thin facade.

Related Issue: Closes #8301

What Changed

  • New upload_repository package with its own analysis config, tests, Hive adapters, and CI workflow. Its pubspec declares no Flutter runtime dependency; the direct dependencies are dio, hive_ce, meta, and the in-workspace blossom_upload_service, models, nostr_sdk, and unified_logger.
  • App-side dependencies (crash reporting, connectivity, thumbnails, blurhash, transient-render cleanup, telemetry, platform facts, background lifecycle) are injected ports. UploadManager stays in the app and keeps the BackgroundAwareService registration and recovery wiring.
  • Behavior is unchanged: persisted Hive type IDs, upload, retry, and recovery semantics, and telemetry phase names all stay the same. The package owns the phase names and PublishPhases refers to them, so a rename on either side is a compile error rather than something a test has to catch.
  • The god-file growth ceiling moved with the core instead of being dropped. The guard scans the package root through SERVICE_GOD_FILE_EXTRA_SCAN_DIRS and accepts a verified Git rename or copy from the modified-path diff for the provenance claim. The baseline row is packages/upload_repository/lib/src/upload_repository.dart at 1,867 lines with # renamed-from: lib/services/upload_manager.dart, so the file cannot grow past the ceiling retired by upload_manager.dart while the epic(maintainability): reduce oversized files, complexity, and general code drag #4339 split is open.
  • The facade re-exports an eight-name allowlist instead of the whole package, so app files no longer pick up storage internals by accident; the files that use those names carry explicit show clauses. The app-side thumbnail typedef is now VideoThumbnailExtractor, distinct from the package's ThumbnailExtractor, which removes the hide/alias import plumbing.
  • Dead code and test-only surface are removed: UploadConnectivity.other (no producer), an unreachable connectivity branch, and UploadManager.getUserFriendlyErrorMessage with its private mapping. The suites call the package reporter's static API directly, and removed map entries use a wildcard discard instead of unawaited(...), so the lint stays enabled and a genuinely dropped future would still be caught.
  • The store suite moved into the package: 40 tests run against the packaged PendingUploadStore on a package-local Hive home and an injected opener port, and the app keeps 3 adapter integration tests.
  • Extraction leftovers are gone: the package reporter tests use the static APIs, the intentional no-op comments are restored in the facade, the carried // rethrow; is deleted, and the "pure-Dart" wording is corrected to "no direct Flutter dependency" in the facade, the package dartdoc, and the stale reference in crash_reporter.dart.

Out of Scope

Verification

  • App: dart format --set-exit-if-changed and flutter analyze lib test integration_test tools: clean. At the merged head (8537ef1d), the full plain flutter test run reports 20,520 pass, 52 skip, and 3 fail, all three in the Docker-dependent test/manual/ acceptance suite that CI tags out.
  • Affected app suites (upload manager, upload services, publish classification, publish timeline) with DIVINE_STRICT_CHANNELS=true: 147 pass, 9 skipped.
  • packages/upload_repository: flutter analyze clean; flutter test --coverage: 190 tests, 840/1490 lines (56.4%) against the 40% floor.
  • packages/models: flutter analyze clean; flutter test: 972 tests pass.
  • God-file ceiling guard test: 22 pass, including the verified-copy case. The full 67-script guard sweep passes 64; the three failures are pre-existing environment checks (a live route probe and two Codemagic-only iOS scripts) and are unrelated to this change.
  • CI on the branch (6e33b55): all checks green, one skipped, none failing, including Analyze, Format, Generated Files, Goldens, all four test shards, Integration Tests (services), and both build jobs. The head has since merged main, and required CI runs again for the merged head.
  • .codex/scripts/test-config.sh and the .github/scripts/tests suite (110 tests): pass.

Validation gaps: mergeability and semantic-title are reusable CI workflows and not locally runnable. The unfiltered flutter test also runs Docker-dependent manual acceptance tests under test/manual/ that CI excludes with --exclude-tags integration; those fail locally without the local stack and are unrelated to this change.

Type of Change

  • ✨ New feature (non-breaking change which adds functionality)
  • 🛠️ Bug fix (non-breaking change which fixes an issue)
  • ❌ Breaking change (fix or feature that would cause existing functionality to change)
  • 🧹 Code refactor
  • ✅ Build configuration change
  • 📝 Documentation
  • 🗑️ Chore

@dcadenas
dcadenas requested a review from a team as a code owner September 13, 2026 00:47
@dcadenas
dcadenas requested review from NotThatKindOfDrLiz and realmeylisdev and removed request for a team September 13, 2026 00:47
@github-actions

This comment has been minimized.

@NotThatKindOfDrLiz NotThatKindOfDrLiz left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The extraction appears behavior-preserving, and all current checks are green. I found two package-boundary issues that should be resolved before merge:

  1. mobile/scripts/check_service_god_file_ceiling.sh:32 only scans mobile/lib/services, while this PR removes the old upload_manager.dart baseline entry and moves the still-oversized implementation to mobile/packages/upload_repository/lib/src/upload_repository.dart. That leaves the 1,868-line core with no mechanical growth ceiling. Deferring the split to #4339 is reasonable, but please preserve an equivalent package baseline/provenance constraint or deliberately broaden the guard so the file cannot grow while that work remains outstanding.

  2. mobile/test/services/upload/pending_upload_store_test.dart:13 directly tests the newly packaged PendingUploadStore, but its roughly 987 lines remain outside the package test tree and therefore do not contribute to the package's 40% coverage floor. The store already accepts an injected box opener. Please move the core store coverage into the package and retain only app/plugin adapter integration coverage in the app, or document the concrete dependency that prevents establishing that boundary.

Please also clean up the small extraction artifacts while touching this area:

  • Point the package reporter tests at the static APIs and remove the test-only instance delegators at mobile/packages/upload_repository/lib/src/upload_progress_reporter.dart:154 and mobile/packages/upload_repository/lib/src/upload_progress_reporter.dart:313.
  • Restore the intentional no-op rationale removed from mobile/lib/services/upload_manager.dart:182 and mobile/lib/services/upload_manager.dart:185.
  • Remove the carried-forward commented-out // rethrow; at mobile/packages/upload_repository/lib/src/upload_repository.dart:244.
  • Replace "pure-Dart" at mobile/lib/services/upload_manager.dart:1 with the accurate "no direct Flutter dependency" wording; nostr_sdk and unified_logger remain Flutter-dependent packages.

Afterward, please rerun package tests with coverage, the app upload suites, analysis, generated-file/ratchet checks, and required CI.

@dcadenas

Copy link
Copy Markdown
Member Author

@NotThatKindOfDrLiz, all six items are addressed at 91bfa7b1a. Five commits moved the branch:

  • cc6b20c81 removes the test-only instance delegators from the package reporter, so its tests call the static APIs; restores the intentional no-op comments in the facade; deletes the carried // rethrow;; and corrects the "pure-Dart" wording in the app-side file you cited.
  • 58b12ad19 moves the store suite into the package. Its 40 tests now run against the packaged PendingUploadStore on a package-local Hive home and an injected opener port; the app keeps 3 adapter integration tests covering the helper-backed round trip. Package coverage at this head is 190 tests / 56.30% lines against the 40% floor.
  • faf55d4e0 carries the retired god-file ceiling into the package. The guard now scans mobile/packages/upload_repository/lib through SERVICE_GOD_FILE_EXTRA_SCAN_DIRS and accepts a verified Git copy for the provenance claim, with the baseline row packages/upload_repository/lib/src/upload_repository.dart at 1,867 lines and # renamed-from: lib/services/upload_manager.dart. The file cannot grow past the old ceiling while epic(maintainability): reduce oversized files, complexity, and general code drag #4339 is open.
  • b4dba65a5 fixes two stale references found while rerunning checks: the "pure-Dart" wording in the package dartdoc, and the old services/upload/upload_ports.dart path in crash_reporter.dart.
  • 91bfa7b1a drops a pathspec that narrowed the provenance diff, so git matches a copy or rename against the whole tree.

Dispositions:

Validation at this head: dart format and flutter analyze clean in both roots; package flutter test --coverage 190 tests / 56.30%; full app suite 20,418 pass / 36 skip; upload-focused suites 274 pass; god-file ceiling guard test 22 pass including the new copy case. The full guard sweep passes 64 of 66 scripts; the two failures reproduce on a clean main checkout or against live infrastructure and are unrelated to this change.

Required CI for the head has not finished yet. @realmeylisdev already has a pending review request and the head moved, so please both take a look at the updated state.

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@realmeylisdev realmeylisdev left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dcadenas I reviewed 91bfa7b1a and pushed nine commits to this branch (head is now a7515646b0), one per finding so you can revert any of them on its own. The extraction itself is clean — everything below is boundary hygiene and dead code in the seams, not the move.

Pushed

Package boundary — the cluster worth looking at first

  • 0cb168fb19 The facade traded three narrow show re-exports for export 'package:upload_repository/upload_repository.dart', so all 35 files importing upload_manager.dart got PendingUploadStore, UploadRetryPolicy, UploadProgressReporter, VideoCircuitBreaker and the Hive box opener in scope. That reopens, at the facade, the boundary this PR exists to draw, and nothing catches it: check_layer_direction.sh only rejects providers/services/repositories/state importing screens/widgets/router, not UI reaching storage internals. It now re-exports an eight-name allowlist, and the seven app files that had swapped a narrow model import for the whole barrel carry a show clause for the one or two names each uses. flutter analyze lib test integration_test is clean, which is the check that the allowlist is complete.
  • 4f449d0bcd ThumbnailExtractor was declared in both libraries, so the facade imported the package twice (once hide, once aliased show), re-exported it with a hide, and bridged the two. Two test files already import both libraries; the first reference to that name from either would have been an ambiguous import naming two declarations that read identically in source. Nothing outside the facade ever named the app typedef, so it is now VideoThumbnailExtractor and the hide/alias plumbing is gone. The adapter stays — your port carries just the path and VideoThumbnailService returns a timestamp with it.

Dead code and test-only surface

  • 0536762e5e UploadConnectivity.other had no producer anywhere. _checkConnectivity returns none for everything it does not recognise, which is what UploadProgressReporter.checkNetworkConnectivity did before the extraction, so the 'Unknown' network-type string and the 'ConnectivityResult.other' crash-report value were both unreachable. Removing the member keeps both switches exhaustive and the reported values identical.
  • edfcbd53a9 _checkConnectivity ended with if (results.contains(none)) return none; immediately above return none;.
  • 4f44c9ddf0 UploadManager.getUserFriendlyErrorMessage and its private _mapConnectivity had no production callers — only 15 call sites across two app test files. That is the shape cc6b20c81 deleted from UploadProgressReporter, re-created one layer up, and it made a second ConnectivityResult -> UploadConnectivity mapping something to keep in step with _checkConnectivity. Both suites now call UploadProgressReporter.userFriendlyErrorMessage directly, the way the package's own tests already do; the drift guard still guards the same copy. The classification suite no longer needs an UploadManager, so its fixture went too.
  • bb29c6572d unawaited() wrapped three Map<String, Future<void>>.remove() calls. The value those return is the future being removed — the one whose whenComplete is running — not a newly started operation, so the wrapper silenced discarded_futures while asserting the opposite. A wildcard discard says what is true and satisfies the lint without suppressing it, so a genuinely dropped future there would still be caught. Kept to one line so upload_repository.dart stays at exactly its 1,867-line ceiling.

Duplication and CI

  • fe1e208261 UploadPhases restated six telemetry strings PublishPhases already owned, with a new test asserting the six pairs equal. That is a test compensating for duplication: it covered only the copied six, so a seventh phase on either side would have been unguarded. The package now owns the names and PublishPhases refers to them, so divergence is a compile error; the parity test goes with the duplication it policed.
  • e83af3d0f7 This one touches your most recent commit, so to be explicit: it keeps the whole-tree provenance match you added in 91bfa7b1a and only drops --find-copies-harder, which asks git to consider every unmodified file in the repo as a copy source. Git answers warning: you may want to set your diff.renameLimit variable to at least 7243 and degrades to "only found copies from modified paths" anyway. A claimed source is a modified path by definition — the move either deletes it or leaves a facade — so plain --find-copies finds the same pair. Measured here: identical C087 lib/services/upload_manager.dart -> packages/upload_repository/lib/src/upload_repository.dart, 0.02s instead of 0.55s, without the two spurious copy pairs the harder scan invented between unrelated new files. The guard still honours the claim.
  • a7515646b0 Two things I found re-reading my own diff: the classifyPublishErrorMessage dartdoc named video_publish_service_test.dart as its drift guard, which contains no such assertion (it has always been publish_error_classification_test.dart); and my export comment overstated the allowlist, since the inherited circuitBreaker parameter takes a VideoCircuitBreaker that is deliberately not re-exported because nothing passes one.

Not pushed

The god-file guard covers one package by name. EXTRA_SCAN_DIRS defaults to packages/upload_repository/lib, and [[ -d "$dir" ]] || continue means it sees exactly that one. Nineteen files under mobile/packages/*/lib are already over 1,500 lines and stay invisible — dm_repository.dart at 9,283, relay_pool.dart at 3,739, blossom_upload_service.dart at 3,466 and so on.

I am deliberately not broadening it here, and I want to be clear it is not a defect in this PR. At the merge base the guard scanned only mobile/lib/services, so packages were never covered; this PR narrows that gap by one rather than opening it. @NotThatKindOfDrLiz's review offered "preserve an equivalent package baseline/provenance constraint or deliberately broaden the guard", and you took the first option, which is a legitimate reading. Broadening it properly means globbing packages/*/lib and seeding nineteen ceilings — including a 10,118-line generated app_database.steps.dart the current exclusions do not filter — which is a separate change with its own review. Worth a follow-up issue; happy to file one if you want it tracked.

Package coverage floor at 40 against 56.4 measured. I measured 56.44% at this head. You have already explained the 40 to Liz — floors are not raised automatically and #4339 will move covered code back out — so this is a note rather than a request. The cost is that coverage can fall sixteen points with CI green and no signal. Either way I could not have changed it: .github/workflows/upload_repository.yaml is a platform-sensitive path and I am on @divinevideo/reviewers, not @divinevideo/platform, so that file is outside my branch-modification authority.

lib/hive_registrar.g.dart — I was wrong about this one. I had it down as a dead file in the package's public lib/ root with no callers. It is dead in the sense that nothing calls registerAdapters() (the real registration is explicit in upload_initialization_helper.dart:148,151), but deleting it is not the fix: hive_ce_generator:hive_registrar_generator re-emits it for any package containing a @HiveType. I deleted it, ran dart run build_runner build in the package, and it came straight back byte-identical with git status clean. Its location is the generator's choice, and AGENTS.md names hive_registrar.g.dart among the artifacts to commit. Leaving it as is.

One finding folded into another: the PendingUpload import deleted from video_event_publisher.dart and video_publish_service.dart is resolved by the allowlist rather than separately. With the whole package re-exported, those two files depending on the re-export was accidental; with a deliberate eight-name allowlist it is the declared contract, and adding a second import for names the facade already re-exports trips unnecessary_import.

Validation at a7515646b0

  • dart format clean on all 22 changed Dart files; flutter analyze lib test integration_test and the package's lib test both clean.
  • Package: 190 tests pass, flutter test --coverage 841/1490 lines = 56.44% against the 40 floor.
  • App: the publish, upload-progress, provider, model and upload suites, plus every touched test file — 1,767 and 677 in the two runs, all pass. The pre-push hook ran the affected suites again on the way out.
  • 25 ratchets run directly, all OK, including check_service_god_file_ceiling.sh (rename claim still honoured, 1,867 unchanged), check_layer_direction, check_package_*, and the test-quality set.
  • CI was green on 91bfa7b1a before this push, so anything red now is mine to fix.

@NotThatKindOfDrLiz your review sits on 8cb18f66f and the head has moved twice since — you already have a pending request, so I have not created a duplicate one, but the six items you raised are worth a look at the current state. @dcadenas please re-read the nine commits above and revert anything you disagree with; the merge decision stays yours.

@dcadenas

Copy link
Copy Markdown
Member Author

@realmeylisdev, re-read all nine commits and kept every one; none reverted. The allowlist export, the VideoThumbnailExtractor rename, the dead UploadConnectivity.other, the unreachable connectivity branch, the test-only error-message delegators, and PublishPhases referring to UploadPhases all leave behavior unchanged, and dropping --find-copies-harder still matches the same rename pair.

A second independent review of a751564 came back ready; its two low-severity findings are fixed:

  • 6e33b55 points the models dedup TODO at packages/upload_repository/lib/src/pending_upload.dart instead of the old app path. Comment-only, one file, +4/-2.
  • The description no longer claims a parity test pins the phase lists (they are bound by compile-time reference) and no longer says the provenance check scans the whole tree (it matches rename and copy sources in the modified-path diff).

Validation at the final head:

  • Format and analyze clean in the app, upload_repository, and models.
  • models: 972 tests pass.
  • upload_repository: 190 tests, 840/1490 lines (56.4%) against the 40% floor.
  • Affected app suites: 147 pass, 9 skipped.
  • God-file ceiling guard test: 22 pass. The 66-script guard sweep passes 64, with the same two failures that reproduce on clean main or against live infrastructure.
  • CI was green at a751564; it runs again for the new head.

No merge or approval from me; the state is open for review. @NotThatKindOfDrLiz your review sits on 8cb18f6 and the head has moved twice since; the six items you raised are worth a look at the current state.

@github-actions

This comment has been minimized.

@NotThatKindOfDrLiz NotThatKindOfDrLiz left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re-reviewed at 6e33b55. The six issues from my prior review are resolved, the subsequent boundary-cleanup commits are sound, and all required and relevant checks passed on this exact head. Ready to merge.

@NotThatKindOfDrLiz

Copy link
Copy Markdown
Member

Overlap heads-up: this package extraction intersects #9108 in upload_manager.dart and recovery tests, #9102 across ten Hive-sensitive upload tests, and #9147 in async-safety baselines and agent guidance. This is the common collision point. Please coordinate merge order and rebase after the smaller fixes land, preserving disposed-manager behavior, Hive isolation, behavioral coverage, and the reduced guardrail baselines.

@dcadenas

Copy link
Copy Markdown
Member Author

Synchronized the branch with main: 6e33b55 → 8537ef1d. Three commits, two of them merges of main plus the package Hive-home helper. The branch is published, so this is a merge commit rather than a rebase: no force-push, no history rewrite, the existing commits stay as they are.

The merge takes main at 057700c7, which includes #9102, #9147, #9150, #9175 and the rest of current main. What needed resolution:

  • mobile/test/services/upload/pending_upload_store_test.dart: kept the app-side adapter test, dropped its unused Hive import, and adopted main's Hive test-home helper so the new global-Hive guard passes.
  • mobile/scripts/baseline/service_god_file_sizes.txt: kept main's reduced ceilings (video_event_publisher 2291, video_event_service 6389) and the package row at 1867 with its rename provenance.
  • Added mobile/packages/upload_repository/test/helpers/hive_test_home.dart, because main's guard now scans package tests too.
  • async_safety_counts.txt merged to the union of both sides' removed rows.

Validation at 8537ef1d:

  • dart format and flutter analyze clean.
  • Plain flutter test: 20,520 pass, 52 skip, 3 fail; all three are the Docker-dependent test/manual/ acceptance tests that CI excludes.
  • packages/upload_repository: 190 tests pass. packages/models: 972 tests pass.
  • Guard sweep: 64 of 67 pass; the three failures are pre-existing environment checks (a live route probe and two Codemagic-only iOS scripts), none related to this change.
  • Checks: running on 8537ef1d. The CLA check passed; at the first read the remaining workflows were queued or in progress.

@realmeylisdev @NotThatKindOfDrLiz this push makes the existing approvals stale, so please take another look. On the overlap heads-up: #9108 is still open and touches the same file, so whichever of the two lands second will need a small reconciliation; #9102, #9147, #9150 and #9175 are already in this branch.

@dcadenas
dcadenas requested review from a team, NotThatKindOfDrLiz, hm21, rabble and realmeylisdev and removed request for a team September 14, 2026 18:08
@github-actions

This comment has been minimized.

@NotThatKindOfDrLiz

Copy link
Copy Markdown
Member

@dcadenas, please rebase this branch onto fresh origin/main and push with --force-with-lease. The current head contains two merges from main, but the repository workflow requires feature branches to rebase and explicitly says never to merge main into them. After the rewritten head is published, please let the required checks finish and re-request the current reviewers.

@NotThatKindOfDrLiz

Copy link
Copy Markdown
Member

Updated overlap heads-up: this package extraction also intersects #9057 in upload initialization/provider cleanup and draft #8467 in video publishing and its tests. Please coordinate merge order; after either lands, rebase onto fresh origin/main and preserve Hive-open isolation, package boundaries, audio-reuse policy, and publishing coverage.

dcadenas and others added 22 commits September 15, 2026 12:58
`UploadConnectivity.other` had no producer. `UploadManager._checkConnectivity`
returns `none` for every result it does not recognise, which matches what
`UploadProgressReporter.checkNetworkConnectivity` did before the extraction,
so the `'Unknown'` network-type string and the `'ConnectivityResult.other'`
crash-report value were both unreachable.

Removing the member keeps both switches exhaustive, preserves the reported
values exactly, and stops every future switch on this enum from paying for
a case that cannot occur.
`_checkConnectivity` ended with `if (results.contains(none)) return none;`
immediately followed by `return none;`, so the branch could never alter the
result. It also made the priority ladder read as if an explicit "no network"
answer were distinguished from an unrecognised one, which it is not.
`UploadManager.getUserFriendlyErrorMessage` and its private
`_mapConnectivity` had no production callers: the app reaches the copy
through `UploadRepository`, and these two existed purely so two app test
files could keep their old call shape. That is the shape cc6b20c deleted
from `UploadProgressReporter`, re-created one layer up, and it made a
second `ConnectivityResult -> UploadConnectivity` mapping something we had
to keep in step with `_checkConnectivity`.

Both test files now call `UploadProgressReporter.userFriendlyErrorMessage`
directly, the way the package's own tests already do, so the drift guard
still guards the same copy without an app-side shim to carry it. The
classification suite no longer needs an `UploadManager` at all, so its
fixture and the imports that fed it go too.
The facade declared `ThumbnailExtractor` while the package declares one
too, so the library imported the package twice -- once `hide`, once
aliased `show` -- re-exported it with a `hide`, and bridged the two with
an adapter. Two files already import both libraries; the first reference
to that name from either of them would have been an ambiguous import
naming two declarations that look identical in source.

Nothing outside this library ever named the app typedef, so renaming it
to `VideoThumbnailExtractor` removes the collision and the double import,
alias and hide that existed only to work around it. The adapter stays: the
package's port carries just the path, and `VideoThumbnailService` returns a
timestamp with it.
The facade replaced three narrow `show` re-exports with
`export 'package:upload_repository/upload_repository.dart'`, so all 35
files importing `upload_manager.dart` got `PendingUploadStore`,
`UploadRetryPolicy`, `UploadProgressReporter`, `VideoCircuitBreaker` and
the Hive box opener in scope. That reopens, at the facade, the boundary
this PR exists to draw, and nothing guards it: check_layer_direction.sh
only rejects providers/services/repositories/state importing
screens/widgets/router, not UI reaching storage internals.

Re-export only the upload vocabulary that appears in `UploadManager`'s own
signatures, and give the seven app files that had swapped a narrow model
import for the whole barrel a `show` clause for the one or two names each
actually uses. The Hive adapters are an initialization concern, so the
helper and the five suites that register them import them directly rather
than reaching them through the facade.

`flutter analyze lib test integration_test` is clean, which is the check
that the allowlist is complete.
`UploadPhases` restated six telemetry strings that `PublishPhases` already
owned, and a new test asserted the six pairs were equal. That is a test
compensating for duplication rather than a single source of truth: it
covered only the six copied constants, so a seventh phase added to either
side would have been unguarded, and a key drift would surface as a failing
test rather than as a compile error.

The upload leg is timed inside the package, so the package owns the names
and `PublishPhases` refers to them. Divergence is now impossible to write,
and the parity test goes with the duplication it existed to police.
`unawaited()` wrapped three `Map<String, Future<void>>.remove()` calls.
The value those return is the future being removed -- the same one whose
`whenComplete` callback is running -- not a newly started operation. The
wrapper silenced `discarded_futures` while asserting the opposite of what
is happening, so anyone auditing fire-and-forget work had three false
positives to rule out.

A wildcard discard says what is actually true: the returned value is
thrown away. It also satisfies the lint without suppressing it, so a
genuinely dropped future here would still be caught.
The provenance check ran `git diff` with `--find-copies-harder` and no
pathspec, which asks git to consider every *unmodified* file in the repo as
a candidate copy source. On this branch git answers with `warning: you may
want to set your diff.renameLimit variable to at least 7243` and degrades to
"only found copies from modified paths" anyway.

A claimed rename source is a modified path by definition -- the move either
deletes it or leaves a facade behind -- so plain --find-copies finds the same
pair. Measured on this branch: identical
`C087 lib/services/upload_manager.dart -> packages/upload_repository/lib/src/upload_repository.dart`,
0.02s instead of 0.55s, and without two spurious copy pairs the harder scan
invented between unrelated new files. The guard still honours the claim.
Two follow-ups from re-reading this branch's own diff:

The `classifyPublishErrorMessage` dartdoc named
`video_publish_service_test.dart` as the drift guard, which contains no
such assertion -- the guard has always been the category table in
`publish_error_classification_test.dart`. Wrong enough to send the next
reader to the wrong file.

The export comment claimed the allowlist covers everything in
`UploadManager`'s signatures, which overstates it: the inherited
`circuitBreaker` parameter takes a `VideoCircuitBreaker` that is
deliberately not re-exported, because nothing passes one. Say what the
list is instead -- what callers use -- so reaching past the facade stays
a visible act rather than looking like an oversight.
@NotThatKindOfDrLiz
NotThatKindOfDrLiz force-pushed the dw-author-divinemobile-is8301-9b2035fc964503049a2b4e281650d5eae7a517fb branch from 935c851 to 26f83bd Compare September 15, 2026 17:59
@NotThatKindOfDrLiz

Copy link
Copy Markdown
Member

@dcadenas I completed the authorized takeover and rebased this branch onto the current origin/main at 445cc6807d without merge commits. While reconciling the extraction, I preserved the observable Hive box-opening behavior from #9057 and the disposal/race guards from #9108 in both the packaged upload repository and app facade. I also fixed the generated-files failure by isolating the Hive home change in the remaining app test.

Current head: 26f83bd4882f4bbabd099c43d19b1ba7e45db9f5.

All review items are fixed; none were declined or escalated. All 23 exact-head checks have completed successfully, aside from the expected skipped daily service-result publication job. The branch is clean, linear, and GitHub reports it mergeable.

Please review the takeover changes and merge when you are ready; the merge decision remains yours. @hm21 and @realmeylisdev are still requested reviewers.

@NotThatKindOfDrLiz NotThatKindOfDrLiz left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved at 26f83bd4882f4bbabd099c43d19b1ba7e45db9f5 after the takeover rebase onto current origin/main. The reconciliation preserves #9057 Hive-opening observability and #9108 disposal/race protections, and the remaining Hive test mutation is isolated. All exact-head checks passed (with only the expected daily service-result publication job skipped). Ready to merge.

@NotThatKindOfDrLiz
NotThatKindOfDrLiz added this pull request to the merge queue Sep 15, 2026
Merged via the queue into main with commit 40e00ea Sep 15, 2026
23 checks passed
@NotThatKindOfDrLiz
NotThatKindOfDrLiz deleted the dw-author-divinemobile-is8301-9b2035fc964503049a2b4e281650d5eae7a517fb branch September 15, 2026 18:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

refactor(upload): lift the blocker-free upload core into packages/upload_repository

4 participants