docs(comments): strip internal task/milestone/bundle bookkeeping from code comments

Remove project bookkeeping citations from shipped code comments across the
solution: hyphenated task IDs (WP-14, StoreAndForward-025), milestone/task/
issue refs (M3, Task 4, Audit Log #23, #21), Bundle X task-bundle labels,
and C/D/K/S/T phase labels.

Comment text only — no code logic, string/log literals, or XML-doc structure
changed. Genuine descriptions are preserved (only the citation is stripped),
and technical lookalikes are retained (UTF-8, SHA-256, T00:00:00, M365,
UTC-5, pre-C4/pre-C5 schema versions). Flagged by the new CommentChecker
TaskReferenceInComment / TrackingReferenceInComment checks plus targeted
grep passes; full solution builds clean, append-only guard tests pass.
This commit is contained in:
Joseph Doherty
2026-07-07 11:03:26 -04:00
parent 67005ca4c0
commit 9cff87fe85
435 changed files with 2338 additions and 2547 deletions
@@ -12,7 +12,7 @@ using AuditOutcome = ZB.MOM.WW.Audit.AuditOutcome;
namespace ZB.MOM.WW.ScadaBridge.AuditLog.Site;
/// <summary>
/// Site-side SQLite hot-path writer for Audit Log (#23) events. Mirrors the
/// Site-side SQLite hot-path writer for Audit Log events. Mirrors the
/// <see cref="ZB.MOM.WW.ScadaBridge.SiteEventLogging.SiteEventLogger"/> design — a single
/// owned <see cref="SqliteConnection"/> serialised behind a write lock, fed by a
/// bounded <see cref="Channel{T}"/> drained on a dedicated background writer
@@ -20,7 +20,7 @@ namespace ZB.MOM.WW.ScadaBridge.AuditLog.Site;
/// </summary>
/// <remarks>
/// <para>
/// <b>C4 (Task 2.5) — two-table schema.</b> The site store is now two tables:
/// <b>Two-table schema.</b> The site store is now two tables:
/// the append-only canonical <c>audit_event</c> (the 10 canonical
/// <see cref="AuditEvent"/> fields stored directly — NO 24-column decompose) and
/// the mutable operational <c>audit_forward_state</c> sidecar that carries the
@@ -31,10 +31,10 @@ namespace ZB.MOM.WW.ScadaBridge.AuditLog.Site;
/// </para>
/// <para>
/// <b>Ephemeral reset.</b> The site SQLite store is ephemeral (≈7-day retention,
/// recreated per deployment), so C4's schema change is an in-place RESET: the new
/// recreated per deployment), so this schema change is an in-place RESET: the new
/// tables are created and the old single 24-column <c>AuditLog</c> table is
/// DROP-ped if present. No SQLite data migration is performed (and none is
/// needed) — any rows in a pre-C4 <c>AuditLog</c> table are within the retention
/// needed) — any rows in the old <c>AuditLog</c> table are within the retention
/// window and are discarded by the drop.
/// </para>
/// <para>
@@ -56,7 +56,7 @@ public class SqliteAuditWriter : IAuditWriter, ISiteAuditQueue, IAsyncDisposable
private const int SqliteErrorConstraint = 19;
private readonly SqliteConnection _connection;
// AuditLog-005: dedicated read-only connection used by GetBacklogStatsAsync,
// Dedicated read-only connection used by GetBacklogStatsAsync,
// ReadPendingAsync, ReadPendingSinceAsync, and ReadForwardedAsync so a slow
// backlog scan (COUNT(*) over hundreds of thousands of Pending rows under a
// central outage) never parks the hot-path writer behind _writeLock.
@@ -102,7 +102,7 @@ public class SqliteAuditWriter : IAuditWriter, ISiteAuditQueue, IAsyncDisposable
InitializeSchema();
// AuditLog-005: open a second connection for read-only callers
// Open a second connection for read-only callers
// (GetBacklogStatsAsync, ReadPendingAsync, ReadPendingSinceAsync,
// ReadForwardedAsync). InitializeSchema set journal_mode=WAL on the
// writer connection, which is a database-level setting that persists
@@ -128,7 +128,7 @@ public class SqliteAuditWriter : IAuditWriter, ISiteAuditQueue, IAsyncDisposable
new BoundedChannelOptions(_options.ChannelCapacity)
{
// The hot-path enqueue must back-pressure if the background
// writer falls behind; a higher-level fallback (Bundle B-T4)
// writer falls behind; a higher-level fallback
// handles truly catastrophic primary failure with a drop-oldest
// ring buffer.
FullMode = BoundedChannelFullMode.Wait,
@@ -150,7 +150,7 @@ public class SqliteAuditWriter : IAuditWriter, ISiteAuditQueue, IAsyncDisposable
pragmaCmd.ExecuteNonQuery();
}
// AuditLog-005: enable WAL so a second connection on the same file can
// Enable WAL so a second connection on the same file can
// serve read-only callers (GetBacklogStatsAsync, ReadPendingAsync,
// ReadPendingSinceAsync, ReadForwardedAsync) concurrently with the
// batched writer, decoupling those reads from _writeLock. WAL is a
@@ -185,14 +185,14 @@ public class SqliteAuditWriter : IAuditWriter, ISiteAuditQueue, IAsyncDisposable
pragmaCmd.ExecuteNonQuery();
}
// C4 (Task 2.5) — in-place reset. The site store is EPHEMERAL (≈7-day
// In-place reset. The site store is EPHEMERAL (≈7-day
// retention, recreated per deployment), so we do NOT migrate the old
// single 24-column AuditLog table to the new two-table shape: any rows
// it holds are within the retention window and discarded. DROP it if a
// pre-C4 deployment left it behind, then CREATE the two new tables. This
// it holds are within the retention window and discarded. DROP it if an
// earlier deployment left it behind, then CREATE the two new tables. This
// is safe precisely BECAUSE the site store is ephemeral — never do this
// on a durable store (the central SQL Server side keeps its shim until
// C5 and is migrated, not reset).
// it is migrated, not reset).
using (var dropCmd = _connection.CreateCommand())
{
dropCmd.CommandText = "DROP TABLE IF EXISTS AuditLog;";
@@ -442,10 +442,10 @@ public class SqliteAuditWriter : IAuditWriter, ISiteAuditQueue, IAsyncDisposable
}
}
// AuditLog-001: cached-lifecycle audit kinds that ride the combined-telemetry
// Cached-lifecycle audit kinds that ride the combined-telemetry
// drain (joined with the operational tracking row + pushed via
// IngestCachedTelemetryAsync into the central dual-write transaction).
// C4: this is the SAME set the pre-C4 ReadPendingCachedTelemetryAsync query
// This is the SAME set the earlier ReadPendingCachedTelemetryAsync query
// filtered on (Kind IN (...)); it is now precomputed into the sidecar's
// IsCachedKind flag at INSERT (see IsCachedKind) so the read split is a cheap
// integer predicate, not a JSON parse. ReadPendingAsync drains everything
@@ -459,7 +459,7 @@ public class SqliteAuditWriter : IAuditWriter, ISiteAuditQueue, IAsyncDisposable
};
/// <summary>
/// C4: precomputes the sidecar's <c>IsCachedKind</c> flag from a canonical
/// Precomputes the sidecar's <c>IsCachedKind</c> flag from a canonical
/// row's <c>DetailsJson</c>. Parses the <see cref="AuditDetails.Kind"/>
/// discriminator via <see cref="AuditDetailsCodec"/> and returns <c>true</c>
/// iff it is one of the cached-lifecycle kinds
@@ -489,14 +489,14 @@ public class SqliteAuditWriter : IAuditWriter, ISiteAuditQueue, IAsyncDisposable
throw new ArgumentOutOfRangeException(nameof(limit), "limit must be > 0.");
}
// AuditLog-005: read via the dedicated _readConnection so this scan
// Read via the dedicated _readConnection so this scan
// (which can be expensive when the backlog grows under a central
// outage) does not block the batched writer on _writeLock. WAL mode
// gives us a stable snapshot of the tables while writes proceed on the
// writer connection. _readLock serialises this connection across
// multiple concurrent read callers since SqliteConnection itself is
// not thread-safe.
// C4: JOIN the sidecar and filter on IsCachedKind=0 — the cached-
// JOIN the sidecar and filter on IsCachedKind=0 — the cached-
// lifecycle kinds (IsCachedKind=1) flow through
// ReadPendingCachedTelemetryAsync + the combined-telemetry drain. The
// split is a precomputed integer predicate on the indexed sidecar, not
@@ -539,7 +539,7 @@ public class SqliteAuditWriter : IAuditWriter, ISiteAuditQueue, IAsyncDisposable
throw new ArgumentOutOfRangeException(nameof(limit), "limit must be > 0.");
}
// AuditLog-001 / C4: dedicated read surface for the cached-call lifecycle
// Dedicated read surface for the cached-call lifecycle
// drain — symmetric to ReadPendingAsync but filtered to IsCachedKind=1.
// Same _readConnection + _readLock pattern so the hot-path writer is not
// contended.
@@ -586,9 +586,9 @@ public class SqliteAuditWriter : IAuditWriter, ISiteAuditQueue, IAsyncDisposable
throw new ArgumentOutOfRangeException(nameof(limit), "limit must be > 0.");
}
// AuditLog-005: mirror ReadPendingAsync — read via _readConnection /
// Mirror ReadPendingAsync — read via _readConnection /
// _readLock so this query never contends with the batched writer on
// _writeLock. C4: JOIN the sidecar and filter on ForwardState='Forwarded'
// _writeLock. JOIN the sidecar and filter on ForwardState='Forwarded'
// (no IsCachedKind split — both cached and non-cached Forwarded rows are
// returned, as before).
lock (_readLock)
@@ -626,7 +626,7 @@ public class SqliteAuditWriter : IAuditWriter, ISiteAuditQueue, IAsyncDisposable
ObjectDisposedException.ThrowIf(_disposed, this);
using var cmd = _connection.CreateCommand();
// C4: flip the sidecar — UPDATE audit_forward_state, not the canonical
// Flip the sidecar — UPDATE audit_forward_state, not the canonical
// audit_event (which is append-only / write-once). Bump AttemptCount +
// stamp LastAttemptUtc so operators can see how many drain passes a row
// took to forward. Build a single IN (...) parameter list so we issue
@@ -667,7 +667,7 @@ public class SqliteAuditWriter : IAuditWriter, ISiteAuditQueue, IAsyncDisposable
/// <summary>
/// Returns up to <paramref name="batchSize"/> pending or forwarded audit events
/// with <see cref="AuditEvent.OccurredAtUtc"/> &gt;= <paramref name="sinceUtc"/>, oldest first.
/// Used by the M6 reconciliation-pull handler.
/// Used by the reconciliation-pull handler.
/// </summary>
/// <param name="sinceUtc">Lower bound timestamp (UTC) for event occurrence.</param>
/// <param name="batchSize">Maximum number of rows to return.</param>
@@ -681,8 +681,8 @@ public class SqliteAuditWriter : IAuditWriter, ISiteAuditQueue, IAsyncDisposable
throw new ArgumentOutOfRangeException(nameof(batchSize), "batchSize must be > 0.");
}
// AuditLog-005: read via _readConnection / _readLock — same lock-
// decoupling as ReadPendingAsync. C4: JOIN the sidecar; the range scan
// Read via _readConnection / _readLock — same lock-
// decoupling as ReadPendingAsync. JOIN the sidecar; the range scan
// is on the sidecar's duplicated OccurredAtUtc so it stays on IX_fwd.
// Both Pending and Forwarded rows are returned (the central reconciliation
// puller dedups on EventId; re-shipping a Forwarded-but-not-yet-ingested
@@ -729,7 +729,7 @@ public class SqliteAuditWriter : IAuditWriter, ISiteAuditQueue, IAsyncDisposable
ObjectDisposedException.ThrowIf(_disposed, this);
using var cmd = _connection.CreateCommand();
// C4: flip the sidecar from Pending/Forwarded → Reconciled. Rows
// Flip the sidecar from Pending/Forwarded → Reconciled. Rows
// already Reconciled are left untouched (idempotent re-call), and the
// canonical audit_event row is never modified.
var sb = new System.Text.StringBuilder();
@@ -759,13 +759,13 @@ public class SqliteAuditWriter : IAuditWriter, ISiteAuditQueue, IAsyncDisposable
int pendingCount;
DateTime? oldestPending;
// AuditLog-005: read via the dedicated _readConnection (under
// Read via the dedicated _readConnection (under
// _readLock) so this probe — polled every 30 s by SiteAuditBacklogReporter
// — never blocks the batched hot-path writer on _writeLock. Under a
// central outage the Pending backlog can grow to hundreds of thousands
// of rows and the COUNT(*) scan correspondingly stretches; that no
// longer adds tail latency to user-facing audit writes.
// C4: count over the sidecar (audit_forward_state) — the canonical
// Count over the sidecar (audit_forward_state) — the canonical
// audit_event table carries no ForwardState. The IX_fwd index makes both
// aggregates cheap (count is a covering scan, min is the first key).
lock (_readLock)
@@ -843,7 +843,7 @@ public class SqliteAuditWriter : IAuditWriter, ISiteAuditQueue, IAsyncDisposable
}
/// <summary>
/// C4: builds the canonical <see cref="AuditEvent"/> DIRECTLY from the 10
/// Builds the canonical <see cref="AuditEvent"/> DIRECTLY from the 10
/// stored <c>audit_event</c> columns — no 24-column <c>Recompose</c>, because
/// <c>audit_event</c> already holds the canonical fields + <c>DetailsJson</c>.
/// <c>Outcome</c> is stored as the enum's name; the safe
@@ -875,7 +875,7 @@ public class SqliteAuditWriter : IAuditWriter, ISiteAuditQueue, IAsyncDisposable
/// Disposes the audit writer and releases resources.
/// </summary>
/// <remarks>
/// AuditLog-006: prefer <see cref="DisposeAsync"/> when possible (DI honours
/// Prefer <see cref="DisposeAsync"/> when possible (DI honours
/// <see cref="IAsyncDisposable"/> on singletons). The sync path remains for
/// callers that only know about <see cref="IDisposable"/> (e.g. legacy
/// composition roots, <c>using</c> statements without <c>await</c>). To
@@ -938,7 +938,7 @@ public class SqliteAuditWriter : IAuditWriter, ISiteAuditQueue, IAsyncDisposable
_connection.Dispose();
}
// AuditLog-005: dispose the dedicated read connection after the writer
// Dispose the dedicated read connection after the writer
// is fully drained and closed. _readLock is taken to fence out any
// in-flight read caller that grabbed the lock before _disposed flipped
// — they observe ObjectDisposedException on the next attempt.