Skip to content

FLT-75 — replay the Allyson incident against the fixed pipeline

Add ONE new test to FounderIntake.Tests (new file AllysonIncidentReplayTests.cs, same harness pattern as TrustHardeningTests.RealThreadReadyConfirmCreatesExactlyOneTicketAndReusesOriginalEnvelope — real ConversationStore, ReplyOutbox, EgressSanitizer, RequestStateMachine, IdempotencyStore, ConversationResponder; fake IJiraTicketCreator and a recording ICorrelatedThreadReplyWriter/outbox consumer; no real Slack/Jira network calls) that reproduces the actual incident shape from

work-wingman-intake on 2026-07-22, driven through ONE shared ConversationResponder instance

(same as the real single-host deployment):

Scenario (three concurrent threads, one host, one batch)

  • Thread A (slack:C1:100.1): requester Allyson (Slack id U_ALLYSON, display name "Allyson"), message: "Please help me compare the benefits of amazon bedrock vs microsoft foundry for running an up and coming Ai based application"
  • Thread B (slack:C1:200.1): requester Andrew (Slack id U_ANDREW, display name "Andrew"), message: "Test intake: can someone help me draft a one-pager for the pilot?"
  • Thread C (slack:C1:300.1): requester Andrew again, SAME requester as B but a DIFFERENT thread, message: "Test intake #2: please help me outline the pilot one-pager."

All three EnqueueJob calls happen before any ProcessOneBatchAsync call, so the responder handles them within the same batch/pass — this is what actually happened the night of the incident (multiple threads in flight on one host at once).

Assertions (this is the acceptance test from the original council verdict)

  1. No misaddressing: the reply enqueued for thread A greets/addresses Allyson only — assert her reply text contains "Allyson" and does NOT contain "Andrew". The replies for threads B/C address Andrew only and do NOT contain "Allyson".
  2. No cross-thread contamination: assert the CONTENT of thread A's reply/writeup has zero overlap with B/C's subject matter (no mention of "one-pager", "pilot", draft outline) and vice versa — each reply is about only its own requester's own message.
  3. Exactly one ticket per confirmed thread, no duplicates: drive each thread through its own READY_TO_FILE -> CONFIRM cycle (use a fake backend returning READY_TO_FILE: immediately, matching the existing ReadyBackend fake). After all three confirms, the fake Jira creator's CreateCount must be exactly 3 (one per thread), never more, even if a confirm is replayed/duplicated for one thread (add a duplicate confirm for thread A and assert the count is still 3).
  4. No internal leak: none of the three replies' enqueued text may contain any of: 127.0.0.1, BOARD.md, [Jira FLT-, WT- followed by hex, or the harness names (Jenny, Cody, Clahadore, Gronktayvius). If you want to prove the sanitizer's role concretely, inject one thread's fake backend response with an internal string (e.g. append "\n[Jira FLT-3](https://workwingman.atlassian.net/browse/FLT-3)" to its READY_TO_FILE text) and assert that specific reply is HELD (not enqueued as pending) rather than delivered.
  5. Single-writer sanity: run the whole scenario through TWO IntakeLeaderLease-guarded responder instances pointed at the same DB/lease store (mirroring IntakeLeaderCoordinator), where only the leader is allowed to actually drain replies — assert the non-leader instance produces zero outbound sends.

Constraints

  • C# only, xUnit, follow the existing style in TrustHardeningTests.cs (helper fakes already defined there — RecordingJira, ReadyBackend, GovernorClient usage — reuse them; only add what's missing).
  • No real network I/O anywhere in the test.
  • dotnet build FounderIntake.slnx and dotnet test FounderIntake.slnx must be clean/green (including all pre-existing tests).
  • Do not commit. Leave changes uncommitted for review.
  • If any assertion FAILS against the current code (i.e. the replay finds a real regression or gap), do NOT weaken the assertion to make it pass — report the failure exactly as found and stop; that is a real finding, not a test-authoring problem.
  • End with: pass/fail per assertion, and the full dotnet test output tail.