diff --git a/.planning/REQUIREMENTS.md b/.planning/REQUIREMENTS.md index b3b8ddd..a4bb6b0 100644 --- a/.planning/REQUIREMENTS.md +++ b/.planning/REQUIREMENTS.md @@ -55,14 +55,14 @@ Requirements for initial release. Each maps to roadmap phases. ### Site Templates -- [ ] **TMPL-01**: User can capture site structure (libraries, folders, permission groups, logo, settings) as a template -- [ ] **TMPL-02**: User can apply template to create new Communication or Teams site +- [x] **TMPL-01**: User can capture site structure (libraries, folders, permission groups, logo, settings) as a template +- [x] **TMPL-02**: User can apply template to create new Communication or Teams site - [x] **TMPL-03**: Templates persist locally as JSON - [x] **TMPL-04**: User can manage templates (create, rename, delete) ### Folder Structure -- [ ] **FOLD-01**: User can create folder structures on a site from a CSV template +- [x] **FOLD-01**: User can create folder structures on a site from a CSV template - [x] **FOLD-02**: Example CSV templates provided for common structures ### Bulk Operations @@ -146,11 +146,11 @@ Which phases cover which requirements. Updated during roadmap creation. | DUPL-01 | Phase 3 | Complete | | DUPL-02 | Phase 3 | Complete | | DUPL-03 | Phase 3 | Complete | -| TMPL-01 | Phase 4 | Pending | -| TMPL-02 | Phase 4 | Pending | +| TMPL-01 | Phase 4 | Complete | +| TMPL-02 | Phase 4 | Complete | | TMPL-03 | Phase 4 | Complete | | TMPL-04 | Phase 4 | Complete | -| FOLD-01 | Phase 4 | Pending | +| FOLD-01 | Phase 4 | Complete | | FOLD-02 | Phase 4 | Complete | | BULK-01 | Phase 4 | Complete | | BULK-02 | Phase 4 | Complete | diff --git a/.planning/ROADMAP.md b/.planning/ROADMAP.md index 258c6e8..8525a8f 100644 --- a/.planning/ROADMAP.md +++ b/.planning/ROADMAP.md @@ -138,5 +138,5 @@ Phases execute in numeric order: 1 → 2 → 3 → 4 → 5 | 1. Foundation | 8/8 | Complete | 2026-04-02 | | 2. Permissions | 7/7 | Complete | 2026-04-02 | | 3. Storage and File Operations | 8/8 | Complete | 2026-04-02 | -| 4. Bulk Operations and Provisioning | 5/10 | In Progress| | +| 4. Bulk Operations and Provisioning | 6/10 | In Progress| | | 5. Distribution and Hardening | 0/? | Not started | - | diff --git a/.planning/STATE.md b/.planning/STATE.md index e307542..e6bd718 100644 --- a/.planning/STATE.md +++ b/.planning/STATE.md @@ -2,16 +2,16 @@ gsd_state_version: 1.0 milestone: v1.0 milestone_name: milestone -status: planning -stopped_at: Completed 04-bulk-operations-and-provisioning-04-04-PLAN.md -last_updated: "2026-04-03T08:10:00.000Z" +status: executing +stopped_at: Completed 04-bulk-operations-and-provisioning-04-06-PLAN.md +last_updated: "2026-04-03T08:09:18.086Z" last_activity: 2026-04-03 — Plan 04-04 complete — BulkMemberService with Graph API and CSOM fallback progress: total_phases: 5 completed_phases: 3 total_plans: 33 completed_plans: 29 - percent: 88 + percent: 65 --- # Project State @@ -88,6 +88,7 @@ Progress: [██████░░░░] 65% | Phase 04-bulk-operations-and-provisioning P03 | 7min | 2 tasks | 2 files | | Phase 04-bulk-operations-and-provisioning P02 | 25 | 2 tasks | 4 files | | Phase 04-bulk-operations-and-provisioning P04 | 7min | 2 tasks | 3 files | +| Phase 04-bulk-operations-and-provisioning P06 | 10min | 2 tasks | 4 files | ## Accumulated Context @@ -165,6 +166,9 @@ Recent decisions affecting current work: - [Phase 04-bulk-operations-and-provisioning 04-04]: GraphClientFactory uses GetOrCreateAsync (async) — MsalClientFactory only exposes async method with SemaphoreSlim locking; plan had incorrect sync reference GetOrCreateClient - [Phase 04-bulk-operations-and-provisioning 04-04]: AuthGraphClientFactory alias resolves CS0104 — Microsoft.Graph.GraphClientFactory conflicts with SharepointToolbox.Infrastructure.Auth.GraphClientFactory when both namespaces imported - [Phase 04-bulk-operations-and-provisioning 04-04]: Microsoft.SharePoint.Client.Group? fully qualified in AddToClassicGroupAsync — Microsoft.Graph.Models.Group also in scope in BulkMemberService; explicit namespace resolves ambiguity +- [Phase 04-bulk-operations-and-provisioning]: TemplateService uses ModelSiteTemplate alias — consistent with ITemplateService; CSOM SiteTemplate and Core.Models.SiteTemplate are both in scope +- [Phase 04-bulk-operations-and-provisioning]: FolderStructureService.BuildUniquePaths sorts by slash count for parent-first ordering — ensures intermediate folders exist before children when using Folders.Add +- [Phase 04-bulk-operations-and-provisioning]: TemplateService.ApplyTemplateAsync creates new ClientContext for new site URL — adminCtx.Url points to admin site, new site needs separate context ### Pending Todos @@ -177,6 +181,6 @@ None yet. ## Session Continuity -Last session: 2026-04-03T08:10:00.000Z -Stopped at: Completed 04-bulk-operations-and-provisioning-04-04-PLAN.md +Last session: 2026-04-03T08:09:18.084Z +Stopped at: Completed 04-bulk-operations-and-provisioning-04-06-PLAN.md Resume file: None diff --git a/.planning/phases/04-bulk-operations-and-provisioning/04-06-SUMMARY.md b/.planning/phases/04-bulk-operations-and-provisioning/04-06-SUMMARY.md new file mode 100644 index 0000000..b9f410e --- /dev/null +++ b/.planning/phases/04-bulk-operations-and-provisioning/04-06-SUMMARY.md @@ -0,0 +1,126 @@ +--- +phase: 04-bulk-operations-and-provisioning +plan: 06 +subsystem: bulk-operations +tags: [csom, pnp-framework, template, folder-structure, sharepoint, dotnet] + +# Dependency graph +requires: + - phase: 04-bulk-operations-and-provisioning + plan: 01 + provides: "SiteTemplate, SiteTemplateOptions, TemplateLibraryInfo, TemplateFolderInfo, TemplatePermissionGroup, FolderStructureRow models and ITemplateService, IFolderStructureService interfaces" +provides: + - "TemplateService: CSOM site template capture (libraries, folders, permission groups, logo, settings) and apply via PnP Framework site creation" + - "FolderStructureService: folder hierarchy creation from CSV rows with parent-first ordering via BulkOperationRunner" + - "FolderStructureServiceTests: 4 unit tests (BuildUniquePaths logic) + 1 live-skip" + - "TemplateServiceTests: 3 unit tests (interface impl, model defaults) + 2 live-skip" +affects: [04-07, 04-08, 04-09, 04-10] + +# Tech tracking +tech-stack: + added: [] + patterns: + - "TemplateService.CaptureTemplateAsync — reads Web properties, filters hidden+system lists, enumerates folders recursively, captures SiteGroups with role assignments" + - "TemplateService.ApplyTemplateAsync — creates Team or Communication site via PnP Framework CreateSiteAsync, then recreates libraries/folders/groups via CSOM" + - "FolderStructureService.BuildUniquePaths — deduplicates and sorts CSV-derived folder paths parent-first by counting '/' separators" + - "System list filter via HashSet — normalized comparison against known system list names (Style Library, Form Templates, etc.)" + - "ModelSiteTemplate alias — resolves CSOM SiteTemplate vs Core.Models.SiteTemplate ambiguity" + +key-files: + created: + - "SharepointToolbox/Services/TemplateService.cs" + - "SharepointToolbox/Services/FolderStructureService.cs" + - "SharepointToolbox.Tests/Services/FolderStructureServiceTests.cs" + - "SharepointToolbox.Tests/Services/TemplateServiceTests.cs" + modified: [] + +key-decisions: + - "TemplateService uses ModelSiteTemplate alias — same pattern as ITemplateService; CSOM SiteTemplate and Core.Models.SiteTemplate are both in scope" + - "FolderStructureService.BuildUniquePaths sorts by slash count for parent-first ordering — ensures intermediate folders exist before children when using Folders.Add" + - "System list filter uses HashSet with OrdinalIgnoreCase — fast O(1) lookup, handles case differences in SharePoint list names" + - "TemplateService.ApplyTemplateAsync creates new ClientContext for new site URL — adminCtx.Url points to admin site, new site needs separate context" + +patterns-established: + - "BuildUniquePaths internal static — enables direct unit testing without ClientContext mock" + - "Parent-first folder ordering via depth sort — critical for Folders.Add which does not create intermediates automatically" + +requirements-completed: [TMPL-01, TMPL-02, FOLD-01] + +# Metrics +duration: 10min +completed: 2026-04-03 +--- + +# Phase 04 Plan 06: TemplateService + FolderStructureService Implementation Summary + +**CSOM site template capture/apply (libraries, folders, permission groups, logo) and CSV-driven folder hierarchy creation with parent-first BulkOperationRunner integration** + +## Performance + +- **Duration:** 10 min +- **Started:** 2026-04-03T09:57:13Z +- **Completed:** 2026-04-03T10:07:13Z +- **Tasks:** 2 +- **Files modified:** 4 + +## Accomplishments +- Implemented TemplateService with CaptureTemplateAsync (reads site structure via CSOM) and ApplyTemplateAsync (creates site via PnP Framework, recreates structure via CSOM) +- Implemented FolderStructureService with BuildUniquePaths (parent-first deduplication) and CreateFoldersAsync using BulkOperationRunner +- Created unit tests: 4 FolderStructureService tests (all pass) + 3 TemplateService tests (all pass), 3 live-SharePoint tests marked Skip + +## Task Commits + +Each task was committed atomically: + +1. **Task 1: Implement TemplateService** — already committed prior to this plan execution (verified via `git log`) +2. **Task 2: FolderStructureService + tests** - `84cd569` (feat) + +**Plan metadata:** (added in final commit) + +## Files Created/Modified +- `SharepointToolbox/Services/TemplateService.cs` — Site template capture (reads Web, lists, folders, groups) and apply (PnP Framework site creation + CSOM structure recreation) +- `SharepointToolbox/Services/FolderStructureService.cs` — CSV row to folder hierarchy via BuildUniquePaths + BulkOperationRunner.RunAsync +- `SharepointToolbox.Tests/Services/FolderStructureServiceTests.cs` — 4 unit tests: interface impl, parent-first ordering, deduplication, empty levels +- `SharepointToolbox.Tests/Services/TemplateServiceTests.cs` — 3 unit tests: interface impl, SiteTemplate defaults, SiteTemplateOptions defaults + +## Decisions Made +- TemplateService uses `using ModelSiteTemplate = SharepointToolbox.Core.Models.SiteTemplate` alias — consistent with ITemplateService.cs established in Plan 04-01 +- FolderStructureService.BuildUniquePaths sorts by slash depth (fewer slashes = shallower path = parent) — guarantees parent folders are created before children when SharePoint's Folders.Add does not create intermediates +- ApplyTemplateAsync creates a new ClientContext(siteUrl) for the newly created site — the adminCtx.Url is the admin site URL, not the new site + +## Deviations from Plan + +### Auto-fixed Issues + +**1. [Rule 1 - Bug] Plan's BuildUniquePaths_DuplicateRows_Deduplicated expected count was incorrect** +- **Found during:** Task 2 (writing unit tests) +- **Issue:** Plan specified `Assert.Equal(4, paths.Count)` for rows `{A,B}`, `{A,B}`, `{A,C}` which produces 3 unique paths: "A", "A/B", "A/C" +- **Fix:** Changed expected count from 4 to 3 to match correct deduplication behavior +- **Files modified:** `SharepointToolbox.Tests/Services/FolderStructureServiceTests.cs` +- **Verification:** Test passes with correct assertion +- **Committed in:** `84cd569` (Task 2 commit) + +--- + +**Total deviations:** 1 auto-fixed (1 x Rule 1 - plan spec bug in test expectation) +**Impact on plan:** Corrected incorrect test expectation; actual BuildUniquePaths behavior is correct. No scope creep. + +## Issues Encountered +- Transient WPF build file locking (`.msCoverageSourceRootsMapping_*`, `CoverletSourceRootsMapping_*`) required deleting locked coverage files and creating root `obj/` directory before builds succeeded. This is an established environment issue unrelated to code changes. +- TemplateService.cs was already committed in a prior plan agent's docs commit — verified content matches plan spec exactly (372 lines, full implementation). + +## User Setup Required +None - no external service configuration required. + +## Next Phase Readiness +- TemplateService and FolderStructureService are ready for Plan 04-07 (ViewModels for template and folder operations) +- Both services use BulkOperationRunner for per-item error handling, consistent with Plans 04-03 to 04-05 +- All 122 tests pass (0 failures) across the full test suite + +## Self-Check: PASSED + +All files found, all commits verified. + +--- +*Phase: 04-bulk-operations-and-provisioning* +*Completed: 2026-04-03*