Skip to content

feat(039): team board settings — export, import, architecture fixes#128

Merged
MrHinsh merged 56 commits into
mainfrom
039-team-board-settings
Jun 18, 2026
Merged

feat(039): team board settings — export, import, architecture fixes#128
MrHinsh merged 56 commits into
mainfrom
039-team-board-settings

Conversation

@MrHinsh

@MrHinsh MrHinsh commented Jun 18, 2026

Copy link
Copy Markdown
Member

Summary

Implements US1 of issue 039: export and import of team board configuration (columns, swimlanes, card rules, backlogs, taskboard columns) as part of the Teams module extension system.

What changed

Core feature (phases 1–11)

  • ITeamBoardAdapter — new port for all board read/write operations; implementations for Azure DevOps, Simulated, and TFS null adapter
  • BoardConfigTeamExtensionIModuleExtension that exports board-config.json per team and imports it back with Replace / Merge / Skip modes
  • ConnectorCapability enum — BoardConfig, Backlogs, TaskboardColumns flags; IConnectorCapabilityProvider port
  • TargetBoardSnapshot — value object batching all target-side reads before any write (FR-013 state-mapping validation, Merge/Skip logic)
  • BoardConfigExportPlan — private record consolidating capability-gate checks in ExportAsync
  • RawWorkItemRevisionData / RawWorkItemRelation — SDK-free records in Abstractions.Agent replacing ADO SDK types in the mapper interface

Architecture fixes (combined review)

  • IEmbeddedImageExportService, IRevisionFolderProcessor moved from Infrastructure.AgentAbstractions.Agent (CA/HX interfaces in wrong layer)
  • PassThroughIdentityMappingService, IdMapStoreFactory moved to Infrastructure.Agent.Identity (VS-H1 cross-slice namespace)
  • ExportImagesFromHtmlAsync, DispatchTasksAsync, ImportRevisionAsync — public method renames to business verbs (SA screaming architecture)
  • IWorkItemExportOrchestrator / IWorkItemExportOrchestratorFactory deleted; dependency inversion corrected

WorkItems module refactor (prerequisite work)

  • Extension stage list made injectable; AppliedComments cursor stage added
  • God-object (WorkItemsModuleExtensions) fields retired: RevisionsEnabled, Comments.Enabled, LinksEnabled, AttachmentsEnabled, EmbeddedImages
  • Links, Attachments, Comments driven through IModuleExtension ports (ADR 0019)
  • WorkItemRevisionLoopDriver renamed from WorkItemsImportRuntime

Bug fixes (this session)

  • Net481GuardedTypesContractTests — namespace updated from WorkItems.Identity to Identity after VS-H1 move
  • SimulatedBoardAdapter.GetBoardConfigSnapshotAsync — was returning TargetBoardSnapshot.Empty; now returns real board state so Skip mode and state-mapping validation work correctly in system tests

Test results (all fresh after last change)

  • Unit tests: 950/950 passed
  • Simulated system tests: 38/38 passed
  • Live system tests: 13/13 passed

Reviewer notes

  • TargetBoardSnapshot.BoardNames uses ISet<string> not IReadOnlySet<string>IReadOnlySet<T> is unavailable on net481
  • AzureDevOpsBoardAdapter.GetBoardConfigSnapshotAsync is a real implementation stub; the live ADO adapter makes the actual REST calls
  • The BoardConfigExtensionOptions.ImportMode default is Replace; Skip and Merge modes tested in both unit and simulated suites

Test plan

  • pwsh ./build.ps1 Test — 950/950 unit tests green
  • pwsh ./build.ps1 SystemTest_Simulated — 38/38 simulated system tests green
  • pwsh ./build.ps1 SystemTest_Live — 13/13 live system tests green
  • No Assert.Inconclusive introduced
  • net481 contract test updated and passing

🤖 Generated with Claude Code

MrHinsh and others added 30 commits June 11, 2026 07:06
…ions

- Introduced tasks for exporting and importing team board configurations.
- Defined phases for setup, foundational work, and user stories for exporting board columns, swimlanes, card rules, backlogs, and taskboard columns.
- Established a test-first approach with detailed test cases for each user story.
- Implemented connector capability mechanism and ensured compatibility with existing systems.
- Added observability metrics and logging for export/import processes.
- Updated the constitution to align testing principles with the canonical taxonomy, introducing dual parent and specific tags for tests.
- Revised the technology stack section to reflect changes in the test framework and taxonomy references.
- Enhanced the BoardSwimLane record to include Id as source-only metadata, aligning with the Azure DevOps API.
- Introduced BacklogLevelType enum to capture backlog level types, reflecting changes in the data model.
- Updated ConnectorCapability enum to include granular capabilities for board configuration, ensuring compliance with functional requirements.
- Modified test approach to enforce tagging of tests with both parent family and specific category tags, ensuring clarity in test classification.
- Added detailed acceptance scenarios and functional requirements for board configuration export/import, ensuring comprehensive coverage.
- Established a documentation sync phase to ensure all discrepancies are resolved before merging the spec branch.
- Introduced a new spec addendum for the WorkItems module refactor, detailing the alignment with the extension model.
- Updated tasks for the 039-team-board-settings to reflect changes in extension contracts and implementation plans.
- Created IExtensionContext and IModuleExtension interfaces to standardize extension behavior across modules.
- Established a clear separation of concerns between core functionality and extensions within the Teams module.
- Documented the implementation plan for converting existing capabilities to the new extension model.
…rator (ADR 0019 Stage 1)

Stage 1 of the WorkItems extension-seam refactor, delivered test-first
(RED -> GREEN -> REFACTOR), full suite green (1064/1064), both TFMs build.

- Move the inventory/capture loop from WorkItemsModule.CaptureAsync into
  WorkItemsOrchestrator.CaptureAsync (IWorkItemsOrchestrator gains CaptureAsync).
  Driven by new WorkItemsOrchestratorInventoryTests.
- Remove the unnecessary IWorkItemsOrchestratorFactory/WorkItemsOrchestratorFactory
  (manual DI); the container now composes the orchestrator graph directly.
- WorkItemsModule is now a thin facade taking only IWorkItemsOrchestrator;
  ctor collapsed ~30 params -> 1, all phases delegate.
- Close a DI-vs-factory duplicate-construction regression (DI now passes the
  inventory deps to the orchestrator).
- Remove dead ApplyImportReplayLevers + unused activity sources (Rule 30).
- Relocate behavioural test construction to WorkItemsModuleTestFactory; remove
  obsolete fat-ctor guard-clause tests and redundant module-inventory tests;
  reframe the module-isolation test to the thin module + orchestrator.
- Add ADR 0019 (accepted) and the WorkItems refactor spec addendum.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Introduces the work-item extension port and the first facet, test-first
(RED -> GREEN), full suite green (1067/1067), both TFMs build.

- WorkItemExtensionContext : IExtensionContext — the per-revision domain port
  context (revision + resolved target id), decoupled from the checkpoint engine.
- LinksExtensionOptions — the extension's own IOptions<T> (no shared god-object).
- LinksWorkItemExtension : IModuleExtension — encapsulates link-application
  (related/external/hyperlinks) as a domain capability; import-only (links are
  captured in revision.json on export). Driven by LinksWorkItemExtensionTests.

Additive only: the checkpoint/resume engine is untouched. Wiring the processor
to drive this port (replacing the inline link stage) is the next increment.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
… inline duplication)

Wires the per-revision import to delegate the AppliedLinks stage to
LinksWorkItemExtension, removing the inline _target.AddLinksAsync call. The
checkpoint/resume logic, cursor markers, and enablement gate are unchanged —
only the link-application call is rerouted through the capability port.

- WorkItemExtensionContext carries the per-job IWorkItemTarget (the port reads
  its driven adapter from the per-entity context; the extension no longer
  ctor-injects a per-job dependency).
- RevisionFolderProcessor: AppliedLinks stage now calls _linksExtension.ImportAsync;
  the extension is an optional ctor dependency defaulting to a new instance
  (same default-dependency pattern already used for AttachmentReplayService).
- RevisionFolderProcessorFactory threads the DI-resolved extension through.
- Register LinksWorkItemExtension + IOptions<LinksExtensionOptions> (IConfigSection,
  AddSchemaEntry) in AddWorkItemsModule.

Full Infrastructure.Agent suite green (1067/1067), both TFMs build. No more
duplicate link-application logic.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…factor addendum

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…port (remove inline duplication)

Extracts the attachment-replay capability into AttachmentsWorkItemExtension
(IModuleExtension, Module=WorkItems, Name=Attachments, Order=400, import-only),
mirroring the already-merged Links facet. The per-revision UploadedAttachments
stage now delegates to the port instead of calling AttachmentReplayService inline.

- AttachmentsExtensionOptions: own IOptions<T> (IConfigSection, AddSchemaEntry),
  Enabled default true.
- WorkItemExtensionContext gains optional IdMapStore, ReadBinaryAsync, and
  AvailableBinaryPaths members so the port can build its per-job replay service
  from the per-entity context (Links is unaffected — additive only).
- RevisionFolderProcessor: UploadedAttachments stage calls
  _attachmentsExtension.ImportAsync; extension is an optional ctor dependency
  defaulting to a new instance (same pattern as the Links extension). The
  checkpoint/resume cursor markers and the AttachmentsEnabled enablement gate
  are unchanged — only the replay call is rerouted.
- RevisionFolderProcessorFactory threads the DI-resolved extension through.
- Register AttachmentsWorkItemExtension + IOptions<AttachmentsExtensionOptions>
  in AddWorkItemsModule.

Test-first: contract assertions + an ImportAsync behavioural test proving the
attachment replays to the resolved target (RED via NotImplementedException, then
GREEN). Full Infrastructure.Agent suite green (1070/1070), both TFMs build.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…remove inline duplication)

Extracts the inline work-item comment replay into CommentsWorkItemExtension
(IModuleExtension, Module=WorkItems, Name=Comments, Order=500, import-only),
mirroring the already-merged Links and Attachments facets. The per-revision
import now delegates to the port instead of calling ProcessInlineCommentsAsync
inline.

- CommentsExtensionOptions: own IOptions<T> (IConfigSection, AddSchemaEntry),
  Enabled default true.
- WorkItemExtensionContext gains an optional ReadTextAsync member so the port can
  read the comment.json sidecar (with the driver's legacy-path fallbacks) without
  owning package-access plumbing (Links/Attachments unaffected — additive only).
- RevisionFolderProcessor: the inline-comments step calls
  _commentsExtension.ImportAsync; the extension is an optional ctor dependency
  defaulting to a new instance (same pattern as Links/Attachments). The
  ext.Comments.Enabled gate is unchanged and Comments still has no cursor stage —
  only the replay call is rerouted. The now-unused ProcessInlineCommentsAsync is
  removed.
- RevisionFolderProcessorFactory threads the DI-resolved extension through.
- Register CommentsWorkItemExtension + IOptions<CommentsExtensionOptions> in
  AddWorkItemsModule.

Test-first: contract assertions + an ImportAsync behavioural test proving
non-deleted comments replay (rendered text preferred) to the resolved target
(RED via NotImplementedException, then GREEN). Full Infrastructure.Agent suite
green (1073/1073), both TFMs build.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…acet completion

Removes the now-unused _attachmentReplayService field/ctor param from
WorkItemResolutionProcessor (Rule 30; attachment replay now lives in the
Attachments port). Updates the 039 addendum: Attachments + Comments facets done,
EmbeddedImages confirmed as the decided field-rewrite contributor (no extraction),
and the remaining work (Stage 5 god-object retirement; Stage 2 deferred).

Full Infrastructure.Agent suite green (1073/1073), both TFMs build.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
A Tool is defined by its single-instance / single run-wide config shape, not by
purity. Tools may perform I/O (e.g. identity/cache lookups) and may hold run-wide
derived state; they must not carry per-consumer/per-call mutable state. Fixes the
execution-contract tool rules + violation list and the terminology/domain-model
primers.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ent into Stage 2

The facet enablement flags are read in multiple places (processor stage gates +
stream-orchestrator skip-visibility) and the processor still maps each extension to
a fixed cursor stage, so retiring the WorkItemsModuleExtensions enablement is
entangled with the Stage 2 cursor generalisation and is folded into that dedicated,
integrity-critical effort. Capabilities already own their logic as ports; only the
enablement source still flows through the god-object gate.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…(Stage 5)

Moves Links/Attachments/Comments enablement off the WorkItemsModuleExtensions
god-object flags onto each extension's own IsEnabled, bound from the same operator
config (Extensions.{Links,Attachments,Comments}.Enabled) for exact parity. The
processor's three stage gates now read _linksExtension/_attachmentsExtension/
_commentsExtension.IsEnabled; the cursor/resume logic and markers are byte-identical.

- Links/Attachments/CommentsExtensionOptions.Enabled made settable; bound via
  Configure<IOptions<WorkItemsModuleOptions>> in AddWorkItemsModule.
- One test (ProcessAsync_WhenLinksDisabled_SkipsStageC) updated to disable Links via
  an injected disabled port instead of the god-object flag.

Full Infrastructure.Agent suite green (1073/1073), both TFMs build. Cursor engine untouched.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…led into Stage 2

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…jj95-wg3x

NuGet audit (NU1903, warning-as-error) was failing the full-solution build on the
transitive MessagePack 2.5.192 (pulled via StreamJsonRpc -> KubernetesClient in the
Aspire AppHost). Enables central package transitive pinning and pins MessagePack to
2.5.301 — the patched release in the same 2.5.x line (binary-compatible, no major bump).

Verified: full solution builds (exit 0) and the entire test suite passes with a real
captured exit code (FULL_TEST_EXIT=0) — 1564 tests, 0 failures across all 10 test
projects incl. net481 TfsMigrationAgent.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Replaced instances of WorkItemsImportRuntime with WorkItemRevisionLoopDriver across multiple test contexts.
- Updated the BuildOrchestrator methods to return WorkItemRevisionLoopDriver instead of WorkItemsImportRuntime.
- Introduced WorkItemRevisionLoopDriver as a test-only driver to facilitate testing without full ImportContext setup.
- Added new tests for ImportResumeDecisionResolver and WorkItemRevisionStagePipeline to ensure correct behavior.
- Removed obsolete WorkItemRevisionImporterTests and adjusted related test utilities to align with the new structure.
- Updated PackageRuntimeBoundaryEnforcementTests to reflect changes in the WorkItemResolution structure.
Move CommentsWorkItemExtension from an ad-hoc inline call into the
ordered extensionStages array so it gets a cursor write and is
subject to resume/skip logic like Links and Attachments.

Adds CursorStage.AppliedComments and registers it in
WorkItemRevisionStagePipeline.StageNames as the fifth pipeline stage
(after UploadedAttachments, before Completed). Updates all
stage-ordering tests that expected UploadedAttachments → Completed.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add an optional `extensionStages` constructor parameter to
`WorkItemResolutionProcessor` so callers can supply a custom ordered
stage list, enabling tests to vary extension presence without touching
individual extension options.

Make `WorkItemRevisionStage` public (was internal) so it can appear as
a parameter type on the public ctor without an accessibility error.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ferred to Stage 5

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…t gating (Stage 3/4)

Add AttachmentsWorkItemExtension and CommentsWorkItemExtension as
optional ctor parameters on WorkItemsOrchestrator. ExportAsync now
reads IsEnabled from these extension objects rather than from the
WorkItemsModuleExtensions god-object, removing two god-object reads
from the export path.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…t gating

Replace ext.AttachmentsEnabled and ext.Comments.Enabled reads in the
import log line with _attachmentsExtension.IsEnabled and
_commentsExtension.IsEnabled. Loop-level ext.Comments.Enabled for
comment-folder gating retained (levered value, different concern from
the per-revision AppliedComments stage).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ge 4/5 prereq)

Replace ext.RevisionsEnabled reads in the import path with
_options.Value.Extensions.Revisions.Enabled. RevisionsEnabled is a
core kill-switch (not extension-owned); reading from options directly
removes the god-object dependency for this flag without behaviour change.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
… (Stage 4/5 prereq)

Replace ext.EmbeddedImages.Enabled god-object read in RevisionFolderProcessor with
an injected EmbeddedImagesExtensionOptionsConfig parameter so the per-revision
embedded-image gate no longer depends on the god-object at all.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…alue

Remove the last non-deferred god-object read from the import startup log.
ext.LinksEnabled → _options.Value.Extensions.Links.Enabled matches the
pattern already used for Revisions, Attachments, and Comments in the same log line.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ate pending list

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The orchestrator's early-return guard and log already read
_options.Value.Extensions.Revisions.Enabled directly. RevisionsEnabled on
WorkItemsModuleExtensions was set in FromModule, FromOptions, and copied in
ApplyReplayLevers but never read — removing it eliminates the last Revisions-
specific field from the god-object.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…elpers

WorkItemsModuleExtensions.FromModule(JobModule) was never called anywhere
in production code or tests; all 8 private helpers served only that method.
Removing them eliminates ~180 lines of dead code and the unused imports
(System.Text.Json, System.Linq, DevOpsMigrationPlatform.Abstractions.Jobs).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace ext.Comments.Enabled read in RunRevisionFolderLoopAsync with
_commentsExtension.IsEnabled, which is the injected CommentsWorkItemExtension.
Since ApplyReplayLevers does not modify Comments, the levered value is
identical to the pre-lever extension value — no behaviour change.

Update WorkItemRevisionLoopDriver and ImportCommentsContext to accept
CommentsWorkItemExtension? so tests can inject a disabled extension
instead of setting the god-object field.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
MrHinsh and others added 25 commits June 15, 2026 15:56
Comments is no longer read from WorkItemsModuleExtensions anywhere in
production code; the loop-level gate migrated to _commentsExtension.IsEnabled
and ApplyReplayLevers no longer copies it. Remove the property, the
FromOptions assignment, and the dead test initialiser in SkipUnresolvableContext.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…tired

Record that FromModule dead code, loop-level commentsEnabled gate, and
Comments god-object property have all been migrated. Only Stage 5 blocked
items (AttachmentsEnabled, LinksEnabled, EmbeddedImages in ApplyReplayLevers
and EmitReplaySkipVisibilityEvents) remain.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ImageReplayService→RewriteTool

`Service` is not a permitted taxonomy role; stateless concern engines use the `Tool` role.
Renamed AttachmentReplayService → AttachmentReplayTool and EmbeddedImageReplayService →
EmbeddedImageRewriteTool ('Rewrite' reflects the field-URL-rewriting concern). Updated all
call sites, extension wiring, and test files. 1100 tests green.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…mExtension into DI factory

The WorkItemsOrchestrator factory lambda was not passing the registered singletons; the ??
fallback always fired, creating default-options instances that ignored config. Now both
extensions are resolved via GetRequiredService so the configured Enabled flag is honoured.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ter from ProcessAsync

IWorkItemResolutionProcessor.ProcessAsync was declared with a WorkItemsModuleExtensions ext
parameter that was never read in the implementation — the processor gates stages via injected
extension objects. Removed the dead parameter from the interface, implementation, and all
17 call sites. Added attachmentsExtension param to RevisionFolderProcessorTests.CreateSut
so the attachments-disabled gate can still be tested via the injected extension. 1100 green.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…olutionProcessor.cs

File name must match class name (WorkItemResolutionProcessor). No code changes.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…1 file rename as done

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…WorkItemExtension (HX-C2)

AttachmentsWorkItemExtension was silently discarding attachment logs by using NullLogger.
Now accepts ILogger<AttachmentReplayTool> via constructor and forwards it to AttachmentReplayTool.
Fallback new() uses NullLogger where DI is not available (test-only code paths).
Updated all test call sites and guarded-path list (RevisionFolderProcessor→WorkItemResolutionProcessor).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…tances

Previously ApplyReplayLevers computed levered booleans but they only
flowed to telemetry; the processor used singleton extension IsEnabled
(config-level) and completely ignored runtime levers.

Now the processor factory Create() overload accepts per-job lever flags
and synthesises disabled extension instances when a lever suppresses an
extension — so stages are actually skipped, not just logged.

The lever test now asserts specific false/false/false values rather than
It.IsAny<bool>(), proving the orchestrator passes computed flags through.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…eads

ApplyReplayLevers now reads _options.Value.Extensions.* directly instead
of ext.AttachmentsEnabled/LinksEnabled/EmbeddedImages.*; the god-object
is no longer the source-of-truth going into the lever computation.

EmitReplaySkipVisibilityEvents signature changed from WorkItemsModuleExtensions
to two bool parameters (attachmentsEnabled, embeddedImagesEnabled).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…mages from god-object

These three extension-owned properties are removed from WorkItemsModuleExtensions.
ComputeLeveredExtensionFlags() replaces ApplyReplayLevers() — reads _options.Value
directly and returns a (bool, bool, bool) tuple. The god-object now carries only
non-extension config: Query, ResolutionStrategy, IncludeFilters, ExcludeFilters.

Tests that previously set AttachmentsEnabled/EmbeddedImages on the extensions object
now configure WorkItemsModuleOptions with the extension disabled instead, which is
the correct seam for controlling extension enablement.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ments extensions

AttachmentsWorkItemExtension and CommentsWorkItemExtension now implement
SupportsExport=true and ExportAsync, moving attachment binary download
and inline comment export out of WorkItemExportOrchestrator inline code.

WorkItemRevisionExportContext (new) carries per-revision export context
(workItemId, revisionIndex, revision, folderPath, sourceEndpoint) for
extensions to consume. WorkItemExportOrchestrator routes to extensions
when exportExtensions is provided, falling back to inline paths for
backward compatibility with tests that don't inject extensions.

DI registration now injects IAttachmentBinarySource? and
IWorkItemCommentSourceFactory? into the extension singletons.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…l items done

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…2 doc fix

- T091/T092: Update execution-model.md to document Teams simplified model (no
  mandatory tier yet; orchestrator does filtering — deliberate, not a deviation)
- T099: Add TeamExtensionParityTests.cs — DomainTests for all four extensions
  (Settings/Iterations/Members/Capacity) proving artifact written to package
- T013: Add ConnectorCapabilityTests.cs — UnitTests for StaticConnectorCapabilityProvider
  (flag included → true, excluded → false, composite BoardConfig → granular flags true,
  None → all false)
- T014: ConnectorCapability [Flags] enum (None/BoardColumns/BoardRows/CardRules/Backlogs/
  TaskboardColumns/BoardConfig composite)
- T015: IConnectorCapabilityProvider interface
- T016: StaticConnectorCapabilityProvider (bitwise Has() test)
- T017: TfsConnectorCapabilityProvider (always returns false — explicit None declaration)
- T017b: TfsNullBoardAdapter (throws NotSupportedException; satisfies DI contract)
- T018: Register TfsConnectorCapabilityProvider + TfsNullBoardAdapter in TFS agent DI
- T019: Register StaticConnectorCapabilityProvider(BoardConfig|Backlogs|Taskboard) in ADO DI
- T020: Register StaticConnectorCapabilityProvider(BoardConfig|Backlogs|Taskboard) in Simulated DI
- T021: All ConnectorCapabilityTests + full suite (723 tests) pass
- Mark T013–T021, T091, T092, T099 complete in tasks.md

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…pter + AzureDevOpsBoardAdapter stub

- T022: BoardConfigTeamExtensionTests.cs — 5 DomainTests covering all US1 acceptance
  scenarios (multi-board, null WIP limit, capability-absent skip, Columns disabled, process defaults)
- T023/T026: BoardConfigTeamExtension.cs — IModuleExtension with ExportAsync; gates on
  ConnectorCapability.BoardConfig; respects Columns/SwimLanes options; writes board-config.json
- T024: SimulatedBoardAdapter.cs — deterministic 2-board adapter (Stories/Epics, 3 columns each)
- T025: AzureDevOpsBoardAdapter.cs — Phase 4 stub (all methods throw NotImplementedException)
- T027: Register BoardConfigTeamExtension + IOptions<BoardConfigExtensionOptions> in AddTeamsModule
- T029: Structured ILogger observability (started/exported/skipped) in ExportAsync
- T031: All 5 US1 tests pass; full suite 1105/1105 green
- T074/T074b/T075: Columns-disabled and process-defaults tests pass
- Also carry forward Phase 1-3 files (TeamExtensionContext, board abstractions, ConnectorCapability,
  Teams extension conversions, WorkItems god-object retirements) merged from 039-team-board-settings

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…tions, ConnectorCapability

Phase 1: IModuleExtension seam for Teams — TeamExtensionContext, all four per-team
capabilities converted to IModuleExtension, boolean-flag dispatch eliminated.
Phase 2: Board-config abstraction types — BoardColumn, BoardSwimLane, CardRule,
BacklogMetadata, TaskboardColumn, BoardConfig, TeamBoardConfig, ITeamBoardAdapter,
BoardConfigExtensionOptions, BoardConfigImportMode.
Phase 3: ConnectorCapability mechanism — [Flags] enum, IConnectorCapabilityProvider,
StaticConnectorCapabilityProvider, TfsConnectorCapabilityProvider (None),
TfsNullBoardAdapter, DI registrations for all three connectors.
WorkItems: Links/Attachments deleted as extensions (fail Extension Seam Ethos);
single PATCH consolidation via ApplyRevisionAsync; CommentsWorkItemExtension sole
valid extension; ADR 0019 and guardrails updated.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ardAdapter, AzureDevOpsBoardAdapter stub

- BoardConfigTeamExtension: IModuleExtension with ExportAsync checking ConnectorCapability.BoardConfig
- SimulatedBoardAdapter: deterministic 2-board, 3-column adapter for tests
- AzureDevOpsBoardAdapter: Phase 4 stub (methods throw NotImplementedException)
- DI: registered in Teams, Simulated, and AzureDevOps connectors
- Tests: 5 DomainTest methods covering US1 acceptance scenarios (T022, T074, T075)
- BoardConfigExtensionOptions.SectionName added

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…liance

- Add SimulatedBoardAdapterExportTests (8 tests) and SimulatedBoardAdapterImportTests (7 tests)
- Add TeamBoardConfigPerformanceTests (SC-001: 10 teams × 2 boards < 5 min)
- Add AzureDevOpsBoardAdapterTests (11 contract tests) in new Infrastructure.AzureDevOps.Tests project
- Add InternalsVisibleTo for AzureDevOps.Tests; add Infrastructure.Agent ref to Simulated.Tests
- Implement BoardConfigExtensionOptions as IConfigSection; register AddSchemaEntry in TeamsServiceCollectionExtensions
- Fix net481 ReadToEndAsync(CancellationToken) guard in BoardConfigTeamExtension
- Add 2 missing tests: US6 scenario 6e (Skip + empty target → Replace) and SC-004 (idempotency)
- Create discrepancies.md (D-001–D-009, all Resolved/N/A)
- Update docs/capabilities-guide.md with Teams Board Configuration capability section
- Update connector-model.md with ConnectorCapability mechanism
- Update execution-model.md with BoardConfigTeamExtension worked example
- Update analysis/pending-actions.md with spec 039 Complete entry
- Mark all Phase 11 tasks complete (T069, T084–T089)
- Fix build.ps1 elapsed format to uniform m:ss.sss across all summary rows

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
… against real TeamsOrchestrator

- Add missing class-level [TestCategory] to 7 test classes (compliance gate)
- Add missing method-level [TestCategory] to TeamExtensionDispatchTests methods
- Rewrite TeamExtensionDispatchTests to exercise TeamsOrchestrator directly
  instead of reimplementing dispatch logic inline; all 4 tests now construct
  a real orchestrator with SpyExtension instances and assert on actual call counts
- Test (c) strengthened: asserts both SupportsImport=true (called) and
  SupportsImport=false (skipped) in the same run

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…cy inversion, screaming architecture

Fix 1 (Critical): Move 5 interfaces to Abstractions.Agent — IProjectLifecycleProvider,
IProjectLifecycleNameGenerator, IWorkItemExportOrchestrator, IWorkItemExportOrchestratorFactory,
IImportCreatedNodeStateStore.

Fix 2 (Critical): Remove direct Infrastructure.Storage.FileSystem reference from
Infrastructure.Agent.csproj; move AddPackageManagementServices/AddPackageMigrationConfigLoader
into PackageServiceCollectionExtensions in the FileSystem project; wire up shell layers
(MigrationAgent, TfsMigrationAgent, TfsObjectModel) with explicit references.

Fix 3 (High): Screaming Architecture renames — ExportImagesFromHtmlAsync,
ExportImagesFromMarkdownAsync, DispatchTasksAsync, ExportAsync, ImportAsync,
ImportRevisionAsync; propagated through implementations and tests.

Fix 4 (High/VS-H1): Move PassThroughIdentityMappingService and IdMapStoreFactory from
WorkItems.Identity cross-slice namespace to Infrastructure.Agent.Identity.

Fix 5 (High): Add GetBoardConfigSnapshotAsync to ITeamBoardAdapter + TargetBoardSnapshot
value object; refactor ImportCoreAsync to batch all target reads upfront; extract
BoardConfigExportPlan private record to consolidate export capability gate checks.

Fix 6 (High): Define RawWorkItemRevisionData + RawWorkItemRelation SDK-free records in
Abstractions.Agent; update IAzureDevOpsWorkItemRevisionMapper.Map to take these instead
of WorkItem; AzureDevOpsWorkItemRevisionSource converts via ToRaw() adapter.

All 1136 tests green.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
PassThroughIdentityMappingService was moved from WorkItems.Identity to
Identity in Fix 4 (VS-H1), but the net481 guarded-types contract test
still referenced the old namespace.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…eal board state

The Skip mode check in BoardConfigTeamExtension calls
snapshot.BoardNames.Contains(board.BoardName). SimulatedBoardAdapter was
returning TargetBoardSnapshot.Empty (empty BoardNames), so Skip mode
never fired and UpdateBoardColumnsAsync was called unconditionally.

Populate BoardNames, BoardColumns, and TaskboardColumns from the
existing simulated seed data so the snapshot reflects the adapter''s
true state.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jun 18, 2026

Copy link
Copy Markdown

Important

Review skipped

Too many files!

This PR contains 221 files, which is 71 over the limit of 150.

To get a review, narrow the scope:
• coderabbit review --type committed # exclude uncommitted changes
• coderabbit review --dir # limit to a subdirectory
• coderabbit review --base # compare against a closer base

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 2bf393a2-e6c7-4941-863c-5484709adc6c

📥 Commits

Reviewing files that changed from the base of the PR and between ddd5e27 and c039ce4.

📒 Files selected for processing (221)
  • .agents/00-entry/task-profiles.yaml
  • .agents/10-contracts/seam-catalog.yaml
  • .agents/10-contracts/specs/execution-contract.md
  • .agents/10-contracts/specs/orchestrator-contract.md
  • .agents/10-contracts/surface-catalog.yaml
  • .agents/20-guardrails/core/capability-ethos-rules.md
  • .agents/20-guardrails/core/taxonomy-naming.md
  • .agents/30-context/architecture/execution-model.md
  • .agents/30-context/domains/capability-seam-contract.md
  • .agents/30-context/domains/connector-model.md
  • .agents/30-context/domains/identity-and-mapping.md
  • .agents/30-context/domains/module-model.md
  • .agents/30-context/domains/orchestrator-model.md
  • .agents/30-context/primers/domain-model.md
  • .agents/30-context/primers/terminology.md
  • .agents/90-index/context-index.md
  • .agents/skills/nkda-archimprove-documentation/DOCUMENTATION-MAP.md
  • .specify/feature.json
  • .specify/memory/constitution.md
  • CLAUDE.md
  • Directory.Packages.props
  • analysis/pending-actions.md
  • analysis/proposed-features.md
  • build.ps1
  • docs/adr/0019-workitems-extension-seam-and-staged-cursor-pipeline.md
  • docs/adr/README.md
  • docs/capabilities-guide.md
  • specs/039-team-board-settings/checklists/requirements.md
  • specs/039-team-board-settings/contracts/BoardConfigTeamExtension.md
  • specs/039-team-board-settings/contracts/IModuleExtension.md
  • specs/039-team-board-settings/contracts/ITeamBoardAdapter.md
  • specs/039-team-board-settings/data-model.md
  • specs/039-team-board-settings/discrepancies.md
  • specs/039-team-board-settings/plan.md
  • specs/039-team-board-settings/quickstart.md
  • specs/039-team-board-settings/research.md
  • specs/039-team-board-settings/spec-addendum-workitems-module-refactor.md
  • specs/039-team-board-settings/spec.md
  • specs/039-team-board-settings/tasks.md
  • src/DevOpsMigrationPlatform.Abstractions.Agent/Attachments/IEmbeddedImageExportService.cs
  • src/DevOpsMigrationPlatform.Abstractions.Agent/Checkpointing/CursorStage.cs
  • src/DevOpsMigrationPlatform.Abstractions.Agent/ConnectorCapability.cs
  • src/DevOpsMigrationPlatform.Abstractions.Agent/Context/IJobPlanExecutor.cs
  • src/DevOpsMigrationPlatform.Abstractions.Agent/DevOpsMigrationPlatform.Abstractions.Agent.csproj
  • src/DevOpsMigrationPlatform.Abstractions.Agent/Export/IRevisionFolderProcessor.cs
  • src/DevOpsMigrationPlatform.Abstractions.Agent/Export/IRevisionFolderProcessorFactory.cs
  • src/DevOpsMigrationPlatform.Abstractions.Agent/Export/IWorkItemExportOrchestrator.cs
  • src/DevOpsMigrationPlatform.Abstractions.Agent/Export/IWorkItemExportOrchestratorFactory.cs
  • src/DevOpsMigrationPlatform.Abstractions.Agent/IConnectorCapabilityProvider.cs
  • src/DevOpsMigrationPlatform.Abstractions.Agent/IExtensionContext.cs
  • src/DevOpsMigrationPlatform.Abstractions.Agent/IModuleExtension.cs
  • src/DevOpsMigrationPlatform.Abstractions.Agent/Modules/IWorkItemsOrchestrator.cs
  • src/DevOpsMigrationPlatform.Abstractions.Agent/Modules/WorkItemsModuleExtensions.cs
  • src/DevOpsMigrationPlatform.Abstractions.Agent/ProjectLifecycle/IProjectLifecycleNameGenerator.cs
  • src/DevOpsMigrationPlatform.Abstractions.Agent/ProjectLifecycle/IProjectLifecycleProvider.cs
  • src/DevOpsMigrationPlatform.Abstractions.Agent/Teams/BacklogLevelType.cs
  • src/DevOpsMigrationPlatform.Abstractions.Agent/Teams/BacklogMetadata.cs
  • src/DevOpsMigrationPlatform.Abstractions.Agent/Teams/BoardColumn.cs
  • src/DevOpsMigrationPlatform.Abstractions.Agent/Teams/BoardColumnStateMapping.cs
  • src/DevOpsMigrationPlatform.Abstractions.Agent/Teams/BoardColumnType.cs
  • src/DevOpsMigrationPlatform.Abstractions.Agent/Teams/BoardConfig.cs
  • src/DevOpsMigrationPlatform.Abstractions.Agent/Teams/BoardConfigExtensionOptions.cs
  • src/DevOpsMigrationPlatform.Abstractions.Agent/Teams/BoardConfigImportMode.cs
  • src/DevOpsMigrationPlatform.Abstractions.Agent/Teams/BoardSwimLane.cs
  • src/DevOpsMigrationPlatform.Abstractions.Agent/Teams/CardRule.cs
  • src/DevOpsMigrationPlatform.Abstractions.Agent/Teams/CardRuleSettings.cs
  • src/DevOpsMigrationPlatform.Abstractions.Agent/Teams/ITeamBoardAdapter.cs
  • src/DevOpsMigrationPlatform.Abstractions.Agent/Teams/TargetBoardSnapshot.cs
  • src/DevOpsMigrationPlatform.Abstractions.Agent/Teams/TaskboardColumn.cs
  • src/DevOpsMigrationPlatform.Abstractions.Agent/Teams/TeamAreaPathsExtensionOptions.cs
  • src/DevOpsMigrationPlatform.Abstractions.Agent/Teams/TeamBoardConfig.cs
  • src/DevOpsMigrationPlatform.Abstractions.Agent/Teams/TeamCapacityExtensionOptions.cs
  • src/DevOpsMigrationPlatform.Abstractions.Agent/Teams/TeamExtensionContext.cs
  • src/DevOpsMigrationPlatform.Abstractions.Agent/Teams/TeamIterationsExtensionOptions.cs
  • src/DevOpsMigrationPlatform.Abstractions.Agent/Teams/TeamMembersExtensionOptions.cs
  • src/DevOpsMigrationPlatform.Abstractions.Agent/Teams/TeamSettingsExtensionOptions.cs
  • src/DevOpsMigrationPlatform.Abstractions.Agent/Telemetry/IPlatformMetrics.cs
  • src/DevOpsMigrationPlatform.Abstractions.Agent/WorkItems/AttachmentUploadResult.cs
  • src/DevOpsMigrationPlatform.Abstractions.Agent/WorkItems/CommentsExtensionOptions.cs
  • src/DevOpsMigrationPlatform.Abstractions.Agent/WorkItems/IImportCreatedNodeStateStore.cs
  • src/DevOpsMigrationPlatform.Abstractions.Agent/WorkItems/IWorkItemTarget.cs
  • src/DevOpsMigrationPlatform.Abstractions.Agent/WorkItems/Revisions/RawWorkItemRevisionData.cs
  • src/DevOpsMigrationPlatform.Abstractions.Agent/WorkItems/WorkItemExtensionContext.cs
  • src/DevOpsMigrationPlatform.Abstractions/Options/WorkItemsExtensionsOptions.cs
  • src/DevOpsMigrationPlatform.Abstractions/Telemetry/WellKnownAgentMetricNames.cs
  • src/DevOpsMigrationPlatform.Infrastructure.Agent/AssemblyInfo.cs
  • src/DevOpsMigrationPlatform.Infrastructure.Agent/ConnectorCapability/StaticConnectorCapabilityProvider.cs
  • src/DevOpsMigrationPlatform.Infrastructure.Agent/Context/JobExecutionPlanBuilder.cs
  • src/DevOpsMigrationPlatform.Infrastructure.Agent/Context/JobPlanExecutor.cs
  • src/DevOpsMigrationPlatform.Infrastructure.Agent/CoreAgentServiceExtensions.cs
  • src/DevOpsMigrationPlatform.Infrastructure.Agent/DevOpsMigrationPlatform.Infrastructure.Agent.csproj
  • src/DevOpsMigrationPlatform.Infrastructure.Agent/Export/EmbeddedImageExportService.cs
  • src/DevOpsMigrationPlatform.Infrastructure.Agent/Export/WorkItemExportOrchestrator.cs
  • src/DevOpsMigrationPlatform.Infrastructure.Agent/Export/WorkItemExportOrchestratorFactory.cs
  • src/DevOpsMigrationPlatform.Infrastructure.Agent/Identity/IdMapStoreFactory.cs
  • src/DevOpsMigrationPlatform.Infrastructure.Agent/Identity/IdentityServiceCollectionExtensions.cs
  • src/DevOpsMigrationPlatform.Infrastructure.Agent/Identity/PassThroughIdentityMappingService.cs
  • src/DevOpsMigrationPlatform.Infrastructure.Agent/Modules/ModuleServiceCollectionExtensions.cs
  • src/DevOpsMigrationPlatform.Infrastructure.Agent/Modules/TeamsOrchestrator.cs
  • src/DevOpsMigrationPlatform.Infrastructure.Agent/Modules/WorkItemsModule.cs
  • src/DevOpsMigrationPlatform.Infrastructure.Agent/PackageConfigServiceCollectionExtensions.cs
  • src/DevOpsMigrationPlatform.Infrastructure.Agent/ProjectLifecycle/ProjectLifecycleNameGenerator.cs
  • src/DevOpsMigrationPlatform.Infrastructure.Agent/ProjectLifecycle/ProjectLifecycleService.cs
  • src/DevOpsMigrationPlatform.Infrastructure.Agent/Teams/Extensions/BoardConfigTeamExtension.cs
  • src/DevOpsMigrationPlatform.Infrastructure.Agent/Teams/Extensions/TeamAreaPathsTeamExtension.cs
  • src/DevOpsMigrationPlatform.Infrastructure.Agent/Teams/Extensions/TeamCapacityTeamExtension.cs
  • src/DevOpsMigrationPlatform.Infrastructure.Agent/Teams/Extensions/TeamIterationsTeamExtension.cs
  • src/DevOpsMigrationPlatform.Infrastructure.Agent/Teams/Extensions/TeamMembersTeamExtension.cs
  • src/DevOpsMigrationPlatform.Infrastructure.Agent/Teams/Extensions/TeamSettingsTeamExtension.cs
  • src/DevOpsMigrationPlatform.Infrastructure.Agent/Teams/TeamArtifactAddress.cs
  • src/DevOpsMigrationPlatform.Infrastructure.Agent/Teams/TeamExportOrchestrator.cs
  • src/DevOpsMigrationPlatform.Infrastructure.Agent/Teams/TeamImportOrchestrator.cs
  • src/DevOpsMigrationPlatform.Infrastructure.Agent/Teams/TeamsServiceCollectionExtensions.cs
  • src/DevOpsMigrationPlatform.Infrastructure.Agent/Telemetry/PlatformMetrics.cs
  • src/DevOpsMigrationPlatform.Infrastructure.Agent/WorkItems/Attachments/AttachmentReplayTool.cs
  • src/DevOpsMigrationPlatform.Infrastructure.Agent/WorkItems/Attachments/EmbeddedImageRewriteTool.cs
  • src/DevOpsMigrationPlatform.Infrastructure.Agent/WorkItems/Attachments/ImportFailures/MissingAttachmentBinaryImportFailurePattern.cs
  • src/DevOpsMigrationPlatform.Infrastructure.Agent/WorkItems/Extensions/CommentsWorkItemExtension.cs
  • src/DevOpsMigrationPlatform.Infrastructure.Agent/WorkItems/Extensions/WorkItemRevisionExportContext.cs
  • src/DevOpsMigrationPlatform.Infrastructure.Agent/WorkItems/Revisions/RevisionFolderProcessorFactory.cs
  • src/DevOpsMigrationPlatform.Infrastructure.Agent/WorkItems/Revisions/WorkItemResolutionProcessor.cs
  • src/DevOpsMigrationPlatform.Infrastructure.Agent/WorkItems/Revisions/WorkItemRevisionImporter.cs
  • src/DevOpsMigrationPlatform.Infrastructure.Agent/WorkItems/Revisions/WorkItemRevisionStage.cs
  • src/DevOpsMigrationPlatform.Infrastructure.Agent/WorkItems/Revisions/WorkItemRevisionStagePipeline.cs
  • src/DevOpsMigrationPlatform.Infrastructure.Agent/WorkItems/Revisions/WorkItemStreamOrchestrator.cs
  • src/DevOpsMigrationPlatform.Infrastructure.Agent/WorkItems/WorkItemResolution/IWorkItemsOrchestratorFactory.cs
  • src/DevOpsMigrationPlatform.Infrastructure.Agent/WorkItems/WorkItemResolution/ImportResumeDecisionResolver.cs
  • src/DevOpsMigrationPlatform.Infrastructure.Agent/WorkItems/WorkItemResolution/ImportWorkItemStateStore.cs
  • src/DevOpsMigrationPlatform.Infrastructure.Agent/WorkItems/WorkItemResolution/WorkItemRevisionJobScope.cs
  • src/DevOpsMigrationPlatform.Infrastructure.Agent/WorkItems/WorkItemResolution/WorkItemsImportRuntime.cs
  • src/DevOpsMigrationPlatform.Infrastructure.Agent/WorkItems/WorkItemResolution/WorkItemsOrchestrator.cs
  • src/DevOpsMigrationPlatform.Infrastructure.Agent/WorkItems/WorkItemResolution/WorkItemsOrchestratorFactory.cs
  • src/DevOpsMigrationPlatform.Infrastructure.AzureDevOps/DevOpsMigrationPlatform.Infrastructure.AzureDevOps.csproj
  • src/DevOpsMigrationPlatform.Infrastructure.AzureDevOps/ProjectLifecycle/AzureDevOpsProjectLifecycleProvider.cs
  • src/DevOpsMigrationPlatform.Infrastructure.AzureDevOps/Teams/AzureDevOpsBoardAdapter.cs
  • src/DevOpsMigrationPlatform.Infrastructure.AzureDevOps/WorkItems/Revisions/AzureDevOpsWorkItemRevisionMapper.cs
  • src/DevOpsMigrationPlatform.Infrastructure.AzureDevOps/WorkItems/Revisions/AzureDevOpsWorkItemRevisionSource.cs
  • src/DevOpsMigrationPlatform.Infrastructure.AzureDevOps/WorkItems/Revisions/ExportServiceCollectionExtensions.cs
  • src/DevOpsMigrationPlatform.Infrastructure.AzureDevOps/WorkItems/WorkItemResolution/AzureDevOpsWorkItemTarget.cs
  • src/DevOpsMigrationPlatform.Infrastructure.AzureDevOps/WorkItems/WorkItemResolution/ImportServiceCollectionExtensions.cs
  • src/DevOpsMigrationPlatform.Infrastructure.Simulated/Import/SimulatedWorkItemTarget.cs
  • src/DevOpsMigrationPlatform.Infrastructure.Simulated/ProjectLifecycle/SimulatedProjectLifecycleProvider.cs
  • src/DevOpsMigrationPlatform.Infrastructure.Simulated/SimulatedServiceCollectionExtensions.cs
  • src/DevOpsMigrationPlatform.Infrastructure.Simulated/Teams/SimulatedBoardAdapter.cs
  • src/DevOpsMigrationPlatform.Infrastructure.Storage.FileSystem/PackageServiceCollectionExtensions.cs
  • src/DevOpsMigrationPlatform.Infrastructure.TfsObjectModel/DevOpsMigrationPlatform.Infrastructure.TfsObjectModel.csproj
  • src/DevOpsMigrationPlatform.Infrastructure.TfsObjectModel/JobLifecycle/TfsExecution/TfsJobServiceFactory.cs
  • src/DevOpsMigrationPlatform.Infrastructure.TfsObjectModel/ProjectLifecycle/TfsProjectLifecycleProvider.cs
  • src/DevOpsMigrationPlatform.Infrastructure.TfsObjectModel/Teams/TfsConnectorCapabilityProvider.cs
  • src/DevOpsMigrationPlatform.Infrastructure.TfsObjectModel/Teams/TfsNullBoardAdapter.cs
  • src/DevOpsMigrationPlatform.Infrastructure.TfsObjectModel/WorkItems/WorkItemResolution/TfsWorkItemTarget.cs
  • src/DevOpsMigrationPlatform.MigrationAgent/DevOpsMigrationPlatform.MigrationAgent.csproj
  • src/DevOpsMigrationPlatform.MigrationAgent/JobAgentWorker.cs
  • src/DevOpsMigrationPlatform.MigrationAgent/MigrationAgentServiceExtensions.cs
  • src/DevOpsMigrationPlatform.TfsMigrationAgent/DevOpsMigrationPlatform.TfsMigrationAgent.csproj
  • src/DevOpsMigrationPlatform.TfsMigrationAgent/TfsJobAgentWorker.cs
  • src/DevOpsMigrationPlatform.TfsMigrationAgent/TfsMigrationAgentServiceExtensions.cs
  • tests/DevOpsMigrationPlatform.Infrastructure.Agent.Tests/Context/JobAgentWorkerDispatchTests.cs
  • tests/DevOpsMigrationPlatform.Infrastructure.Agent.Tests/Context/JobPlanExecutorTests.cs
  • tests/DevOpsMigrationPlatform.Infrastructure.Agent.Tests/DevOpsMigrationPlatform.Infrastructure.Agent.Tests.csproj
  • tests/DevOpsMigrationPlatform.Infrastructure.Agent.Tests/Export/EmbeddedImageExportServiceTests.cs
  • tests/DevOpsMigrationPlatform.Infrastructure.Agent.Tests/Export/WorkItemExportOrchestratorTests.cs
  • tests/DevOpsMigrationPlatform.Infrastructure.Agent.Tests/Import/AttachmentReplayToolTests.cs
  • tests/DevOpsMigrationPlatform.Infrastructure.Agent.Tests/Import/AzureDevOpsWorkItemTargetTests.cs
  • tests/DevOpsMigrationPlatform.Infrastructure.Agent.Tests/Import/EmbeddedImageRewriteToolTests.cs
  • tests/DevOpsMigrationPlatform.Infrastructure.Agent.Tests/Import/FilterScopeImportContext.cs
  • tests/DevOpsMigrationPlatform.Infrastructure.Agent.Tests/Import/FilterScopeImportTests.cs
  • tests/DevOpsMigrationPlatform.Infrastructure.Agent.Tests/Import/IdMapStoreFactoryTests.cs
  • tests/DevOpsMigrationPlatform.Infrastructure.Agent.Tests/Import/ImportCommentsContext.cs
  • tests/DevOpsMigrationPlatform.Infrastructure.Agent.Tests/Import/ImportCommentsTests.cs
  • tests/DevOpsMigrationPlatform.Infrastructure.Agent.Tests/Import/ImportCursorResumeContext.cs
  • tests/DevOpsMigrationPlatform.Infrastructure.Agent.Tests/Import/ImportCursorResumeDslTests.cs
  • tests/DevOpsMigrationPlatform.Infrastructure.Agent.Tests/Import/ImportEmbeddedImagesContext.cs
  • tests/DevOpsMigrationPlatform.Infrastructure.Agent.Tests/Import/ImportEmbeddedImagesTests.cs
  • tests/DevOpsMigrationPlatform.Infrastructure.Agent.Tests/Import/ImportIdentityResolutionContext.cs
  • tests/DevOpsMigrationPlatform.Infrastructure.Agent.Tests/Import/ImportResumeDecisionResolverTests.cs
  • tests/DevOpsMigrationPlatform.Infrastructure.Agent.Tests/Import/ImportWorkItemStateStoreTests.cs
  • tests/DevOpsMigrationPlatform.Infrastructure.Agent.Tests/Import/PreventDuplicateWorkItemsContext.cs
  • tests/DevOpsMigrationPlatform.Infrastructure.Agent.Tests/Import/PreventDuplicateWorkItemsTests.cs
  • tests/DevOpsMigrationPlatform.Infrastructure.Agent.Tests/Import/RebuildIdMapFromTargetContext.cs
  • tests/DevOpsMigrationPlatform.Infrastructure.Agent.Tests/Import/RerunDeltaImportContext.cs
  • tests/DevOpsMigrationPlatform.Infrastructure.Agent.Tests/Import/RerunDeltaImportTests.cs
  • tests/DevOpsMigrationPlatform.Infrastructure.Agent.Tests/Import/RevisionFolderProcessorFactoryTests.cs
  • tests/DevOpsMigrationPlatform.Infrastructure.Agent.Tests/Import/RevisionFolderProcessorTests.cs
  • tests/DevOpsMigrationPlatform.Infrastructure.Agent.Tests/Import/RevisionLevelProgressTrackingContext.cs
  • tests/DevOpsMigrationPlatform.Infrastructure.Agent.Tests/Import/RevisionLevelProgressTrackingTests.cs
  • tests/DevOpsMigrationPlatform.Infrastructure.Agent.Tests/Import/SimulatedImportTests.cs
  • tests/DevOpsMigrationPlatform.Infrastructure.Agent.Tests/Import/StreamingImportReplayContext.cs
  • tests/DevOpsMigrationPlatform.Infrastructure.Agent.Tests/Import/StreamingImportReplayTests.cs
  • tests/DevOpsMigrationPlatform.Infrastructure.Agent.Tests/Import/WorkItemOrchestratorFilterTests.cs
  • tests/DevOpsMigrationPlatform.Infrastructure.Agent.Tests/Import/WorkItemResolutionStrategiesContext.cs
  • tests/DevOpsMigrationPlatform.Infrastructure.Agent.Tests/Import/WorkItemResolutionStrategiesTests.cs
  • tests/DevOpsMigrationPlatform.Infrastructure.Agent.Tests/Import/WorkItemRevisionImporterTests.cs
  • tests/DevOpsMigrationPlatform.Infrastructure.Agent.Tests/Import/WorkItemRevisionStagePipelineTests.cs
  • tests/DevOpsMigrationPlatform.Infrastructure.Agent.Tests/Modules/InventoryModules/InventoryModuleFactory.cs
  • tests/DevOpsMigrationPlatform.Infrastructure.Agent.Tests/Modules/ModuleIsolationTests.cs
  • tests/DevOpsMigrationPlatform.Infrastructure.Agent.Tests/Modules/TeamExportCapacityTests.cs
  • tests/DevOpsMigrationPlatform.Infrastructure.Agent.Tests/Modules/TeamsModuleTests.cs
  • tests/DevOpsMigrationPlatform.Infrastructure.Agent.Tests/Modules/WorkItemsModuleImportTests.cs
  • tests/DevOpsMigrationPlatform.Infrastructure.Agent.Tests/Modules/WorkItemsModulePrepareTests.cs
  • tests/DevOpsMigrationPlatform.Infrastructure.Agent.Tests/Modules/WorkItemsOrchestratorExportTests.cs
  • tests/DevOpsMigrationPlatform.Infrastructure.Agent.Tests/Modules/WorkItemsOrchestratorInventoryTests.cs
  • tests/DevOpsMigrationPlatform.Infrastructure.Agent.Tests/Prepare/PrepareFeaturesDslTests.cs
  • tests/DevOpsMigrationPlatform.Infrastructure.Agent.Tests/Services/ServicesFeaturesDslTests.cs
  • tests/DevOpsMigrationPlatform.Infrastructure.Agent.Tests/Storage/Package/PackageRuntimeBoundaryEnforcementTests.cs
  • tests/DevOpsMigrationPlatform.Infrastructure.Agent.Tests/Teams/BoardConfigTeamExtensionTests.cs
  • tests/DevOpsMigrationPlatform.Infrastructure.Agent.Tests/Teams/ConnectorCapabilityTests.cs
  • tests/DevOpsMigrationPlatform.Infrastructure.Agent.Tests/Teams/TeamExtensionDispatchTests.cs
  • tests/DevOpsMigrationPlatform.Infrastructure.Agent.Tests/Teams/TeamExtensionParityTests.cs
  • tests/DevOpsMigrationPlatform.Infrastructure.Agent.Tests/TestUtilities/WorkItemRevisionLoopDriver.cs
  • tests/DevOpsMigrationPlatform.Infrastructure.Agent.Tests/TestUtilities/WorkItemsModuleTestFactory.cs
  • tests/DevOpsMigrationPlatform.Infrastructure.Agent.Tests/Tools/NodeTranslation/SkipUnresolvableContext.cs
  • tests/DevOpsMigrationPlatform.Infrastructure.Agent.Tests/WorkItems/Extensions/CommentsWorkItemExtensionTests.cs
  • tests/DevOpsMigrationPlatform.Infrastructure.AzureDevOps.Tests/DevOpsMigrationPlatform.Infrastructure.AzureDevOps.Tests.csproj
  • tests/DevOpsMigrationPlatform.Infrastructure.AzureDevOps.Tests/Teams/AzureDevOpsBoardAdapterTests.cs
  • tests/DevOpsMigrationPlatform.Infrastructure.Simulated.Tests/DevOpsMigrationPlatform.Infrastructure.Simulated.Tests.csproj
  • tests/DevOpsMigrationPlatform.Infrastructure.Simulated.Tests/Teams/SimulatedBoardAdapterExportTests.cs
  • tests/DevOpsMigrationPlatform.Infrastructure.Simulated.Tests/Teams/SimulatedBoardAdapterImportTests.cs
  • tests/DevOpsMigrationPlatform.Infrastructure.Simulated.Tests/Teams/TeamBoardConfigPerformanceTests.cs
  • tests/DevOpsMigrationPlatform.Infrastructure.Tests/Platform/MigrationPlatformOptionsDeserializationTests.cs
  • tests/DevOpsMigrationPlatform.TfsMigrationAgent.Tests/Net481GuardedTypesContractTests.cs

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch 039-team-board-settings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@MrHinsh MrHinsh enabled auto-merge (squash) June 18, 2026 07:09

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c039ce4340

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +257 to +260
var contentCtx = new PackageContentContext(
PackageContentKind.Artefact,
Organisation: ctx.Organisation,
Project: ctx.ProjectName,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Read board-config artifacts from the source project

When importing between differently named source and target projects, ctx.ProjectName is the target project (set by TeamsOrchestrator before dispatch), but the exported board-config.json lives under the source project scope. This lookup therefore misses the artifact and the board-config import silently skips even though the package contains it; use ctx.SourceProjectName for package reads while keeping ctx.ProjectName for target API writes.

Useful? React with 👍 / 👎.

string project, string teamId, CancellationToken ct)
{
ISet<string> boardNames = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
await foreach (var b in GetBoardsAsync(project, teamId, ct).ConfigureAwait(false))

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Enumerate target boards from the target endpoint

In Azure DevOps imports, this snapshot is used to decide whether Skip should leave an existing board alone and whether Merge should preserve target-only columns/lanes, but GetBoardsAsync is the export-side reader and constructs its client from _source. With a target team ID this reads the wrong organization/project (often yielding no boards), so Skip/Merge planning can overwrite target configuration instead of preserving it; the snapshot needs a target-side board enumeration.

Useful? React with 👍 / 👎.

Comment on lines +343 to +345
if (_options.CardRules && teamBoardConfig.CardRules is not null)
await _adapter.UpdateCardRuleSettingsAsync(
ctx.ProjectName, targetId, board.BoardName, teamBoardConfig.CardRules, ct).ConfigureAwait(false);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve card rules per board

When a team has multiple boards with different card rules, this loop applies the single teamBoardConfig.CardRules value to every board. Since export already flattens all per-board rules into that one property, importing a package where only one board had a rule will duplicate that rule onto the other boards and cannot restore distinct rule sets; card rules need to remain keyed by board name through export and import.

Useful? React with 👍 / 👎.

@MrHinsh MrHinsh merged commit 1282690 into main Jun 18, 2026
5 checks passed
@MrHinsh MrHinsh deleted the 039-team-board-settings branch June 18, 2026 07:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant