Skip to content

feat: streaming list rewrite#103

Merged
woutervanranst merged 13 commits into
masterfrom
streaming-list-and-restore
Jun 11, 2026
Merged

feat: streaming list rewrite#103
woutervanranst merged 13 commits into
masterfrom
streaming-list-and-restore

Conversation

@woutervanranst

@woutervanranst woutervanranst commented Jun 10, 2026

Copy link
Copy Markdown
Owner

Summary

  • rewrite the list query flow to stream repository and local overlay results instead of materializing a full listing
  • add CLI/output updates for list state display and optional local path handling
  • tighten chunk index and hydration status plumbing to support the new list/restore behavior across CLI, explorer, and tests

Notes

  • includes related README and AGENTS updates
  • includes OpenSpec change artifacts captured during the rewrite

Summary by CodeRabbit

Release Notes

  • New Features

    • Enhanced arius ls output with file state indicators (showing hydration, availability, and local presence)
    • Added optional [path] argument to arius ls for validating local file overlay directories
  • Improvements

    • Storage tier information now tracked for archived/cold files to enable smarter handling
    • Optimized chunk index lookups with concurrent prefix loading
  • Documentation

    • Updated CLI documentation for ls filtering and snapshot selection options
    • Clarified storage tier hint semantics in index format

@coderabbitai

coderabbitai Bot commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

The PR refactors the list-query and chunk-index subsystems to support storage-tier awareness and state-based entry modeling. It replaces boolean existence flags with a composable RepositoryEntryState enum, introduces StorageTierHint persistence throughout the chunk-index pipeline (wire format, SQLite, repair), rewrites ListQueryHandler into a bounded-channel three-stage pipeline, and updates all consumers (CLI ls command, Explorer views, hydration queries) to use the new models. Documentation updates, CLI state formatter, and comprehensive test coverage align the system end-to-end.

Changes

Repository state flags and tier-aware listing rewrite

Layer / File(s) Summary
Specifications and rewrite documentation
AGENTS.md, README.md, openspec/changes/*
AGENTS.md adds pre-release breaking-change guidance and pipeline/logging conventions; README.md documents ls files listing and chunk-index tier semantics; openspec documents define staged architecture and tier wire/storage formats.
Repository entry state and list contracts
src/Arius.Core/Features/ListQuery/ListQuery.cs, src/Arius.Core/Shared/Storage/IBlobContainerService.cs
RepositoryEntryState [Flags] enum introduced; RepositoryEntry, RepositoryFileEntry, RepositoryDirectoryEntry refactored to carry RepositoryEntryState instead of existence/hydration booleans; BlobListItem gains optional Tier field.
Shard format tier support and serialization
src/Arius.Core/Shared/ChunkIndex/Shard.cs
ShardEntry record extended with StorageTierHint field; serialize/TryParse updated for 4-field (large) and 5-field (small) formats with trailing tier wire value; SerializeTier/DeserializeTier/ParseTier helpers handle wire-value conversion and validation.
Chunk-index tier persistence and lookup infrastructure
src/Arius.Core/Shared/ChunkIndex/ChunkIndexLocalStore.cs, src/Arius.Core/Shared/ChunkIndex/ChunkIndexService.cs, src/Arius.Core/Shared/ChunkIndex/IChunkIndexService.cs, src/Arius.AzureBlob/AzureBlobContainerService.cs, src/Arius.Tests.Shared/Storage/FakeInMemoryBlobContainerService.cs, src/Arius.Core/Features/ArchiveCommand/ArchiveCommandHandler.cs
ChunkIndexLocalStore persists StorageTierHint via storage_tier_hint SQLite column; ChunkIndexService enables concurrent prefix loading via Parallel.ForEachAsync with bounded worker count and adds structured logging (debug cache hits, info for remote validation/download); repair operation scans TAR tier metadata and propagates tier to rebuilt entries (or throws if parent TAR missing); blob listings now populate Tier; ArchiveCommandHandler writes UploadTier to ShardEntry; IChunkIndexService members narrowed to internal.
List query refactor to bounded-channel pipeline
src/Arius.Core/Features/ListQuery/ListQueryHandler.cs
ListQueryHandler converts to three-stage bounded-channel pipeline: Stage 1 (WalkTreeAsync) iterative depth-first walk with immediate local directory snapshot overlay (TopDirectoryOnly); Stage 2 (ResolveAsync) batched chunk-index lookups computing RepositoryEntryState from tier and local presence; Stage 3 consuming, counting, and logging. Pointer hashes no longer read.
Consumer updates for state-based entry handling
src/Arius.Core/Features/ChunkHydrationStatusQuery/ChunkHydrationStatusQuery.cs, src/Arius.Explorer/RepositoryExplorer/RepositoryExplorerViewModel.cs, src/Arius.Explorer/RepositoryExplorer/FileItemViewModel.cs
ChunkHydrationStatusQuery filters by RepositoryEntryState.Repository flag; FileItemViewModel and RepositoryExplorerViewModel derive colors/status from State bitflags using HasFlag checks for hydration/archive/rehydrating.
CLI ls state rendering and local path
src/Arius.Cli/Commands/Ls/LsStateFormatter.cs, src/Arius.Cli/Commands/Ls/LsVerb.cs, src/Arius.Cli.Tests/Commands/Ls/ListQueryParsingTests.cs, src/Arius.Cli.Tests/Commands/Ls/LsStateFormatterTests.cs
LsStateFormatter provides ToChars and ToMarkup rendering of 4-character RepositoryEntryState cells with colored tier output; LsVerb adds optional positional [path] argument with Directory.Exists validation, streams output per entry via MarkupLine, removes Recorder-based audit capture approach; comprehensive state-formatter and CLI parsing tests added.
List query handler and overlay tests
src/Arius.Core.Tests/Features/ListQuery/ListQueryHandlerTests.cs
Tests renamed from cloud-only to repository-only scenarios; assertions refactored to verify RepositoryEntryState flags; tier-aware shard seeding throughout; new tier-hint-to-state mapping test added; overlay merge, pointer case-sensitivity, and size-lookup tests updated for state semantics.
Explorer and hydration status tests
src/Arius.Explorer.Tests/RepositoryExplorer/FileItemViewModelTests.cs, src/Arius.Explorer.Tests/RepositoryExplorer/RepositoryExplorerViewModelTests.cs
FileItemViewModelTests and RepositoryExplorerViewModelTests refactored to construct RepositoryFileEntry using RepositoryEntryState flags; list-query stream fixtures and view-model assertions updated for state-based semantics.
Shard serialization and wire format tests
src/Arius.Core.Tests/Shared/ChunkIndex/ShardTests.cs, src/Arius.Core.Tests/Shared/ChunkIndex/ShardSerializerTests.cs
ShardTests parameterized over BlobTier with StorageTierHint round-trip assertions; field-count expectations changed to 4/5 fields; invalid parse cases now reject tier-less legacy lines and invalid wire values; tier-wire-mapping stability test added.
Local store tier persistence tests
src/Arius.Core.Tests/Shared/ChunkIndex/ChunkIndexLocalStoreTests.cs
New parameterized tier round-trip test; all ShardEntry constructions updated to include explicit BlobTier; persistence assertions verify StorageTierHint survives across upserts, prefix updates, synchronization, and cache clearing.
Service scenario, flush, and lookup concurrency tests
src/Arius.Core.Tests/Shared/ChunkIndex/ChunkIndexService*Tests.cs
Archive scenario, flush, and lookup tests updated to construct ShardEntry with BlobTier; new concurrency test verifies batched prefix loading; repair tests verify tier propagation and missing-parent-tar failure behavior with exception.
Archive and restore feature tests
src/Arius.Core.Tests/Features/ArchiveCommand/ArchiveRecoveryTests.cs, src/Arius.Core.Tests/Features/ChunkHydrationStatusQuery/ResolveFileHydrationStatusesHandlerTests.cs, src/Arius.Core.Tests/Features/RestoreCommand/RestoreCommandHandlerTests.cs
ArchiveRecoveryTests matrix test verifies UploadTier recorded as StorageTierHint; hydration status and restore handler tests updated for tier/state parameters; hydration filtering updated to repository-state basis.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~75 minutes

Possibly related PRs

  • woutervanranst/Arius7#95: Tier-aware chunk-index repair and thin-chunk metadata handling directly overlap with this PR's repair operation tier derivation from parent TAR and tier propagation during rebuild.
  • woutervanranst/Arius7#20: Both PRs refactor the CLI audit logging approach for ls—this PR removes Recorder capture and streams output directly, while PR #20 introduced the file-based audit infrastructure that replaced prior console recording.
  • woutervanranst/Arius7#100: Both PRs modify archive handler code, particularly tier propagation into chunk-index entries, making them code-level related.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch streaming-list-and-restore

@codecov

codecov Bot commented Jun 10, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 92.83489% with 23 lines in your changes missing coverage. Please review.
✅ Project coverage is 80.50%. Comparing base (e9c1c4d) to head (e5f010e).
⚠️ Report is 1 commits behind head on master.

Files with missing lines Patch % Lines
.../Arius.Core/Features/ListQuery/ListQueryHandler.cs 95.37% 5 Missing and 3 partials ⚠️
src/Arius.Cli/Commands/Ls/LsVerb.cs 83.87% 5 Missing ⚠️
src/Arius.Core/Shared/ChunkIndex/Shard.cs 91.17% 1 Missing and 2 partials ⚠️
...kHydrationStatusQuery/ChunkHydrationStatusQuery.cs 60.00% 0 Missing and 2 partials ⚠️
...s.Explorer/RepositoryExplorer/FileItemViewModel.cs 77.77% 0 Missing and 2 partials ⚠️
.../RepositoryExplorer/RepositoryExplorerViewModel.cs 60.00% 0 Missing and 2 partials ⚠️
src/Arius.Cli/Commands/Ls/LsStateFormatter.cs 95.23% 0 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master     #103      +/-   ##
==========================================
+ Coverage   80.11%   80.50%   +0.39%     
==========================================
  Files          90       91       +1     
  Lines        6045     6166     +121     
  Branches      799      824      +25     
==========================================
+ Hits         4843     4964     +121     
+ Misses        977      974       -3     
- Partials      225      228       +3     
Flag Coverage Δ
linux 83.39% <93.81%> (+0.38%) ⬆️
windows 79.30% <92.83%> (+0.41%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@woutervanranst woutervanranst changed the title Rewrite streaming list and restore feat: streaming list rewrite Jun 10, 2026

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 6

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/Arius.Core.Tests/Shared/ChunkIndex/ShardSerializerTests.cs (1)

46-48: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Add tier assertions for stream-based deserialization paths.

Line 46 and Line 88 only assert size fields; they should also assert StorageTierHint to fully cover the new shard tier contract in both Deserialize(Stream, ...) test paths.

Suggested test patch
@@
         loaded.TryLookup(FakeContentHash('e'), out var e).ShouldBeTrue();
         e!.OriginalSize.ShouldBe(512);
+        e.StorageTierHint.ShouldBe(BlobTier.Archive);
@@
         loaded.TryLookup(FakeContentHash('8'), out var e).ShouldBeTrue();
         e!.CompressedSize.ShouldBe(40);
+        e.StorageTierHint.ShouldBe(BlobTier.Cool);

As per coding guidelines, test-project reviews should prioritize coverage gaps and assertion quality.

Also applies to: 88-90

Source: Coding guidelines

🧹 Nitpick comments (4)
README.md (1)

310-312: 💤 Low value

Optional: specify language for fenced code block.

The shard line format example is in an unlabeled fenced code block. Consider adding ```text to improve markdown hygiene.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@README.md` around lines 310 - 312, Update the unlabeled fenced code block
that shows the shard line format example (the block containing "`<content-hash>
<chunk-hash> <original-size> <compressed-size> <tier>`") to include an explicit
language label by changing the opening fence to "```text" so the example is
rendered as plain text and improves markdown hygiene.

Source: Linters/SAST tools

openspec/changes/2026-06-10-rewrite/PLAN.MD (1)

64-66: 💤 Low value

Optional: specify language for fenced code block.

The ASCII pipeline diagram is in an unlabeled fenced code block. Consider adding ```text to improve markdown hygiene, though this is purely cosmetic.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@openspec/changes/2026-06-10-rewrite/PLAN.MD` around lines 64 - 66, Add a
language label to the fenced code block that contains the ASCII pipeline diagram
(the block starting with ``` and the content `Walk (×1) ─► walkItemChannel
(bounded) ─► Resolve (×1) ─► entryChannel (bounded) ─► Handle (yield)`) by
changing the opening fence to ```text so the block is explicitly marked as plain
text; this is a purely cosmetic markdown hygiene change and requires updating
only the fenced code block around that pipeline string.

Source: Linters/SAST tools

src/Arius.Cli.Tests/Commands/Ls/LsStateFormatterTests.cs (1)

38-58: ⚡ Quick win

Add explicit ToMarkup assertions for ~ and ? tier outputs.

Current markup tests cover hydrated/archived/absent dots, but not rehydrating and unknown-tier paths, which are emitted by the formatter and surfaced in CLI output.

Suggested additions
+    [Test]
+    public void ToMarkup_Rehydrating_UsesExpectedColor()
+    {
+        var state = RepositoryEntryState.Repository | RepositoryEntryState.RepositoryArchived | RepositoryEntryState.RepositoryRehydrating;
+        LsStateFormatter.ToMarkup(state).ShouldBe("[dim].[/][dim].[/]R[purple]~[/]");
+    }
+
+    [Test]
+    public void ToMarkup_UnknownTier_RendersQuestionMark()
+    {
+        var state = RepositoryEntryState.Repository;
+        LsStateFormatter.ToMarkup(state).ShouldBe("[dim].[/][dim].[/]R?");
+    }
As per coding guidelines, “Test projects. Focus on test coverage gaps and assertion quality rather than style.”
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/Arius.Cli.Tests/Commands/Ls/LsStateFormatterTests.cs` around lines 38 -
58, Add explicit assertions to LsStateFormatterTests to cover the rehydrating
and unknown-tier outputs emitted by LsStateFormatter.ToMarkup: update or add
tests (e.g., in ToMarkup_PresentFlags_AreColored or new test methods) that call
LsStateFormatter.ToMarkup with state combinations that produce the rehydrating
marker (~) and the unknown-tier marker (?) and assert the exact markup strings
include "~" and "?" with the expected coloring/formatting; reference
LsStateFormatter.ToMarkup and RepositoryEntryState flags to construct the input
states that produce those outputs so the tests fail if those markers are omitted
or misformatted.

Source: Coding guidelines

src/Arius.AzureBlob/AzureBlobContainerService.cs (1)

184-198: Clarify tier behavior for GetBlobsAsync and guard against null tiers

  • BlobTraits.None only requests “default information”; AccessTier/AccessTierInferred come from the List Blobs response contract, not from the BlobTraits flags—so this mapping (Tier = FromAzureTier(item.Properties.AccessTier)) shouldn’t be prevented just because traits is BlobTraits.None.
  • Still, item.Properties.AccessTier can be absent/null depending on the service/account/blob tiering support; ensure FromAzureTier (and the in-memory fake) handles null consistently and add coverage for that scenario in listing tests.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/Arius.AzureBlob/AzureBlobContainerService.cs` around lines 184 - 198,
Listing code currently skips or assumes Tier behavior based on BlobTraits but
AccessTier can be present even when traits == BlobTraits.None and can also be
null; update the blob listing in GetBlobsAsync so it always calls
FromAzureTier(item.Properties.AccessTier) for Tier (do not gate it behind
includeMetadata/traits), modify FromAzureTier to accept a nullable AccessTier
and return a consistent value for null inputs, and update the in-memory/fake
implementation and listing tests to cover the null-AccessTier case and the
presence-of-AccessTier-when-traits-none scenario (refer to GetBlobsAsync,
BlobListItem, FromAzureTier, and the fake container/listing test helpers).
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/Arius.Cli/Commands/Ls/LsVerb.cs`:
- Around line 145-147: The legend printed by AnsiConsole.MarkupLine in LsVerb.cs
is missing symbols emitted by LsStateFormatter (specifically "~" and "?");
update the legend string (the two AnsiConsole.MarkupLine calls) to include short
human-readable descriptions for "~" and "?" alongside the existing P/B/R/H/A
entries so streamed output users see all possible state symbols; ensure the text
matches the semantics defined in LsStateFormatter so the legend accurately
describes each symbol.

In `@src/Arius.Core/Features/ListQuery/ListQuery.cs`:
- Around line 69-79: The hydration flags in the RepositoryEntryState enum
(RepositoryHydrated, RepositoryArchived, RepositoryRehydrating) must encode
their documented implication of Repository by including the Repository bit in
their values; update those enum member definitions so each is defined as
Repository ORed with its current unique bit (e.g., RepositoryHydrated =
Repository | (1 << 4), etc.) so HasFlag(RepositoryEntryState.Repository) returns
true for those states and downstream checks in RepositoryExplorerViewModel work
correctly.

In `@src/Arius.Core/Features/ListQuery/ListQueryHandler.cs`:
- Around line 216-258: The overlay matching is currently case-sensitive causing
duplicate emits; make local-overlay comparisons case-insensitive by normalizing
or using ordinal-ignore-case collections: build emittedDirectoryNames as a
case-insensitive set, access localSnapshot.Directories with case-insensitive
keys (or normalize DirectoryEntry.Name/PathSegment when populating), and perform
localFiles.Remove using a case-insensitive lookup; update all uses referenced
here (emittedDirectoryNames, localSnapshot.Directories, localSnapshot.Files,
localDirectory.Name, repositoryDirectory.Name, localFiles.Remove) and the same
logic in the other block (lines ~423-459) so repository vs local matching uses
consistent OrdinalIgnoreCase semantics.

In `@src/Arius.Core/Shared/ChunkIndex/ChunkIndexLocalStore.cs`:
- Line 560: Create an explicit schema-break handling path in
ChunkIndexLocalStore initialization/CreateOrUpgradeSchema(): detect older
cache.sqlite files missing the new required column (storage_tier_hint) by
checking PRAGMA table_info('chunk_index') or attempting a safe test query and
catching a SQLite missing-column error, and if the column is absent/exception
occurs, delete or recreate the local cache DB and re-run schema creation so the
cache is rebuilt rather than letting a later SELECT/UPSERT fail; update
CreateOrUpgradeSchema() (and any initialization logic in ChunkIndexLocalStore
that opens cache.sqlite) to perform this check and recreate the DB when the
schema mismatch is detected.

In `@src/Arius.Core/Shared/ChunkIndex/ChunkIndexService.cs`:
- Around line 362-377: The code currently defaults missing parent TAR tiers to
BlobTier.Hot when building tarTiers in the pass over _blobs.ListAsync (using
BlobPaths.ChunksPrefix, BlobMetadataKeys.TypeTar and ChunkHash.TryParse), which
can incorrectly mark archived content as hydrated; change the logic in the
tarTiers construction and any subsequent use (the code around tarTiers lookup
where BlobTier.Hot is used) to treat a missing tarTiers entry as an error
condition: either fail the repair with a clear exception/return or explicitly
skip that thin-chunk entry (do not synthesize BlobTier.Hot), so that unknown
parent TAR tiers are not persisted as hydrated state.

In `@src/Arius.Explorer/RepositoryExplorer/FileItemViewModel.cs`:
- Around line 45-50: The HydrationStatus setter in FileItemViewModel assigns
ChunkHydrationStatus.Unknown as a no-op so the hydration UI presentation never
gets initialized; fix by ensuring the Unknown presentation is applied: either
call OnHydrationStatusChanged(HydrationStatus) once after the constructor
finishes (so the Unknown case applies the label/color), or initialize the
backing presentation fields to the same values used for
ChunkHydrationStatus.Unknown (so the constructor seeds the UI state); update
FileItemViewModel to use one of these approaches referencing the HydrationStatus
property and OnHydrationStatusChanged method.

---

Nitpick comments:
In `@openspec/changes/2026-06-10-rewrite/PLAN.MD`:
- Around line 64-66: Add a language label to the fenced code block that contains
the ASCII pipeline diagram (the block starting with ``` and the content `Walk
(×1) ─► walkItemChannel (bounded) ─► Resolve (×1) ─► entryChannel (bounded) ─►
Handle (yield)`) by changing the opening fence to ```text so the block is
explicitly marked as plain text; this is a purely cosmetic markdown hygiene
change and requires updating only the fenced code block around that pipeline
string.

In `@README.md`:
- Around line 310-312: Update the unlabeled fenced code block that shows the
shard line format example (the block containing "`<content-hash> <chunk-hash>
<original-size> <compressed-size> <tier>`") to include an explicit language
label by changing the opening fence to "```text" so the example is rendered as
plain text and improves markdown hygiene.

In `@src/Arius.AzureBlob/AzureBlobContainerService.cs`:
- Around line 184-198: Listing code currently skips or assumes Tier behavior
based on BlobTraits but AccessTier can be present even when traits ==
BlobTraits.None and can also be null; update the blob listing in GetBlobsAsync
so it always calls FromAzureTier(item.Properties.AccessTier) for Tier (do not
gate it behind includeMetadata/traits), modify FromAzureTier to accept a
nullable AccessTier and return a consistent value for null inputs, and update
the in-memory/fake implementation and listing tests to cover the null-AccessTier
case and the presence-of-AccessTier-when-traits-none scenario (refer to
GetBlobsAsync, BlobListItem, FromAzureTier, and the fake container/listing test
helpers).

In `@src/Arius.Cli.Tests/Commands/Ls/LsStateFormatterTests.cs`:
- Around line 38-58: Add explicit assertions to LsStateFormatterTests to cover
the rehydrating and unknown-tier outputs emitted by LsStateFormatter.ToMarkup:
update or add tests (e.g., in ToMarkup_PresentFlags_AreColored or new test
methods) that call LsStateFormatter.ToMarkup with state combinations that
produce the rehydrating marker (~) and the unknown-tier marker (?) and assert
the exact markup strings include "~" and "?" with the expected
coloring/formatting; reference LsStateFormatter.ToMarkup and
RepositoryEntryState flags to construct the input states that produce those
outputs so the tests fail if those markers are omitted or misformatted.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 323d16a0-858c-4134-9455-4ecf3e5758ab

📥 Commits

Reviewing files that changed from the base of the PR and between d420680 and 3c4f68c.

📒 Files selected for processing (37)
  • AGENTS.md
  • README.md
  • openspec/changes/2026-06-10-rewrite/2026-06-10-234022-local-command-caveatcaveat-the-messages-below.txt
  • openspec/changes/2026-06-10-rewrite/2026-06-11-010913-this-session-is-being-continued-from-a-previous-c.txt
  • openspec/changes/2026-06-10-rewrite/PLAN.MD
  • src/Arius.AzureBlob/AzureBlobContainerService.cs
  • src/Arius.Cli.Tests/Commands/Ls/ListQueryParsingTests.cs
  • src/Arius.Cli.Tests/Commands/Ls/LsStateFormatterTests.cs
  • src/Arius.Cli/Commands/Ls/LsStateFormatter.cs
  • src/Arius.Cli/Commands/Ls/LsVerb.cs
  • src/Arius.Core.Tests/Features/ArchiveCommand/ArchiveRecoveryTests.cs
  • src/Arius.Core.Tests/Features/ChunkHydrationStatusQuery/ResolveFileHydrationStatusesHandlerTests.cs
  • src/Arius.Core.Tests/Features/ListQuery/ListQueryHandlerTests.cs
  • src/Arius.Core.Tests/Features/RestoreCommand/RestoreCommandHandlerTests.cs
  • src/Arius.Core.Tests/Shared/ChunkIndex/ChunkIndexLocalStoreTests.cs
  • src/Arius.Core.Tests/Shared/ChunkIndex/ChunkIndexServiceArchiveScenarioTests.cs
  • src/Arius.Core.Tests/Shared/ChunkIndex/ChunkIndexServiceFlushTests.cs
  • src/Arius.Core.Tests/Shared/ChunkIndex/ChunkIndexServiceLookupTests.cs
  • src/Arius.Core.Tests/Shared/ChunkIndex/ChunkIndexServiceRepairTests.cs
  • src/Arius.Core.Tests/Shared/ChunkIndex/ShardSerializerTests.cs
  • src/Arius.Core.Tests/Shared/ChunkIndex/ShardTests.cs
  • src/Arius.Core/Features/ArchiveCommand/ArchiveCommandHandler.cs
  • src/Arius.Core/Features/ChunkHydrationStatusQuery/ChunkHydrationStatusQuery.cs
  • src/Arius.Core/Features/ListQuery/ListQuery.cs
  • src/Arius.Core/Features/ListQuery/ListQueryHandler.cs
  • src/Arius.Core/Shared/ChunkIndex/ChunkIndexLocalStore.cs
  • src/Arius.Core/Shared/ChunkIndex/ChunkIndexService.cs
  • src/Arius.Core/Shared/ChunkIndex/IChunkIndexService.cs
  • src/Arius.Core/Shared/ChunkIndex/Shard.cs
  • src/Arius.Core/Shared/Storage/IBlobContainerService.cs
  • src/Arius.Explorer.Tests/RepositoryExplorer/FileItemViewModelTests.cs
  • src/Arius.Explorer.Tests/RepositoryExplorer/RepositoryExplorerViewModelTests.cs
  • src/Arius.Explorer/RepositoryExplorer/FileItemViewModel.cs
  • src/Arius.Explorer/RepositoryExplorer/RepositoryExplorerViewModel.cs
  • src/Arius.Integration.Tests/ChunkIndex/ChunkIndexServiceArchiveScenarioTests.cs
  • src/Arius.Integration.Tests/ChunkIndex/ChunkIndexServiceIntegrationTests.cs
  • src/Arius.Tests.Shared/Storage/FakeInMemoryBlobContainerService.cs

Comment thread src/Arius.Cli/Commands/Ls/LsVerb.cs
Comment thread src/Arius.Core/Features/ListQuery/ListQuery.cs Outdated
Comment thread src/Arius.Core/Features/ListQuery/ListQueryHandler.cs
Comment thread src/Arius.Core/Shared/ChunkIndex/ChunkIndexLocalStore.cs
Comment thread src/Arius.Core/Shared/ChunkIndex/ChunkIndexService.cs
Comment thread src/Arius.Explorer/RepositoryExplorer/FileItemViewModel.cs

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 1

🧹 Nitpick comments (2)
openspec/changes/2026-06-10-rewrite-restore/PLAN.MD (2)

78-79: 💤 Low value

Clarify concurrent collection choice for re-route rehydration set.

Lines 78-79 and 174 mention "ConcurrentDictionary/ConcurrentBag" for the ×N-written re-route rehydration set but don't specify which. ConcurrentDictionary supports deduplication (if the same chunk fails multiple times), while ConcurrentBag is append-only. For a rehydration set, deduplication is likely desired.

Consider specifying ConcurrentDictionary<ChunkHash, byte> (or a ConcurrentHashSet-equivalent) in the plan.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@openspec/changes/2026-06-10-rewrite-restore/PLAN.MD` around lines 78 - 79,
Clarify the concurrent collection choice for the "re-route rehydration set" by
replacing the ambiguous "ConcurrentDictionary/ConcurrentBag" references with a
deduplicating structure; specify using ConcurrentDictionary<ChunkHash, byte> (or
a ConcurrentHashSet-equivalent) for the ×N-written re-route rehydration set so
repeated failed-chunk entries are deduplicated rather than appended, and update
both the mentions around "re-route rehydration set" and any usage notes to
reflect deduplication semantics.

203-206: ⚡ Quick win

Avoid coupling the scattered-tar test to implementation details.

Lines 205-206 suggest "counting DownloadAsync calls on FakeInMemoryBlobContainerService" to validate that each chunk is downloaded exactly once. This couples the test to the fake's call-count implementation detail rather than testing the behavior (files are restored correctly).

Based on learnings, prefer testing behavior over implementation. Instead, the test could:

  • Assert that all scattered-tar files are restored with correct content and timestamps.
  • Optionally verify bounded memory (e.g., no full-tree materialization) by measuring peak allocations if needed, but avoid asserting on internal method call counts.

Based on learnings: "Avoid coupling tests to implementation details. Test the behavior, not the implementation."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@openspec/changes/2026-06-10-rewrite-restore/PLAN.MD` around lines 203 - 206,
Update the "scattered-tar" test to avoid asserting on
FakeInMemoryBlobContainerService.DownloadAsync call counts; instead validate
behavior by asserting all scattered files are restored with correct contents and
timestamps (and any expected metadata), and if you need to assert resource
bounds do so via external observable metrics (e.g., peak memory/allocations)
rather than internal method call counts; remove or replace the DownloadAsync
call-count assertion in the scattered-tar test and rely on file-level
restoration assertions (referencing the scattered-tar test and
FakeInMemoryBlobContainerService.DownloadAsync to locate the change).

Source: Learnings

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@openspec/changes/2026-06-10-rewrite-restore/PLAN.MD`:
- Around line 197-214: Update the PLAN.MD verification section to adopt a TDD
workflow: before implementing the rewrite, add failing tests that drive the new
streaming behavior (create new tests such as a scattered-tar test and
cancel-rehydration test in RestoreCommandHandlerTests and add
bounded-memory/streaming tests), then implement the pipeline incrementally
across the Walk → Route → Resolve → Pass1 → Pass2 stages making one stage green
at a time, and commit after each stage passes; also ensure CLI parsing tests
(RestoreCommandTests) remain unchanged and run dotnet test/dotnet build after
each stage to catch analyzer/nullable warnings early.

---

Nitpick comments:
In `@openspec/changes/2026-06-10-rewrite-restore/PLAN.MD`:
- Around line 78-79: Clarify the concurrent collection choice for the "re-route
rehydration set" by replacing the ambiguous "ConcurrentDictionary/ConcurrentBag"
references with a deduplicating structure; specify using
ConcurrentDictionary<ChunkHash, byte> (or a ConcurrentHashSet-equivalent) for
the ×N-written re-route rehydration set so repeated failed-chunk entries are
deduplicated rather than appended, and update both the mentions around "re-route
rehydration set" and any usage notes to reflect deduplication semantics.
- Around line 203-206: Update the "scattered-tar" test to avoid asserting on
FakeInMemoryBlobContainerService.DownloadAsync call counts; instead validate
behavior by asserting all scattered files are restored with correct contents and
timestamps (and any expected metadata), and if you need to assert resource
bounds do so via external observable metrics (e.g., peak memory/allocations)
rather than internal method call counts; remove or replace the DownloadAsync
call-count assertion in the scattered-tar test and rely on file-level
restoration assertions (referencing the scattered-tar test and
FakeInMemoryBlobContainerService.DownloadAsync to locate the change).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 10b5e5b7-f975-4cc7-b09b-7eb802f7bf9f

📥 Commits

Reviewing files that changed from the base of the PR and between 3c4f68c and e5f010e.

📒 Files selected for processing (13)
  • README.md
  • openspec/changes/2026-06-10-rewrite-list/2026-06-10-234022-local-command-caveatcaveat-the-messages-below.txt
  • openspec/changes/2026-06-10-rewrite-list/2026-06-11-010913-this-session-is-being-continued-from-a-previous-c.txt
  • openspec/changes/2026-06-10-rewrite-list/PLAN.MD
  • openspec/changes/2026-06-10-rewrite-list/PLAN2-Coderabbit fixes.MD
  • openspec/changes/2026-06-10-rewrite-restore/PLAN.MD
  • src/Arius.Cli.Tests/Commands/Ls/LsStateFormatterTests.cs
  • src/Arius.Cli/Commands/Ls/LsVerb.cs
  • src/Arius.Core.Tests/Shared/ChunkIndex/ChunkIndexServiceRepairTests.cs
  • src/Arius.Core/Features/ListQuery/ListQuery.cs
  • src/Arius.Core/Features/ListQuery/ListQueryHandler.cs
  • src/Arius.Core/Shared/ChunkIndex/ChunkIndexService.cs
  • src/Arius.Explorer/RepositoryExplorer/FileItemViewModel.cs
💤 Files with no reviewable changes (1)
  • openspec/changes/2026-06-10-rewrite-list/2026-06-11-010913-this-session-is-being-continued-from-a-previous-c.txt
✅ Files skipped from review due to trivial changes (3)
  • openspec/changes/2026-06-10-rewrite-list/PLAN2-Coderabbit fixes.MD
  • openspec/changes/2026-06-10-rewrite-list/PLAN.MD
  • README.md
🚧 Files skipped from review as they are similar to previous changes (5)
  • src/Arius.Explorer/RepositoryExplorer/FileItemViewModel.cs
  • src/Arius.Cli.Tests/Commands/Ls/LsStateFormatterTests.cs
  • src/Arius.Cli/Commands/Ls/LsVerb.cs
  • src/Arius.Core/Features/ListQuery/ListQuery.cs
  • src/Arius.Core/Features/ListQuery/ListQueryHandler.cs

Comment on lines +197 to +214
## Verification

- **Unit/handler tests** (`src/Arius.Core.Tests/Features/RestoreCommand/RestoreCommandHandlerTests.cs`):
all existing tests must pass unchanged (behavior preserved) — large files, tar duplicates, zero-byte
tar entries, invalid-hash failure, `TargetPath` filtering, `NoPointers`, missing-container. Run
`dotnet test` for `Arius.Core.Tests`.
- Add a **scattered-tar** test: several distinct small files that land in one tar bundle but live at
distant tree paths (e.g. `a/…`, `z/…`); assert all are restored correctly. Optionally assert each
chunk is downloaded exactly once by counting `DownloadAsync` calls on `FakeInMemoryBlobContainerService`
(== distinct available chunks) — validates the refcount flush avoids re-downloads.
- Add a **cancel-rehydration** test (returns `FilesRestored = 0`, downloads nothing) using a fake
that reports an archive-tier chunk — confirms the two-pass barrier.
- **CLI tests** (`src/Arius.Cli.Tests/Commands/Restore/RestoreCommandTests.cs`): parsing tests unchanged
(no new CLI options/args). Verify `CliHarness` still builds.
- **End-to-end manual check:** archive a small tree then restore it via the CLI (`/run` or
`dotnet run -- archive … && dotnet run -- restore …`) into an empty dir; confirm files + pointers +
timestamps and the progress UI (now showing download queue depth) render correctly.
- Build: `dotnet build` the solution; ensure no analyzer/nullable warnings introduced.

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.

⚠️ Potential issue | 🟠 Major | 🏗️ Heavy lift

Consider a Test-Driven Development approach for this rewrite.

The plan lists verification steps at the end, after the full pipeline design. Based on learnings, the preferred workflow is: "first write a failing test, then implement, then make a conventional git commit when tests pass."

For a rewrite of this scope—particularly one addressing memory bottlenecks and streaming correctness in a backup tool—discovering issues early via TDD provides higher confidence. Consider restructuring the implementation plan to:

  1. Write failing tests for the new streaming behavior first (e.g., scattered-tar, cancel-rehydration, bounded-memory constraints).
  2. Implement stages incrementally (Walk → Route → Resolve → Pass 1 → Pass 2), making tests green one stage at a time.
  3. Commit after each stage passes its tests.

This reduces the risk of discovering design issues late and aligns with the "work in small steps" learning.

Based on learnings: "Work in small steps using Test-Driven Development: first write a failing test, then implement, then make a conventional git commit when tests pass."

🧰 Tools
🪛 LanguageTool

[grammar] ~199-~199: Ensure spelling is correct
Context: ...Verification - Unit/handler tests (`src/Arius.Core.Tests/Features/RestoreCommand/Rest...

(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@openspec/changes/2026-06-10-rewrite-restore/PLAN.MD` around lines 197 - 214,
Update the PLAN.MD verification section to adopt a TDD workflow: before
implementing the rewrite, add failing tests that drive the new streaming
behavior (create new tests such as a scattered-tar test and cancel-rehydration
test in RestoreCommandHandlerTests and add bounded-memory/streaming tests), then
implement the pipeline incrementally across the Walk → Route → Resolve → Pass1 →
Pass2 stages making one stage green at a time, and commit after each stage
passes; also ensure CLI parsing tests (RestoreCommandTests) remain unchanged and
run dotnet test/dotnet build after each stage to catch analyzer/nullable
warnings early.

Source: Learnings

@woutervanranst woutervanranst merged commit a5e2eb6 into master Jun 11, 2026
11 of 12 checks passed
@woutervanranst woutervanranst deleted the streaming-list-and-restore branch June 11, 2026 10:55
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.

1 participant