Skip to content

Release M283 - #2151

Merged
Tyrie Vella (tyrielv) merged 47 commits into
releases/shippedfrom
milestones/M283
Nov 2, 2026
Merged

Tyrie Vella (tyrielv) merged 47 commits into
releases/shippedfrom
milestones/M283

Conversation

@tyrielv

@tyrielv Tyrie Vella (tyrielv) commented Nov 2, 2026 •

Copy link
Copy Markdown
Contributor

Changes:

Tyrie Vella (tyrielv) and others added 30 commits September 1, 2026 11:05
When GVFS.Mount failed to mount, the client printed a transport error:

    Could not connect to GVFS.Mount: BrokenPipeException: Unable to send: GetStatus

The real cause was written only to the mount process log. A user hitting a
ProjFS attach failure on a Dev Drive got no cause and no remedy, although
the mount process had already diagnosed it.

Two defects combined to lose the reason.

First, FailMountAndExit called fileSystemCallbacks.Dispose(), which reached
GitIndexProjection.Dispose(bool) and called Task.Dispose() on the still
running index-parsing thread. Shutdown() had not run, so the task was not in
a completion state and Task.Dispose threw InvalidOperationException. That
secondary exception killed the process before it could serve a GetStatus
response.

Second, even without the exception, FailMountAndExit called Environment.Exit
immediately after setting MountState.MountFailed. The client polls GetStatus
every 100ms, so the process usually died before the client observed the
state. MountState.MountFailed and the GetStatus.MountFailed response already
existed but were never seen.

Changes:

- GitIndexProjection.Dispose(bool) only disposes the index-parsing task once
  it has completed. A Task holds no unmanaged resources, so skipping the
  call is safe, and it no longer throws during a failed mount.

- FailMountAndExit keeps the named pipe answering GetStatus after a failure,
  and exits once a client has read MountFailed. Callbacks are disposed after
  the failure is reported, and disposal exceptions are logged instead of
  terminating the process. A latch makes the first failing thread the only
  one that tears down and exits.

  The wait is deliberately short. Until the process exits it still holds the
  mount lock and its named pipe, and a "gvfs mount" retry inside that window
  hits IsExistingPipeListening and is told "The repo at ... is already
  mounted" with exit code Success. So the wait is capped at 2 seconds, or
  500ms when no client has polled GetStatus at all, and normally ends on the
  client's next poll, about 100ms. Failures raised before the pipe server
  starts do not wait; MountVerb already detects those through the mount
  process exit code.

- GetStatus.Response carries a MountError field, so WaitUntilMounted prints
  the mount process's own message rather than "Failed to mount at <path>".

- StartVirtualizing failures with 0x800701DE
  (ERROR_FILE_SYSTEM_VIRTUALIZATION_NOT_AVAILABLE) name the cause and the
  remedy: PrjFlt cannot attach to the volume, and on a Dev Drive it must be
  allowed with "fsutil devdrv setfiltersallowed PrjFlt".

Tests: disposing a projection whose parsing thread is still running must not
throw, and WaitUntilMounted must surface MountError when the mount process
sends one, falling back to the generic message when it does not. Both fail
against the unfixed code.

Assisted-by: Claude Opus 5
Signed-off-by: Tyrie Vella <tyrielv@gmail.com>
Verified the original fix end-to-end on a real ReFS Dev Drive with PrjFlt not
on the allowed-filter list. The baseline reproduced the reported
BrokenPipeException exactly, and this branch now prints the real cause. That
run, plus a multi-perspective self-review, turned up several defects in the
first version of this change.

Fix a second copy of the disposal bug. The repro showed the
InvalidOperationException still being thrown after the GitIndexProjection fix,
now from BackgroundFileSystemTaskRunner.Dispose, which disposes its own
still-running Task. Only the new try/catch kept the report alive. Both classes
now drop the Task.Dispose call outright rather than guarding it: a Task holds
no unmanaged resources and Task.Dispose is legacy IAsyncResult cleanup.

Correct the Dev Drive remedy, which was wrong and destructive. It advised
"fsutil devdrv setfiltersallowed PrjFlt". Without /volume that applies to every
developer volume on the machine, and setFiltersAllowed replaces the list rather
than appending to it, so following the advice would drop filters the machine
already requires. The message now names the enlistment's own volume, tells the
user to read the current list first, and says the list is replaced.

Do not let message formatting hang the mount process. FailMountAndExit
formatted the message twice, and the second call was unprotected. A malformed
format string threw there, and an outer catch block then re-entered
FailMountAndExit on the same thread, where the latch parked it forever holding
the mount lock and the pipe. Format once, and make the latch re-entrant for the
thread that already owns it.

Other fixes from the review:

- Only count a client that actually received a status. clientPolledStatus was
  set before the send succeeded, so a client that connected and disconnected
  still extended the wait.
- Raise the drain above the client's 100ms poll interval. Any client can
  satisfy the wait, so a concurrent "gvfs status" could consume the signal
  while the mounting client was still sleeping.
- Trace the report timeout and the swallowed disposal exception with
  Keywords.Telemetry. Without it, a failure that used to be a process-fatal
  crash became invisible in the field.
- Shorten the test's server-task wait so a failing assertion is not delayed.

Adds a regression test for the BackgroundFileSystemTaskRunner disposal. Both
disposal tests are mutation-checked.

Assisted-by: Claude Opus 5
Signed-off-by: Tyrie Vella <tyrielv@gmail.com>
The failure-reporting change had grown to three constants, four fields and two
methods inside InProcessMount, a 2158-line class that already carried 74 private
fields. The state was cohesive but scattered, and it was reachable from only
five places, so it moves out cleanly.

MountFailureReporter now owns the handshake: the ownership latch, the published
failure message, the pipe-ready and client-received flags, the bounded wait, and
the safe message formatting. InProcessMount keeps the policy that belongs to it
-- the MountFailed state transition, tracing, disposal, and process exit.

Ownership is expressed as a MountFailureOwnership enum (Owner, Reentrant,
NotOwner) rather than a bare interlocked int, so the re-entrant case is named
instead of implied by a thread-id comparison at the call site.

The class lives in GVFS.Common/NamedPipes beside the protocol it implements.
The client half of the same handshake, GVFSEnlistment.WaitUntilMounted, is
already in GVFS.Common, so both halves now sit together.

Placing it there also makes the state machine testable. GVFS.UnitTests
references GVFS.Common but not GVFS.Mount, so while this logic lived in
InProcessMount none of it could be covered, and CI runs only GVFS.UnitTests.
Adds 11 tests for ownership and re-entrancy, the wait and its two timeouts, the
distinction between a status that carried the failure and one that did not, and
the formatting fallback. Two are mutation-checked.

No behavior change. Verified on the same ReFS Dev Drive repro: the mount still
prints the real ProjFS cause, and the mount log has no disposal exception and
no report timeout.

Assisted-by: Claude Opus 5
Signed-off-by: Tyrie Vella <tyrielv@gmail.com>
A second self-review pass over the extraction. No defects were found -- every
finding was a judgement call, and the security, async and rollout lenses were
clean -- but three were worth acting on.

Narrow the public surface. The three Default* timeout constants are read
nowhere outside the class, so they are now internal. GVFS.Common already grants
InternalsVisibleTo to GVFS.UnitTests, so the tests still see them. The class and
the ownership enum stay public because GVFS.Mount consumes them across an
assembly boundary.

Cover the public constructor. Every test built the reporter through the internal
test constructor, so nothing exercised the public one or its forwarding of the
Default* constants. Swapping DefaultReportTimeoutMs and DefaultNoClientTimeoutMs
would have shipped unnoticed. Two tests now close that: one drives the public
constructor down the no-client path, and one asserts the ordering invariants the
constants have to satisfy. Mutation-checked by swapping the two values.

Cut the fixture's wall-clock cost. One test has to wait out the long timeout to
prove the long timeout was selected, and the fixture's own constants made that
2000ms. They are arbitrary -- they only have to be far enough apart to tell the
two paths apart -- so the long one drops to 600ms. The assertion now checks
against the short timeout rather than a fixed margin below the long one, which
is what actually proves the selection. Fixture time falls from ~2.9s to ~2.0s.

Also: document why InProcessMount deliberately never disposes the reporter, and
stop discarding the result of the stand-in server's Wait so a hung server task
is reported instead of silently faulting.

Measured on this machine: 977 tests pass, and the timing assertions survived six
consecutive runs with all twelve cores saturated.

Assisted-by: Claude Opus 5
Signed-off-by: Tyrie Vella <tyrielv@gmail.com>
Route index generation, repair, FastFetch, and dehydrate backups through GitIndexPath.

Reject full dehydrate for linked worktrees before it moves the .git file.

Assisted-by: GPT-5.6 Sol

Signed-off-by: Tyrie Vella <tyrielv@gmail.com>
Reject full dehydrate when linked worktrees exist.

Store worktree backups beside each worktree with unique paths.

Preserve backup errors and add regression coverage.

Assisted-by: GPT-5.6 Sol

Signed-off-by: Tyrie Vella <tyrielv@gmail.com>
When the disk layout version is missing from .gvfs metadata, report that the metadata is incomplete and tell the user to reclone the enlistment. Return a distinct mount exit code for that case so automation can identify it.

Keep generic upgrade failures on the existing error path. Cover both a missing layout key and a missing repo metadata file in mount functional tests.

Assisted-by: GitHub Copilot
Signed-off-by: Tyrie Vella <tyrielv@gmail.com>
Use structured return codes throughout disk layout version checks instead of deriving the missing-layout case from message text. Propagate the new return code through repair and dehydrate as well as mount.

Keep functional tests tied to the production return code and message constants, and share repo metadata read/write helper logic in test utilities.

Assisted-by: GitHub Copilot
Signed-off-by: Tyrie Vella <tyrielv@gmail.com>
HydrateFile swallowed IOException and UnauthorizedAccessException without
recording anything about them, so a failed hydration only ever produced
"Failed to read <path>" in telemetry with no exception type, HResult, or
Win32 error code. That makes every such failure unattributable after the
fact.

HydrateFile on IPlatformFileSystem now has an `out Exception failure`
parameter. WindowsFileSystem populates it with the caught exception
instead of discarding it; the out parameter costs nothing on the (much
more common) success path, so the ~36-40K files/s hydration pipeline is
unaffected there.

HydrateFilesStage and the `gvfs prefetch --hydrate` verb turn that
exception into structured EventMetadata (exception type, HResult, and the
Win32 error code derived from the HResult when it is Win32-facility)
via a new HydrationFailureDiagnostics helper, so the fields are queryable
in telemetry instead of being buried in a concatenated string. The
existing "Failed to read <path>" message text is unchanged. The
per-thread activity summary also now reports a count per distinct failure
signature, so a large failed prefetch can be triaged from the summary
event alone instead of requiring one query per file.

Checked whether the prior P/Invoke-based implementation (replaced by the
managed FileStream rewrite) ever surfaced a Win32 error: it did not -
`CreateFile` failures produced an invalid handle and the method returned
false with no call to GetLastError. Neither implementation ever captured
diagnostics here, so this is a long-standing gap rather than a
regression. It is also a pure instrumentation change with no effect on
control flow or return values for any input.

Self-review found that the new failure-signature summary and the
`--hydrate` verb's warning both defaulted to Keywords.None, so neither
ever reached the telemetry pipe the aggregation was built for (the
per-file error already did). Both now pass Keywords.Telemetry explicitly.
Also added: a HydrateFilesStage test covering the aggregation path (the
mock file system is now scriptable instead of always throwing), pinned
Win32 HResult assertions in WindowsFileSystemTests instead of only
checking non-zero, a missing-file test case, and null-argument guards in
HydrationFailureDiagnostics.

Assisted-by: Claude Sonnet 5
Signed-off-by: Tyrie Vella <tyrielv@gmail.com>
Capture and surface the real failure when placeholder hydration fails
Qualify the missing disk layout recovery guidance and keep the log pointer on that path. Remove unused disk layout helper overloads, make the mount upgrade failure branch explicit, and pin the functional test to the shipped exit-code contract.

Add RepoMetadata unit coverage for missing and invalid disk layout values.

Assisted-by: GitHub Copilot
Signed-off-by: Tyrie Vella <tyrielv@gmail.com>
In a linked git worktree, Enlistment.DotGitRoot and the git directory that
GitProcess passes as --git-dir point at different locations:

  Enlistment.DotGitRoot -> the shared .git directory of the main repo
  GitProcess git dir    -> "<worktree>\.git", a file holding
                           "gitdir: <shared>/.git/worktrees/<name>"

The two values look inconsistent, but each is correct for its purpose. Git
follows the gitdir: pointer, so the worktree .git file resolves the
per-worktree state (HEAD, index, per-worktree refs, reflog) and, through
commondir, the shared state (config, objects, packed-refs). DotGitRoot is used
for shared state that GVFS reads or writes directly on disk (objects,
objects/info/alternates, hooks).

Making GitProcess use DotGitRoot would be a regression. Every command would
bind to the main worktree. From inside a linked worktree, "rev-parse HEAD" and
"name-rev --name-only HEAD" would report the main worktree's branch and commit.

No behavior changes. This adds comments on both sides of the divergence, an
internal GitDirPath accessor, and tests that pin the current values. The tests
cover both linked-worktree and regular enlistment behavior, plus the null
working-directory constructor case.

Assisted-by: Claude Opus 4.5
Signed-off-by: Tyrie Vella <tyrielv@gmail.com>
Correct the GitProcess comment: only HEAD, index, ORIG_HEAD, logs/HEAD,
refs/bisect and refs/worktree are per-worktree. config, objects, packed-refs
and refs/heads stay in the shared git directory. Reword it so it no longer
reads as following the gitdir: target.

Document Enlistment.DotGitRoot as a contract that subclasses supporting linked
worktrees must satisfy. The base constructor sets it to a path that is a file in
a linked worktree.

Replace the tests that re-derived the path formula with tests that assert the
--git-dir value that reaches InvokeGitImpl. MockGitProcess now records that
value and has constructors for a specific enlistment and a bare working
directory root. Remove the internal GitDirPath accessor, which only the old
tests used.

Assisted-by: Claude Opus 4.5
Signed-off-by: Tyrie Vella <tyrielv@gmail.com>
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 7.0.1 to 7.0.2.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](actions/upload-artifact@043fb46...cf430e0)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-version: 7.0.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Bumps [actions/download-artifact](https://github.com/actions/download-artifact) from 8.0.1 to 8.0.2.
- [Release notes](https://github.com/actions/download-artifact/releases)
- [Commits](actions/download-artifact@3e5f45b...9000827)

---
updated-dependencies:
- dependency-name: actions/download-artifact
  dependency-version: 8.0.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
…ions/download-artifact-8.0.2

Bump actions/download-artifact from 8.0.1 to 8.0.2
…ions/upload-artifact-7.0.2

Bump actions/upload-artifact from 7.0.1 to 7.0.2
A reviewer found that the failure handshake could bring back the failure it
exists to remove. This commit fixes that and the other review findings.

HandleRequest answered every request except GetStatus while the mount was in
the MountFailed state. HandleReleaseLockRequest then read fileSystemCallbacks,
which is still null when the mount fails before that field is set. The
NullReferenceException ended the process through NamedPipeServer, and the
client saw a broken pipe with the real reason lost. A mount that fails in
ValidateHooksVersion reproduces it: a ReleaseLock sent while the process waits
for the client killed it.

While the state is MountFailed, the mount process now answers only GetStatus and
Unmount. It answers every other request with MountNotReady, the same reply it
gives while mounting.

An Unmount request in the MountFailed state used to start a teardown on the pipe
thread, race the thread that reports the failure, and exit with Success. The
process now replies MountFailed and does not tear down, because the failing
mount is already ending the process. UnmountVerb already prints "previous mount
attempt failed" for that reply. gvfs service --unmount-all now skips a repo in
the MountFailed state, as it already skips one that is unmounting, so the
installer does not report a failure for it.

Other changes:

- Rename the HRESULT constant to CantAttachToDevVolume. 0x800701DE is
  HRESULT_FROM_WIN32(ERROR_CANT_ATTACH_TO_DEV_VOLUME), which is 478.
- Remove IDisposable from MountFailureReporter. Nothing disposes it, and a
  Dispose during a wait would make WaitOne throw.
- Inject the wait, sleep, exit, and block operations through an internal
  IMountFailureEnvironment. The tests assert on the timeouts that the reporter
  requests, so they no longer measure elapsed time or sleep.
- Move the ownership dispatch into TryBeginFailure and the send-then-record step
  into TrySendStatus, so both can be tested. The tests cover the re-entrant and
  other-thread outcomes, a failed send, and both wait timeouts.
- Add GVFSEnlistment.MountStatusPollIntervalMs. The client poll and the drain
  after the failure now derive from it.
- Test BuildProjFsAttachRemedy.
- Mark the malformed-format test ExceptionExpected, and use a mock: path.
- Reduce the history comments to the invariants that they protect.

Verified on a ReFS Dev Drive. On the old build, a ReleaseLock or Unmount sent
during the failure killed the process or started a teardown, and the client
printed a broken pipe. On this build, the client prints the real reason in three
of three runs, with no NullReferenceException.

Assisted-by: Claude Opus 5
Signed-off-by: Tyrie Vella <tyrielv@gmail.com>
Trace only allow-listed credential keys on parse failure. Map unknown or
malformed output lines to placeholders so arbitrary helper text cannot
appear in telemetry as a key name.

Add tests that use a secret sentinel in both a password value and a
malformed helper line. Assert that neither value appears in activity
metadata.

Assisted-by: Claude Opus 5
Signed-off-by: Tyrie Vella <tyrielv@gmail.com>
ParseValue added the prefix length to IndexOf without checking for -1.
When the key was absent, the start index landed a few characters into
the output and the method returned an unrelated substring. For example,
output with no "username=" line gave a username of "=https". The caller
treated this as success, so malformed credential output could be cached
and used for authentication.

Return null when the key is absent. A helper that returns only a token
does not send a username, so TryGetCredential now treats an absent
username as empty and requires only the password. GitAuthentication
accepts an empty username and builds the basic-auth string as
":<password>". Output without a password is rejected.

Add tests for output without a username, without a password, and the
certificate-password path, plus authentication tests for both cases.

Assisted-by: Claude Opus 5
Signed-off-by: Tyrie Vella <tyrielv@gmail.com>
Git can echo an unparseable credential helper line to stderr, including a
secret. The failure warning for "git credential fill" carried that stderr
with the telemetry keyword. Report the failure in the telemetry event
without stderr, and write the stderr text to the local log only. The
console-visibility diagnostic stays in the telemetry event.

Bound the traced key summary. It lists at most 32 lines and reports
"<truncated>" when the captured output was truncated, so a broken helper
cannot make the summary larger than the output. Recognize the other key
names in the git credential protocol, so a helper that returns a bearer
token without a password is easy to diagnose.

Match "username=" and "password=" only at the start of a line, so a
longer key such as "oauth_password=" or a value that contains the text
cannot supply the value. Return a reason when a credential has no
password. Split a stored credential at the first ":" so a password
that contains ":" can be approved.

Add tests for each case, including stderr, which now cover every traced
event instead of only the activity metadata. Fix a test that waited for
the 120 second initialization timeout.

Assisted-by: Claude Opus 5
Signed-off-by: Tyrie Vella <tyrielv@gmail.com>
The activity stop event for a credential fill uses no telemetry keyword,
so the output keys that explain a rejected credential never left the
machine. A helper whose output shape the parser rejects was a silent
failure. Report a rejected credential in a warning that carries the
telemetry keyword, with the allowed key names, the exit code, and the
length and truncation of stderr. Add the exit code and the stderr length
and truncation to the failure warning as well, so the failures of a
helper can be told apart without sending stderr.

Make the parser and the key summary agree on what a line is, and match
how git reads credential output. A line ends at a newline, the last line
need not end with one, a carriage return is not a separator, and a
repeated key takes its last value. Git writes each key once and ends
every line, so this does not change what a real helper returns. It makes
the parser no stricter than git.

Test failures with an absent password instead of a missing final
newline, which git never produces. Use the stop metadata that the mock
tracer already records.

Assisted-by: Claude Opus 5
Signed-off-by: Tyrie Vella <tyrielv@gmail.com>
A failed "git credential fill" returned its stderr as the error message.
The caller puts that message in an exception, and the retry handler
reports the final failure of a request with the telemetry keyword, so a
secret that git echoed to stderr could still leave the machine. Return a
message that names the exit code, and keep the stderr text in the local
log only.

Treat an empty password like a missing one, so the failure has the same
reason and the same telemetry warning on both layers. Write the captured
stderr of a credential manager timeout to the local log as well, which
is the case where it is most likely to explain the hang.

Encode and decode the stored credential as UTF-8 instead of ASCII. ASCII
replaced every other character with "?", which sent a corrupted
credential to the server and to "git credential approve".

Document that the parser reads all of the output because the last value
wins, and that it skips empty lines where git stops reading at the first
one.

Add tests at the authentication boundary for the returned message and for
non-ASCII credentials, and tests for an empty password and a timeout.

Assisted-by: Claude Opus 5
Signed-off-by: Tyrie Vella <tyrielv@gmail.com>
Git resolves files in the per-worktree git directory by default and redirects
only an explicit shared set through commondir. The GitProcess comment listed a
few per-worktree files and described everything else as shared. That is wrong:
MERGE_HEAD, CHERRY_PICK_HEAD, BISECT_START, FETCH_HEAD, rebase-merge/ and
refs/rewritten are also per-worktree. The two earlier commit messages carry the
same wording.

Document that a GitProcess built from an Enlistment uses
WorkingDirectoryBackingRoot, the root that Enlistment uses to derive
DotGitRoot. Document that subclasses set DotGitRoot during construction, since
it is a non-virtual property with a protected setter and cannot be overridden.

Restore the final CRLF line ending of WorktreeEnlistmentTests.cs, which an
earlier edit changed to LF.

Assisted-by: Claude Opus 4.5
Signed-off-by: Tyrie Vella <tyrielv@gmail.com>
Block full dehydrate when worktree registration reads fail. List the registered paths and explain stale-registration cleanup.

Preserve per-file backup errors and trace the resolved index destination. Add a real-worktree dehydrate test and unit coverage for guard failures, trace metadata, and sub-second backup paths.

Assisted-by: GPT-6.1 Sol
Signed-off-by: Tyrie Vella <tyrielv@gmail.com>
Keep backups outside worktrees when paths include a trailing separator. Resolve relative worktree registrations and retain full exceptions in diagnostic logs.

Report both index backup paths and return a failed dehydrate exit code after backup errors. Add CLI tests for full-dehydrate guards, backup failures, and trailing separators.

Assisted-by: GPT-6.1 Sol
Signed-off-by: Tyrie Vella <tyrielv@gmail.com>
Surface disk layout upgrade error details on non-missing-layout failures instead of discarding them. Extend the functional tests for missing disk layout metadata to assert that the mount output includes the gvfs log pointer.

Assisted-by: GitHub Copilot
Signed-off-by: Tyrie Vella <tyrielv@gmail.com>
Match Git by ignoring directories that contain no worktree registration. Continue to block full dehydrate when a present gitdir file is unreadable or malformed.

Cover empty metadata entries alone and alongside a valid worktree registration.

Assisted-by: GPT-6.1 Sol
Signed-off-by: Tyrie Vella <tyrielv@gmail.com>
Skip missing, zero-byte, and unreadable gitdir files. Record skipped read failures in diagnostic logs instead of blocking full dehydrate on entries Git does not list.

Keep nonempty malformed registrations and enumeration errors blocking. Test whitespace-only content and mixed readable and unreadable registrations.

Assisted-by: GPT-6.1 Sol
Signed-off-by: Tyrie Vella <tyrielv@gmail.com>
….vfs.0.2

Update default Microsoft Git version to v2.56.0.vfs.0.2
Exempt worktree list without relaxing locks for other worktree subcommands.
Also exempt audited history, ref-query, object-statistics, and verification
operations. Default annotate follows the existing blame policy for
working-tree reads. Neither command provides snapshot isolation.

Share the hook policy with unit coverage through a partial source file.
Add deterministic first-open coverage during a paused worktree-list command.
Cover read-only commands under contention and preserve normal status waits.
Keep test lock holders alive only for the synchronous test action.
Require lock readiness before the action and cover retained dispatcher waits.
Use producer-shaped pre-command and post-command metadata in the unit cases.

Assisted-by: GPT-6.1 Sol
Signed-off-by: Tyrie Vella <tyrielv@gmail.com>
…back

Record typed count availability, partial observations, validation failures, and phase outcomes. Correlate health commands with cached and fallback calculations through explicit payload identifiers and a compatible IPC extension. Keep count semantics and wait behavior unchanged.

Add unit and functional tests for the diagnostic contract, serialization, and compatibility.

Assisted-by: GPT-6.1 Sol

Signed-off-by: Tyrie Vella <tyrielv@gmail.com>
…t tests

Preserve cached summaries and circuit-breaker counts when configuration reads fail. Preserve cancellation policy while recording cancellation origin. Separate command outcome from calculation outcome and name the heartbeat cache-state point sample explicitly.

Pin IPC state integers and add regression tests for source-loader orchestration, failed phases, worker timeouts, cache snapshots, real command paths, and collector payloads.

Assisted-by: GPT-6.1 Sol

Signed-off-by: Tyrie Vella <tyrielv@gmail.com>
Poll the structured cache state before checking disabled and available results. Filesystem background readiness does not guarantee that the hydration refresh passed its backoff. Keep the deadline bounded and retain the final completion record on failure.

Add functional test cases with zero-second and five-second cache backoff. Keep product behavior unchanged.

Assisted-by: GPT-6.1 Sol

Signed-off-by: Tyrie Vella <tyrielv@gmail.com>
….vfs.0.4

Update default Microsoft Git version to v2.56.0.vfs.0.4
…ting

Report the real reason a mount fails instead of a broken pipe
Pin and document GitProcess git-dir resolution in linked worktrees
Keep telemetry replacement history in the pull request description. State the count, cache, and circuit-breaker preservation requirement directly in the diagnostic contract.

Assisted-by: GPT-6.1 Sol

Signed-off-by: Tyrie Vella <tyrielv@gmail.com>
Avoid GVFS command locks for read-only Git operations
Reject unreadable reverse gitdir pointers. Ignore missing or empty pointers only when the administrative entry contains no other metadata. Keep nondestructive discovery unchanged.

Add real-worktree tests that demonstrate Git omitting usable worktrees and verify full dehydrate stops before index mutation.

Assisted-by: GPT-6.1 Sol
Signed-off-by: Tyrie Vella <tyrielv@gmail.com>
Keep full upgrade exception details in the log and return only the exception message to the command. Add a functional test that checks console output, diagnostic logs, and recovery after metadata restoration.

Assisted-by: GPT-6.1 Sol

Signed-off-by: Tyrie Vella <tyrielv@gmail.com>
…ostics

Preserve hydration summary diagnostics across failures and cache fallback
…version-error

Improve missing disk layout metadata error
@KeithIsSleeping

Copy link
Copy Markdown

[KeithBot]: ✅ No issues found · iteration 1 (5154816)

Validation

  • ⚠️ Cross-PR pipe seam tests 3/3 — partial
  • ✅ 12 merges clean, no target drift
  • ✅ GVFS.UnitTests 1308/1308 at head
  • ✅ 6 concurrent full suites: no flakes
  • ✅ GVFS.CommandLine.Tests 92/92 at head
  • ✅ CI on SHA: 82/82 checks green
  • ⏭️ Functional/mount E2E locally — not run

Approving.

🤖 KeithBot · claude-opus-5.5 · reply on a thread to dispute

@tyrielv
Tyrie Vella (tyrielv) merged commit ac8ff56 into releases/shipped Nov 2, 2026
82 checks passed
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.

3 participants