See #52: the reader could fail to start when its activation pipe name was unavailable, a launch could exit without opening its document, one unusable argument discarded the rest, and the activation code sat outside the coverage gate with tests the Gitea workflow never ran.
Change
Program.Main: the inbox is created inside error handling and may be absent; the pipe is released before the instance key; a launch whose forward fails opens its documents itself instead of exiting with code 1.
ActivationRequest, ActivationJsonContext, ActivationInbox move to src/MarkdownViewr.Windows.Core/Activation (their tests move to the core test project).
ActivationRequest.Create keeps usable arguments and flags unusable ones.
ActivationInbox: deadlines on a TimeProvider (2 s to connect, 10 s per exchange); Dispose and the listener's disconnect share a lock, which removes the catch for the race between them.
ADR-0005, threat model (pipe name can be taken by another program: denial of forwarding only), fuzzing guide, and the GitHub shadow workflows updated.
User-visible: starting the reader a second time now always opens the document; the process exit code for a failed hand-off is no longer 1.
Verification (run)
Local gate script (.NET gates): all pass. Core tests 699 passed, line coverage 100% (the moved code is now measured).
22 activation tests with real current-user pipes, six consecutive runs, 120 to 175 ms each; no test waits for a deadline.
Mutation check: 28 mutants over the request, schema and inbox (bounds, deadlines, queue, validation on both sides, acknowledgement, instance key): all killed.
Not verified by running: Program.Main itself (it needs the WinUI entry point). Its two new branches are covered only by reading and by the inbox tests for the conditions they react to (name taken, no listener, refusal).
Not run: the FlaUI desktop suite.
AI assistance
Written with Claude Fable 5.2. An independent read-only review of this diff is recorded below before merge.
Closes #52.
## Problem
See #52: the reader could fail to start when its activation pipe name was unavailable, a launch could exit without opening its document, one unusable argument discarded the rest, and the activation code sat outside the coverage gate with tests the Gitea workflow never ran.
## Change
- `Program.Main`: the inbox is created inside error handling and may be absent; the pipe is released before the instance key; a launch whose forward fails opens its documents itself instead of exiting with code 1.
- `ActivationRequest`, `ActivationJsonContext`, `ActivationInbox` move to `src/MarkdownViewr.Windows.Core/Activation` (their tests move to the core test project).
- `ActivationRequest.Create` keeps usable arguments and flags unusable ones.
- `ActivationInbox`: deadlines on a `TimeProvider` (2 s to connect, 10 s per exchange); `Dispose` and the listener's disconnect share a lock, which removes the catch for the race between them.
- ADR-0005, threat model (pipe name can be taken by another program: denial of forwarding only), fuzzing guide, and the GitHub shadow workflows updated.
User-visible: starting the reader a second time now always opens the document; the process exit code for a failed hand-off is no longer 1.
## Verification (run)
- Local gate script (.NET gates): all pass. Core tests 699 passed, line coverage 100% (the moved code is now measured).
- 22 activation tests with real current-user pipes, six consecutive runs, 120 to 175 ms each; no test waits for a deadline.
- Mutation check: 28 mutants over the request, schema and inbox (bounds, deadlines, queue, validation on both sides, acknowledgement, instance key): all killed.
- Not verified by running: `Program.Main` itself (it needs the WinUI entry point). Its two new branches are covered only by reading and by the inbox tests for the conditions they react to (name taken, no listener, refusal).
Not run: the FlaUI desktop suite.
## AI assistance
Written with Claude Fable 5.2. An independent read-only review of this diff is recorded below before merge.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
The reader created its activation pipe outside any error handling, so it
could not start while the pipe name was held by a reader that had not
finished closing or by another program. It now starts without an inbox,
and releases the pipe before the instance key so the next reader can
create its own.
A launch whose request the running reader does not take (no listener, a
refusal, or a deadline) used to exit with code 1 and no window. It now
opens its documents in its own process. An argument that cannot name a
document is dropped and reported while the usable ones still open.
The request, schema and inbox move to Core/Activation, inside the
coverage gate and the core test run. Deadlines run on a TimeProvider:
a sender waits two seconds for the pipe and each side ten seconds for one
exchange, and the tests reach both without waiting. The listener's
disconnect and Dispose share a lock instead of catching the race between
them.
ADR-0005, the threat model, the fuzzing guide and the GitHub shadow
workflows follow the move.
Closes#52
Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
Signed-off-by: James Maes <james@kof22.com>
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Closes #52.
Problem
See #52: the reader could fail to start when its activation pipe name was unavailable, a launch could exit without opening its document, one unusable argument discarded the rest, and the activation code sat outside the coverage gate with tests the Gitea workflow never ran.
Change
Program.Main: the inbox is created inside error handling and may be absent; the pipe is released before the instance key; a launch whose forward fails opens its documents itself instead of exiting with code 1.ActivationRequest,ActivationJsonContext,ActivationInboxmove tosrc/MarkdownViewr.Windows.Core/Activation(their tests move to the core test project).ActivationRequest.Createkeeps usable arguments and flags unusable ones.ActivationInbox: deadlines on aTimeProvider(2 s to connect, 10 s per exchange);Disposeand the listener's disconnect share a lock, which removes the catch for the race between them.User-visible: starting the reader a second time now always opens the document; the process exit code for a failed hand-off is no longer 1.
Verification (run)
Program.Mainitself (it needs the WinUI entry point). Its two new branches are covered only by reading and by the inbox tests for the conditions they react to (name taken, no listener, refusal).Not run: the FlaUI desktop suite.
AI assistance
Written with Claude Fable 5.2. An independent read-only review of this diff is recorded below before merge.
🤖 Generated with Claude Code
View command line instructions
Checkout
From your project repository, check out a new branch and test the changes.