### browser and container diagnostics # Target: http://localhost:3000 # Attempt 1: playwright-cli open http://localhost:3000 # Result: net::ERR_SOCKET_NOT_CONNECTED # Attempt 2: playwright-cli goto http://localhost:3000 after restart diagnosis # Result: net::ERR_CONNECTION_RESET # Direct nested-container probe: curl -sS -D - http://127.0.0.1:3000/ # Result: curl: (7) Failed to connect to 127.0.0.1 port 3000 after 0 ms: Could not connect to server # Listener probe: ss -ltnp showed only 127.0.0.11:39089 and no application listener. # Environment diagnosis: the repository is a native macOS SwiftUI/AppKit app; the Linux # nested container has no GUI app process and its devcontainer command is sleep infinity. # Restart helper invocation released no port and started no service. ### reproduction procedure # Not executed: the native macOS publish surface was unavailable in the Linux nested environment. # 1. Prepare a vault with a published Markdown note and a published Cooklang or Textile note. # 2. Start two Publish Site actions almost at the same time, before the first one finishes. # 3. Wait for both actions to finish and inspect the index, nested page, assets, and publish result. # 4. Compare the final files with each publish's expected note set and check that all pages # and links belong to one complete snapshot. ### publish orchestration // Sources/BANALPublisher/BANALPublisher.swift:24-69 public func publish( notes: [Note], vault: VaultConfiguration, configuration: PublishConfiguration, now: Date = Date(), fileManager: FileManager = .default ) throws -> PublishResult { // ... note filtering and rendering ... let staged = try BorisAdapter.stage( notes: compiled, configuration: configuration, assetsSource: vault.assetsURL, markupHTML: markupHTML, fileManager: fileManager ) let compile = try compiler.compile( stagingDirectory: configuration.stagingDirectory, artifactDirectory: configuration.artifactDirectory, pages: staged.pages, configuration: configuration ) } # The publish method proceeds through staging and compilation without a shared lock or actor. # Both operations receive the same configuration-provided staging and artifact paths. ### staging reset // Sources/BANALPublisher/BorisAdapter.swift:141-148 let staging = configuration.stagingDirectory if fileManager.fileExists(atPath: staging.path) { try fileManager.removeItem(at: staging) } let content = staging.appendingPathComponent("content", isDirectory: true) let layouts = staging.appendingPathComponent("layouts", isDirectory: true) try fileManager.createDirectory(at: content, withIntermediateDirectories: true) try fileManager.createDirectory(at: layouts, withIntermediateDirectories: true) ### artifact reset and page writes // Sources/BANALPublisher/SiteCompiler.swift:33-48 let fileManager = FileManager.default if fileManager.fileExists(atPath: artifactDirectory.path) { try fileManager.removeItem(at: artifactDirectory) } try fileManager.createDirectory(at: artifactDirectory, withIntermediateDirectories: true) for page in pages { let rendered = SiteHTML.document( page: page, pages: pages, configuration: configuration, bodyHTML: page.prebuiltBodyHTML ) let destination = artifactDirectory.appendingPathComponent("\(page.entityID).html") try fileManager.createDirectory(at: destination.deletingLastPathComponent(), withIntermediateDirectories: true) try Data(rendered.utf8).write(to: destination, options: .atomic) } ### Boris output replacement // Sources/BANALPublisher/SiteCompiler.swift:124-127, 159-162 let relativeDist = stagingDirectory.appendingPathComponent("dist", isDirectory: true) if fileManager.fileExists(atPath: relativeDist.path) { try fileManager.removeItem(at: relativeDist) } if fileManager.fileExists(atPath: artifactDirectory.path) { try fileManager.removeItem(at: artifactDirectory) } try fileManager.copyItem(at: relativeDist, to: artifactDirectory) # final result: BF-RAPID-1 failed. The browser scenario was blocked, but source review confirms # that overlapping publishes can delete and rebuild shared staging/artifact paths while another # publish is staging or compiling, leaving mixed or incomplete output.