         "Incremental compilation: Enabling incremental cross-module building",
         "Incremental compilation: May skip current input:  {compile: main.o <= main.swift}",
         "Incremental compilation: May skip current input:  {compile: other.o <= other.swift}",
-        "Incremental compilation: May skip current input:  {compile: \(newInputBasenameWithoutExt).o <= \(newInputBasenameWithoutExt).swift}",
+        "Incremental compilation: May skip current input:  {compile: \(newInput).o <= \(newInput).swift}",
         "Incremental compilation: Skipping input:  {compile: main.o <= main.swift}",
         "Incremental compilation: Skipping input:  {compile: other.o <= other.swift}",
-        "Incremental compilation: Skipping input:  {compile: \(newInputBasenameWithoutExt).o <= \(newInputBasenameWithoutExt).swift}",
+        "Incremental compilation: Skipping input:  {compile: \(newInput).o <= \(newInput).swift}",
         "Incremental compilation: Skipping job: Linking theModule; oldest output is current",
-        "Skipped Compiling \(newInputBasenameWithoutExt).swift",
+        "Skipped Compiling \(newInput).swift",
         "Skipped Compiling main.swift",
         "Skipped Compiling other.swift",
       ],
       whenAutolinking: autolinkLifecycleExpectations)
       .moduleDependencyGraph()
-  }
-}
+
+    XCTAssert(graph.contains(sourceBasenameWithoutExt: newInput))
+    XCTAssert(graph.contains(name: topLevelName))
+  }
+}
+
+// MARK: - Incremental test perturbation helpers
+extension IncrementalCompilationTests {
+  private func touch(_ name: String) {
+    print("*** touching \(name) ***", to: &stderrStream); stderrStream.flush()
+    let (path, contents) = try! XCTUnwrap(inputPathsAndContents.filter {$0.0.pathString.contains(name)}.first)
+    try! localFileSystem.writeFileContents(path) { $0 <<< contents }
+  }
+
+  private func replace(contentsOf name: String, with replacement: String ) {
+    print("*** replacing \(name) ***", to: &stderrStream); stderrStream.flush()
+    let path = inputPath(basename: name)
+    let previousContents = try! localFileSystem.readFileContents(path).cString
+    try! localFileSystem.writeFileContents(path) { $0 <<< replacement }
+    let newContents = try! localFileSystem.readFileContents(path).cString
+    XCTAssert(previousContents != newContents, "\(path.pathString) unchanged after write")
+    XCTAssert(replacement == newContents, "\(path.pathString) failed to write")
+  }
+
+  private func write(_ contents: String, to basename: String) {
+    print("*** writing \(contents) to \(basename)")
+    try! localFileSystem.writeFileContents(inputPath(basename: basename)) {
+      $0 <<< contents
+    }
+  }
+}
+
+// MARK: - Graph inspection
+
 fileprivate extension Driver {
   func moduleDependencyGraph() throws -> ModuleDependencyGraph {
     do {return try XCTUnwrap(incrementalCompilationState?.moduleDependencyGraph) }


  func testDependencyDotFilesCross() throws {
    expectNoDotFiles()
    try tryInitial(extraArguments: [
      "-driver-emit-fine-grained-dependency-dot-file-after-every-import",
    ])
    removeDotFiles()
    try tryTouchingOther(extraArguments: [
      "-driver-emit-fine-grained-dependency-dot-file-after-every-import",
    ])


      ],
      whenAutolinking: [])
  }

  /// Check reaction to touching a non-propagating input.
  ///
  /// - Parameters:
  ///   - checkDiagnostics: If true verify the diagnostics
  ///   - extraArguments: Additional command-line arguments
  private func checkNoPropagation(
    checkDiagnostics: Bool = false,
    extraArguments: [String] = []
  ) throws {
    touch("other")
    try doABuild(
      "touch other; non-propagating",
      checkDiagnostics: checkDiagnostics,
      extraArguments: extraArguments,
      expectingRemarks: [
