Sub-scope 08 (mongo) changestream - manifest and negative-space probes
revision=a24ece9cf797f7ea647e33bf846b115208ed1ba5
generatedAt=2026-08-30T00:15:09+00:00
cwd=/shared/codebase/clean-architecture-backend-template/src

=== OWNED FILES ===
55410c37d99e15fd487d45057a2f44fe2b656582 main/java/dev/caskeleton/adapter/outbound/mongo/changestream/MongoChangeEventIdentity.java 97
2a41c567b37fd2cd0f7adcbd0cf1db3583f020bc main/java/dev/caskeleton/adapter/outbound/mongo/changestream/MongoChangeStreamPipeline.java 85
462398af539336129b4a1f0cf669a94eb0c52120 main/java/dev/caskeleton/adapter/outbound/mongo/changestream/MongoChangeStreamState.java 35
d6a137168ebf884948907dc09a86833bc68a1983 main/java/dev/caskeleton/adapter/outbound/mongo/changestream/MongoChangeStreamSubscription.java 50
b9cb4a344e54678c7c02fc48e71851fc2e84e79c main/java/dev/caskeleton/adapter/outbound/mongo/changestream/MongoClusterTime.java 53
240d41177c0bf08b810928ed61dbdd07874b4a43 main/java/dev/caskeleton/adapter/outbound/mongo/changestream/MongoResumeCheckpoint.java 100
ccac8af549c5ed7b23ed3be2fa1ad68cc1ef5f48 main/java/dev/caskeleton/adapter/outbound/mongo/changestream/MongoResumeCheckpointStore.java 24
22ee8f0391d93b109f3ffa763f1a2acc03564de8 main/java/dev/caskeleton/adapter/outbound/mongo/changestream/MongoResumePosition.java 18
52b776c4178d40bae2e7b48cfcff2207c25cc3ab main/java/dev/caskeleton/adapter/outbound/mongo/changestream/MongoResumeTokenCodec.java 38
76e710168870ef9d9e8a464dba087e247315ccff main/java/dev/caskeleton/adapter/outbound/mongo/changestream/consumer/MongoChangeStreamSource.java 54
5d2c65139d86fefc8f341a120dd3abdff345f368 main/java/dev/caskeleton/adapter/outbound/mongo/changestream/consumer/ReactiveMongoChangeStreamConsumer.java 221
6d2bd659cc831094d7854fcfc4560846ff03927a main/java/dev/caskeleton/adapter/outbound/mongo/changestream/consumer/SpringReactiveChangeStreamSource.java 71
8a7ba018966876acb9c64b9e7906ba11407f0c44 main/java/dev/caskeleton/adapter/outbound/mongo/changestream/projector/MongoChangeClaim.java 25
43032013612390ba42527cfa06d5c74f47409a42 main/java/dev/caskeleton/adapter/outbound/mongo/changestream/projector/MongoChangeDeduplicationStore.java 50
ba15c66e206050463073a2c373e88936d6ec6f36 main/java/dev/caskeleton/adapter/outbound/mongo/changestream/projector/MongoChangeProjectionResult.java 65
75e656da9f039e0124dee52b0e4b55555429c943 main/java/dev/caskeleton/adapter/outbound/mongo/changestream/projector/MongoChangeProjector.java 23
8a49dd99ecf66f528ddba3f17c38f5594d3dc3d4 main/java/dev/caskeleton/adapter/outbound/mongo/changestream/projector/MongoChangeStreamRunner.java 124
a956f31fd1f2779fc1063cfd1407ab098f65bb82 main/java/dev/caskeleton/adapter/outbound/mongo/changestream/recovery/MongoChangeHistoryLostException.java 35
8b02975c382f8df615b19260076554c64aaabf66 main/java/dev/caskeleton/adapter/outbound/mongo/changestream/recovery/MongoChangeStreamRecoveryDecision.java 36
fe947e6c533518c9560650b808cc29b1b0e23ae6 main/java/dev/caskeleton/adapter/outbound/mongo/changestream/recovery/MongoChangeStreamRecoveryPolicy.java 67
88ca505e553bf03721e270d95cf43de6446f5406 main/java/dev/caskeleton/adapter/outbound/mongo/changestream/recovery/MongoInvalidateRecovery.java 46
c51cc24680d0b2cd33c18ca36d4c87f6518287b8 test/java/dev/caskeleton/adapter/outbound/mongo/changestream/MongoChangeStreamPipelineTest.java 153
60a0312b904e8b8ecee216bc84942c2ce8fbe4cc test/java/dev/caskeleton/adapter/outbound/mongo/changestream/MongoResumeCheckpointStoreTest.java 85
a9c7b48469df8438d48ae3edfce562c692c99ab8 test/java/dev/caskeleton/adapter/outbound/mongo/changestream/consumer/ChangeStreamConsumerLifecycleTest.java 332
39c83409212c07edc25c72849e35a3488d3fe7df test/java/dev/caskeleton/adapter/outbound/mongo/changestream/projector/MongoChangeStreamRunnerTest.java 357
d20e9e4712dae2642af4308eda984f84ff0ce8b0 test/java/dev/caskeleton/adapter/outbound/mongo/changestream/recovery/MongoChangeStreamRecoveryPolicyTest.java 69

production: 21
test: 5
production LOC:  1317 total

=== 8.1 reachability: beans and cross-package production references ===
$ grep -n 'ChangeStream\|changestream\|Projector\|Resume' adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/autoconfigure/MongoPlatformAutoConfiguration.java
209:    public dev.caskeleton.adapter.outbound.mongo.changestream.consumer.MongoChangeStreamSource
210:        mongoChangeStreamSource(
213:      return new dev.caskeleton.adapter.outbound.mongo.changestream.consumer
214:          .SpringReactiveChangeStreamSource(template, collections);
228:      dev.caskeleton.adapter.outbound.mongo.changestream.MongoChangeStreamSubscription.class,
229:      dev.caskeleton.adapter.outbound.mongo.changestream.MongoResumeCheckpointStore.class,
230:      dev.caskeleton.adapter.outbound.mongo.changestream.MongoResumeTokenCodec.class,
231:      dev.caskeleton.adapter.outbound.mongo.changestream.projector.MongoChangeProjector.class,
232:      dev.caskeleton.adapter.outbound.mongo.changestream.projector.MongoChangeDeduplicationStore
235:    public dev.caskeleton.adapter.outbound.mongo.changestream.consumer
236:            .ReactiveMongoChangeStreamConsumer
237:        reactiveMongoChangeStreamConsumer(
238:            dev.caskeleton.adapter.outbound.mongo.changestream.MongoChangeStreamSubscription
240:            dev.caskeleton.adapter.outbound.mongo.changestream.consumer.MongoChangeStreamSource
242:            dev.caskeleton.adapter.outbound.mongo.changestream.MongoResumeCheckpointStore
244:            dev.caskeleton.adapter.outbound.mongo.changestream.MongoResumeTokenCodec tokens,
245:            dev.caskeleton.adapter.outbound.mongo.changestream.projector.MongoChangeProjector
247:            dev.caskeleton.adapter.outbound.mongo.changestream.projector
250:      return new dev.caskeleton.adapter.outbound.mongo.changestream.consumer
251:          .ReactiveMongoChangeStreamConsumer(
256:          new dev.caskeleton.adapter.outbound.mongo.changestream.MongoChangeStreamPipeline(
257:              new dev.caskeleton.adapter.outbound.mongo.changestream.projector
258:                  .MongoChangeStreamRunner(projector, deduplication, checkpoints)),
259:          new dev.caskeleton.adapter.outbound.mongo.changestream.recovery
260:              .MongoChangeStreamRecoveryPolicy(),
261:          new dev.caskeleton.adapter.outbound.mongo.changestream.recovery
exit=0

$ git grep -n 'changeStreams' adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/autoconfigure/MongoPlatformSettings.java adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/autoconfigure/MongoPlatformAutoConfiguration.java adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/autoconfigure/MongoStartupValidator.java
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/autoconfigure/MongoPlatformAutoConfiguration.java:363:              properties.changeStreams(),
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/autoconfigure/MongoPlatformSettings.java:22: * assuming it. Both it and {@code changeStreams} used to be literal {@code true}s passed into
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/autoconfigure/MongoPlatformSettings.java:30:    boolean changeStreams,
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/autoconfigure/MongoPlatformSettings.java:55:    changeStreams = false;
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/autoconfigure/MongoStartupValidator.java:34:  private final boolean changeStreamsEnabled;
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/autoconfigure/MongoStartupValidator.java:44:      boolean changeStreamsEnabled,
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/autoconfigure/MongoStartupValidator.java:51:    this.changeStreamsEnabled = changeStreamsEnabled;
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/autoconfigure/MongoStartupValidator.java:104:    if (changeStreamsEnabled && !capabilities.isStable(MongoCapability.CHANGE_STREAM)) {
exit=0

$ git grep -ln 'changestream' -- 'adapter/outbound/persistence-mongo/src/main' | grep -v '/changestream/'
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/advanced/bridge/MongoChangeMessagingBridge.java
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/advanced/bridge/MongoChangeToIntegrationEventMapper.java
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/autoconfigure/MongoPlatformAutoConfiguration.java
exit=0

$ git grep -n 'new ReactiveMongoChangeStreamConsumer\|new SpringReactiveChangeStreamSource\|new MongoChangeStreamPipeline\|new MongoChangeStreamRunner' -- 'adapter/outbound/persistence-mongo/src/main'
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/changestream/consumer/ReactiveMongoChangeStreamConsumer.java:145:        new MongoChangeStreamPipeline.MongoChangeEvent(
exit=0

=== 8.1b implementations of the three SPIs a deployment must supply ===
$ git grep -n 'implements MongoResumeTokenCodec\|implements MongoResumeCheckpointStore\|implements MongoChangeDeduplicationStore\|implements MongoChangeProjector' -- 'adapter/outbound/persistence-mongo/src'
adapter/outbound/persistence-mongo/src/test/java/dev/caskeleton/adapter/outbound/mongo/advanced/bridge/MongoChangeMessagingBridgeTest.java:115:  private static final class CountingCheckpointStore implements MongoResumeCheckpointStore {
adapter/outbound/persistence-mongo/src/test/java/dev/caskeleton/adapter/outbound/mongo/changestream/MongoChangeStreamPipelineTest.java:117:  private static final class AlwaysClaims implements MongoChangeDeduplicationStore {
adapter/outbound/persistence-mongo/src/test/java/dev/caskeleton/adapter/outbound/mongo/changestream/MongoChangeStreamPipelineTest.java:136:  private static final class NoOpCheckpoints implements MongoResumeCheckpointStore {
adapter/outbound/persistence-mongo/src/test/java/dev/caskeleton/adapter/outbound/mongo/changestream/consumer/ChangeStreamConsumerLifecycleTest.java:211:  private static final class PlainTextCodec implements MongoResumeTokenCodec {
adapter/outbound/persistence-mongo/src/test/java/dev/caskeleton/adapter/outbound/mongo/changestream/consumer/ChangeStreamConsumerLifecycleTest.java:261:  private static final class RecordingCheckpointStore implements MongoResumeCheckpointStore {
adapter/outbound/persistence-mongo/src/test/java/dev/caskeleton/adapter/outbound/mongo/changestream/consumer/ChangeStreamConsumerLifecycleTest.java:295:  private final class CountingProjector implements MongoChangeProjector {
adapter/outbound/persistence-mongo/src/test/java/dev/caskeleton/adapter/outbound/mongo/changestream/consumer/ChangeStreamConsumerLifecycleTest.java:314:  private static final class AlwaysClaims implements MongoChangeDeduplicationStore {
adapter/outbound/persistence-mongo/src/test/java/dev/caskeleton/adapter/outbound/mongo/changestream/projector/MongoChangeStreamRunnerTest.java:101:  private static final class RecordingCheckpointStore implements MongoResumeCheckpointStore {
adapter/outbound/persistence-mongo/src/test/java/dev/caskeleton/adapter/outbound/mongo/changestream/projector/MongoChangeStreamRunnerTest.java:290:  private static final class ClaimingDeduplicationStore implements MongoChangeDeduplicationStore {
adapter/outbound/persistence-mongo/src/test/java/dev/caskeleton/adapter/outbound/mongo/changestream/projector/MongoChangeStreamRunnerTest.java:339:  private static final class EmptyDeduplicationStore implements MongoChangeDeduplicationStore {
exit=0

=== 8.2 the high-water mark: set before processing, kept across a resume ===
$ grep -n 'advancesPosition\|getAndAccumulate\|highWaterMark' adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/MongoChangeStreamPipeline.java 2>/dev/null || grep -n 'advancesPosition\|getAndAccumulate\|highWaterMark' adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/changestream/MongoChangeStreamPipeline.java
32:  private final AtomicReference<MongoClusterTime> highWaterMark = new AtomicReference<>();
49:    if (!advancesPosition(event.clusterTime())) {
58:  private boolean advancesPosition(MongoClusterTime candidate) {
60:        highWaterMark.getAndAccumulate(
67:  public MongoClusterTime highWaterMark() {
68:    return highWaterMark.get();
exit=0

$ grep -n 'allowsCheckpointAdvance' -B 8 adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/changestream/projector/MongoChangeProjectionResult.java
38-  }
39-
40-  /** The event could not be interpreted and was routed to the parking workflow. */
41-  public static MongoChangeProjectionResult parked(String reason) {
42-    return new MongoChangeProjectionResult(Outcome.PARKED, reason);
43-  }
44-
45-  /** True when the checkpoint may advance past this event. */
46:  public boolean allowsCheckpointAdvance() {
exit=0

$ grep -n 'recoverFrom\|openAndConsume\|Flux.defer' adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/changestream/consumer/ReactiveMongoChangeStreamConsumer.java
87:        .thenMany(Flux.defer(this::openAndConsume))
88:        .onErrorResume(this::recoverFrom);
101:  private Flux<MongoChangeProjectionResult> openAndConsume() {
188:  private Flux<MongoChangeProjectionResult> recoverFrom(Throwable failure) {
199:    return Flux.defer(this::openAndConsume).onErrorResume(this::haltOn);
exit=0

=== 8.2b does any test cover a redelivery after a resume? ===
$ grep -n 'aResumableFailureReopensFromTheCheckpoint' -A 16 adapter/outbound/persistence-mongo/src/test/java/dev/caskeleton/adapter/outbound/mongo/changestream/consumer/ChangeStreamConsumerLifecycleTest.java
93:  void aResumableFailureReopensFromTheCheckpoint() {
94-    checkpoints.stored = Optional.of(checkpoint("token-1", MongoResumePosition.RESUME_AFTER));
95-    MongoQueryException resumable = queryFailure(133, "ResumableChangeStreamError");
96-    RecordingSource source =
97-        new RecordingSource(
98-            Flux.error(resumable), Flux.just(event("token-2", 2, OperationType.INSERT)));
99-
100-    ReactiveMongoChangeStreamConsumer consumer = consumer(source);
101-    StepVerifier.create(consumer.run()).expectNextCount(1).verifyComplete();
102-
103-    assertThat(source.opens).isEqualTo(2);
104-    assertThat(source.reopenedAt.orElseThrow().token().getString("_data").getValue())
105-        .as("the last written position is the last event a projection completed for")
106-        .isEqualTo("token-1");
107-  }
108-
109-  @Test
exit=0

$ grep -n 'anEventBehindTheHighWaterMarkIsDropped' -A 24 adapter/outbound/persistence-mongo/src/test/java/dev/caskeleton/adapter/outbound/mongo/changestream/MongoChangeStreamPipelineTest.java
62:  void anEventBehindTheHighWaterMarkIsDropped() {
63-    List<String> projected = new ArrayList<>();
64-    MongoChangeStreamPipeline pipeline =
65-        new MongoChangeStreamPipeline(
66-            new MongoChangeStreamRunner(
67-                (identity, change) -> {
68-                  projected.add(change.getString("id").getValue());
69-                  return Mono.just(MongoChangeProjectionResult.applied());
70-                },
71-                new AlwaysClaims(),
72-                new NoOpCheckpoints()));
73-
74-    pipeline
75-        .process(Flux.just(event("a", 5), event("late", 2), event("b", 6)))
76-        .collectList()
77-        .block();
78-
79-    assertThat(projected)
80-        .as("running it would move the resume checkpoint backwards over applied work")
81-        .containsExactly("a", "b");
82-    assertThat(pipeline.highWaterMark()).isEqualTo(new MongoClusterTime(1_700_000_000L, 6));
83-  }
84-
85-  @Test
86-  @DisplayName("cluster time compares numerically, not as text")
exit=0

$ grep -n 'aBusyClaimNeverAdvancesTheCheckpoint' -A 22 adapter/outbound/persistence-mongo/src/test/java/dev/caskeleton/adapter/outbound/mongo/changestream/projector/MongoChangeStreamRunnerTest.java
173:  void aBusyClaimNeverAdvancesTheCheckpoint() {
174-    RecordingCheckpointStore checkpoints = new RecordingCheckpointStore();
175-    ClaimingDeduplicationStore deduplication = new ClaimingDeduplicationStore();
176-    deduplication.claimFor(IDENTITY);
177-
178-    MongoChangeStreamRunner runner =
179-        new MongoChangeStreamRunner(
180-            (identity, change) -> Mono.just(MongoChangeProjectionResult.applied()),
181-            deduplication,
182-            checkpoints);
183-
184-    MongoChangeProjectionResult result =
185-        runner.runOne(IDENTITY, new BsonDocument(), CHECKPOINT).block();
186-
187-    assertThat(result.outcome()).isEqualTo(MongoChangeProjectionResult.Outcome.CLAIMED_ELSEWHERE);
188-    assertThat(checkpoints.saveCount())
189-        .as("the holder may still fail, and the stream never replays what the checkpoint passed")
190-        .isZero();
191-  }
192-
193-  @Test
194-  @org.junit.jupiter.api.DisplayName("a crash after claiming leaves the event retryable")
195-  void aCrashAfterClaimingLeavesTheEventRetryable() {
exit=0

=== 8.3 duplicate mechanisms inside recovery ===
$ git grep -n 'onHistoryLost\|onResumableFailure\|onInvalidate\|checkpointFor\|requireCorrectResumeOption\|autoResumable\|MongoChangeHistoryLostException' -- 'adapter/outbound/persistence-mongo/src'
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/advanced/tenancy/database/MongoTenantMigrationCoordinator.java:85:  public Optional<MongoMigrationCheckpoint> checkpointFor(String tenantKey) {
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/changestream/MongoChangeStreamState.java:32:  public boolean autoResumable() {
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/changestream/consumer/ReactiveMongoChangeStreamConsumer.java:119:          invalidates.requireCorrectResumeOption(checkpoint, checkpoint.position());
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/changestream/recovery/MongoChangeHistoryLostException.java:16:public final class MongoChangeHistoryLostException extends MongoPersistenceException {
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/changestream/recovery/MongoChangeHistoryLostException.java:22:  public MongoChangeHistoryLostException(
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/changestream/recovery/MongoChangeStreamRecoveryPolicy.java:29:  public MongoChangeStreamRecoveryDecision onHistoryLost(String subscriptionProfile) {
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/changestream/recovery/MongoChangeStreamRecoveryPolicy.java:36:  public MongoChangeStreamRecoveryDecision onResumableFailure() {
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/changestream/recovery/MongoChangeStreamRecoveryPolicy.java:46:  public MongoChangeStreamRecoveryDecision onInvalidate() {
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/changestream/recovery/MongoInvalidateRecovery.java:19:  public MongoResumeCheckpoint checkpointFor(String subscriptionProfile, byte[] invalidateToken) {
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/changestream/recovery/MongoInvalidateRecovery.java:31:  public void requireCorrectResumeOption(
adapter/outbound/persistence-mongo/src/test/java/dev/caskeleton/adapter/outbound/mongo/changestream/recovery/MongoChangeStreamRecoveryPolicyTest.java:21:    MongoChangeStreamRecoveryDecision decision = policy.onHistoryLost("orders");
adapter/outbound/persistence-mongo/src/test/java/dev/caskeleton/adapter/outbound/mongo/changestream/recovery/MongoChangeStreamRecoveryPolicyTest.java:31:    assertThat(policy.onResumableFailure().autoResume()).isTrue();
adapter/outbound/persistence-mongo/src/test/java/dev/caskeleton/adapter/outbound/mongo/changestream/recovery/MongoChangeStreamRecoveryPolicyTest.java:55:    MongoResumeCheckpoint checkpoint = recovery.checkpointFor("orders", new byte[] {1, 2, 3});
adapter/outbound/persistence-mongo/src/test/java/dev/caskeleton/adapter/outbound/mongo/changestream/recovery/MongoChangeStreamRecoveryPolicyTest.java:59:            () -> recovery.requireCorrectResumeOption(checkpoint, MongoResumePosition.RESUME_AFTER))
adapter/outbound/persistence-mongo/src/test/java/dev/caskeleton/adapter/outbound/mongo/changestream/recovery/MongoChangeStreamRecoveryPolicyTest.java:65:    assertThat(MongoChangeStreamState.RUNNING.autoResumable()).isTrue();
adapter/outbound/persistence-mongo/src/test/java/dev/caskeleton/adapter/outbound/mongo/changestream/recovery/MongoChangeStreamRecoveryPolicyTest.java:66:    assertThat(MongoChangeStreamState.HISTORY_LOST.autoResumable()).isFalse();
adapter/outbound/persistence-mongo/src/test/java/dev/caskeleton/adapter/outbound/mongo/changestream/recovery/MongoChangeStreamRecoveryPolicyTest.java:67:    assertThat(MongoChangeStreamState.FAILED.autoResumable()).isFalse();
exit=0

=== 8.4 documentation drift: the runbooks the policy names ===
$ ls ../docs/mongodb/runbooks/ 2>&1
failover.md
history-lost.md
unknown-commit.md
exit=0

$ grep -rn 'HISTORY_LOST_RUNBOOK\|FAILURE_RUNBOOK' adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/changestream/recovery/MongoChangeStreamRecoveryPolicy.java
18:  public static final String HISTORY_LOST_RUNBOOK = "docs/mongodb/runbooks/history-lost.md";
21:  public static final String FAILURE_RUNBOOK = "docs/mongodb/runbooks/failover.md";
32:        MongoChangeStreamState.HISTORY_LOST, HISTORY_LOST_RUNBOOK);
55:          MongoChangeStreamState.HISTORY_LOST, HISTORY_LOST_RUNBOOK);
60:    return MongoChangeStreamRecoveryDecision.halt(MongoChangeStreamState.FAILED, FAILURE_RUNBOOK);
exit=0

$ find .. -name 'history-lost.md' -o -name 'failover.md' | head
../docs/mongodb/runbooks/failover.md
../docs/mongodb/runbooks/history-lost.md
exit=0

