@phuc1403/musketeer 0.9.0 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/INSTALLATION.md +53 -52
- package/README.md +1 -1
- package/bin/musketeer.js +168 -168
- package/manifest.json +19 -2
- package/package.json +48 -48
- package/src/dotnet-scaffold-copier.js +79 -79
- package/src/provisioner/detect.js +93 -93
- package/src/self-update.js +77 -77
- package/template/.claude/agents/git-manager.md +18 -18
- package/template/.claude/agents/hallmark-auditor.md +78 -78
- package/template/.claude/agents/researcher.md +33 -33
- package/template/.claude/hooks/block-unsafe-adr-title.cjs +85 -85
- package/template/.claude/hooks/init-adr-dir.cjs +173 -173
- package/template/.claude/hooks/inject-adr-flags.cjs +94 -94
- package/template/.claude/hooks/lib/adr/command-scan.cjs +115 -115
- package/template/.claude/hooks/lib/characteristics/checker.cjs +357 -357
- package/template/.claude/hooks/lib/git-info-cache.cjs +191 -191
- package/template/.claude/hooks/sync-adr-toc.cjs +146 -146
- package/template/.claude/hooks/usage-quota-cache-refresh.cjs +166 -166
- package/template/.claude/hooks/validate-characteristics-hook.cjs +66 -66
- package/template/.claude/hooks/validate-cml-hook.js +146 -145
- package/template/.claude/skills/adr-writer/SKILL.md +48 -48
- package/template/.claude/skills/adr-writer/references/adr-example.md +35 -35
- package/template/.claude/skills/architecture-characteristic-writer/SKILL.md +215 -215
- package/template/.claude/skills/architecture-characteristic-writer/assets/worksheet-template.md +29 -29
- package/template/.claude/skills/architecture-characteristic-writer/references/characteristics-catalog.md +40 -40
- package/template/.claude/skills/architecture-characteristic-writer/scripts/ranking-table.cjs +171 -171
- package/template/.claude/skills/context-map/SKILL.md +80 -80
- package/template/.claude/skills/context-map/example.cml +106 -106
- package/template/.claude/skills/context-map/reference/Bounded Context/Bounded Context.md +40 -40
- package/template/.claude/skills/context-map/reference/Bounded Context/businessModel.md +5 -5
- package/template/.claude/skills/context-map/reference/Bounded Context/domainVisionStatement.md +2 -2
- package/template/.claude/skills/context-map/reference/Bounded Context/evolution.md +5 -5
- package/template/.claude/skills/context-map/reference/Bounded Context/implementationTechnology.md +1 -1
- package/template/.claude/skills/context-map/reference/Bounded Context/implements.md +1 -1
- package/template/.claude/skills/context-map/reference/Bounded Context/knowledgeLevel.md +4 -4
- package/template/.claude/skills/context-map/reference/Bounded Context/realizes.md +9 -9
- package/template/.claude/skills/context-map/reference/Bounded Context/refines.md +10 -10
- package/template/.claude/skills/context-map/reference/Bounded Context/responsibilities.md +26 -26
- package/template/.claude/skills/context-map/reference/Bounded Context/type.md +23 -23
- package/template/.claude/skills/context-map/reference/Bounded Context Relationship/Anticorruption Layer.md +5 -5
- package/template/.claude/skills/context-map/reference/Bounded Context Relationship/Bounded Context Relationship.md +12 -12
- package/template/.claude/skills/context-map/reference/Bounded Context Relationship/Conformist.md +5 -5
- package/template/.claude/skills/context-map/reference/Bounded Context Relationship/Customer-Supplier (C-S).md +22 -22
- package/template/.claude/skills/context-map/reference/Bounded Context Relationship/Open Host Service.md +4 -4
- package/template/.claude/skills/context-map/reference/Bounded Context Relationship/Partnership (P).md +13 -13
- package/template/.claude/skills/context-map/reference/Bounded Context Relationship/Published Language.md +4 -4
- package/template/.claude/skills/context-map/reference/Bounded Context Relationship/Shared Kernel (SK).md +12 -12
- package/template/.claude/skills/context-map/reference/Context Map.md +62 -62
- package/template/.claude/skills/context-map/reference/Domain/Domain.md +30 -30
- package/template/.claude/skills/context-map/reference/Domain/supports.md +33 -33
- package/template/.claude/skills/context-map/reference/Domain/type.md +3 -3
- package/template/.claude/skills/context-map/reference/Semantic Rules.md +32 -32
- package/template/.claude/skills/hallmark/SKILL.md +552 -552
- package/template/.claude/skills/hallmark/references/anti-patterns.md +412 -412
- package/template/.claude/skills/hallmark/references/assets.md +406 -406
- package/template/.claude/skills/hallmark/references/color.md +95 -95
- package/template/.claude/skills/hallmark/references/component-cookbook.md +256 -256
- package/template/.claude/skills/hallmark/references/components/c1-outlined-chip.md +12 -12
- package/template/.claude/skills/hallmark/references/components/c2-inline-form-as-cta.md +16 -16
- package/template/.claude/skills/hallmark/references/components/c3-typographic-link.md +8 -8
- package/template/.claude/skills/hallmark/references/components/c4-sticky-bottom-bar.md +16 -16
- package/template/.claude/skills/hallmark/references/components/f1-bento-grid.md +20 -20
- package/template/.claude/skills/hallmark/references/components/f2-sticky-scroll-stack.md +20 -20
- package/template/.claude/skills/hallmark/references/components/f3-tabular-spec-sheet.md +11 -11
- package/template/.claude/skills/hallmark/references/components/f4-step-sequence.md +11 -11
- package/template/.claude/skills/hallmark/references/components/f5-annotated-screenshot.md +11 -11
- package/template/.claude/skills/hallmark/references/components/f6-product-card-grid.md +41 -41
- package/template/.claude/skills/hallmark/references/components/ft1-mast-headed.md +13 -13
- package/template/.claude/skills/hallmark/references/components/ft2-inline-rule-single-line.md +10 -10
- package/template/.claude/skills/hallmark/references/components/ft3-index-style-category-list.md +12 -12
- package/template/.claude/skills/hallmark/references/components/ft4-dense-typographic.md +10 -10
- package/template/.claude/skills/hallmark/references/components/ft5-statement.md +21 -21
- package/template/.claude/skills/hallmark/references/components/ft6-letter-close.md +19 -19
- package/template/.claude/skills/hallmark/references/components/ft7-newsletter-first.md +27 -27
- package/template/.claude/skills/hallmark/references/components/ft8-marquee-scroll.md +25 -25
- package/template/.claude/skills/hallmark/references/components/h1-marquee.md +15 -15
- package/template/.claude/skills/hallmark/references/components/h2-split-diptych.md +15 -15
- package/template/.claude/skills/hallmark/references/components/h3-quote-led.md +11 -11
- package/template/.claude/skills/hallmark/references/components/h4-stat-led.md +14 -14
- package/template/.claude/skills/hallmark/references/components/h5-letter-hero.md +11 -11
- package/template/.claude/skills/hallmark/references/components/h6-photographic-fold.md +16 -16
- package/template/.claude/skills/hallmark/references/components/h7-demo-video-clipped-by-viewport-edge.md +27 -27
- package/template/.claude/skills/hallmark/references/components/h8-mockup-split-browser-framed.md +23 -23
- package/template/.claude/skills/hallmark/references/components/h9-custom-illustration-centerpiece.md +27 -27
- package/template/.claude/skills/hallmark/references/components/n1-wordmark-2-links.md +12 -12
- package/template/.claude/skills/hallmark/references/components/n10-floating-on-scroll-morph.md +19 -19
- package/template/.claude/skills/hallmark/references/components/n2-floating-chip.md +14 -14
- package/template/.claude/skills/hallmark/references/components/n3-side-rail.md +14 -14
- package/template/.claude/skills/hallmark/references/components/n4-hidden-behind-k.md +9 -9
- package/template/.claude/skills/hallmark/references/components/n5-floating-pill.md +28 -28
- package/template/.claude/skills/hallmark/references/components/n6-newspaper-masthead.md +24 -24
- package/template/.claude/skills/hallmark/references/components/n7-brutal-slab.md +22 -22
- package/template/.claude/skills/hallmark/references/components/n8-terminal-command.md +21 -21
- package/template/.claude/skills/hallmark/references/components/n9-edge-aligned-minimal.md +17 -17
- package/template/.claude/skills/hallmark/references/components/s1-left-margin-numbered.md +15 -15
- package/template/.claude/skills/hallmark/references/components/s2-hanging.md +13 -13
- package/template/.claude/skills/hallmark/references/components/s3-sticky-pinned.md +19 -19
- package/template/.claude/skills/hallmark/references/components/s4-inline-no-break.md +11 -11
- package/template/.claude/skills/hallmark/references/components/s5-bottom-anchored.md +13 -13
- package/template/.claude/skills/hallmark/references/components/t1-pull-quote-with-marginalia.md +12 -12
- package/template/.claude/skills/hallmark/references/components/t2-logo-wall-hairline.md +19 -19
- package/template/.claude/skills/hallmark/references/components/t3-single-huge-quote.md +11 -11
- package/template/.claude/skills/hallmark/references/components/t4-numbered-stat-strip.md +14 -14
- package/template/.claude/skills/hallmark/references/contract.md +24 -24
- package/template/.claude/skills/hallmark/references/copy.md +182 -182
- package/template/.claude/skills/hallmark/references/custom-craft.md +626 -626
- package/template/.claude/skills/hallmark/references/custom-theme.md +329 -329
- package/template/.claude/skills/hallmark/references/design-md.md +116 -116
- package/template/.claude/skills/hallmark/references/export-formats.md +328 -328
- package/template/.claude/skills/hallmark/references/floating-nav.md +89 -89
- package/template/.claude/skills/hallmark/references/genres/atmospheric.md +65 -65
- package/template/.claude/skills/hallmark/references/genres/editorial.md +70 -70
- package/template/.claude/skills/hallmark/references/genres/modern-minimal.md +67 -67
- package/template/.claude/skills/hallmark/references/genres/playful.md +65 -65
- package/template/.claude/skills/hallmark/references/hero-enrichment.md +474 -474
- package/template/.claude/skills/hallmark/references/imagery-kit.md +170 -170
- package/template/.claude/skills/hallmark/references/interaction-and-states.md +207 -207
- package/template/.claude/skills/hallmark/references/layout-and-space.md +111 -111
- package/template/.claude/skills/hallmark/references/macrostructures/01-bento-grid.md +35 -35
- package/template/.claude/skills/hallmark/references/macrostructures/02-long-document.md +34 -34
- package/template/.claude/skills/hallmark/references/macrostructures/03-marquee-hero.md +31 -31
- package/template/.claude/skills/hallmark/references/macrostructures/04-stat-led.md +32 -32
- package/template/.claude/skills/hallmark/references/macrostructures/05-workbench.md +32 -32
- package/template/.claude/skills/hallmark/references/macrostructures/06-conversational-faq.md +33 -33
- package/template/.claude/skills/hallmark/references/macrostructures/07-manifesto.md +32 -32
- package/template/.claude/skills/hallmark/references/macrostructures/08-photographic.md +34 -34
- package/template/.claude/skills/hallmark/references/macrostructures/09-quote-led.md +32 -32
- package/template/.claude/skills/hallmark/references/macrostructures/10-specimen.md +32 -32
- package/template/.claude/skills/hallmark/references/macrostructures/11-catalogue.md +23 -23
- package/template/.claude/skills/hallmark/references/macrostructures/12-letter.md +23 -23
- package/template/.claude/skills/hallmark/references/macrostructures/13-index-first.md +23 -23
- package/template/.claude/skills/hallmark/references/macrostructures/14-narrative-workflow.md +23 -23
- package/template/.claude/skills/hallmark/references/macrostructures/15-split-studio.md +23 -23
- package/template/.claude/skills/hallmark/references/macrostructures/16-feature-stack.md +23 -23
- package/template/.claude/skills/hallmark/references/macrostructures/17-type-specimen.md +23 -23
- package/template/.claude/skills/hallmark/references/macrostructures/18-portfolio-grid.md +23 -23
- package/template/.claude/skills/hallmark/references/macrostructures/19-map-diagram.md +23 -23
- package/template/.claude/skills/hallmark/references/macrostructures/20-ecosystem-index.md +23 -23
- package/template/.claude/skills/hallmark/references/macrostructures/21-component-playground.md +23 -23
- package/template/.claude/skills/hallmark/references/macrostructures.md +89 -89
- package/template/.claude/skills/hallmark/references/microinteractions.md +260 -260
- package/template/.claude/skills/hallmark/references/motion.md +109 -109
- package/template/.claude/skills/hallmark/references/preview-examples.md +49 -49
- package/template/.claude/skills/hallmark/references/responsive.md +138 -138
- package/template/.claude/skills/hallmark/references/slop-test.md +205 -205
- package/template/.claude/skills/hallmark/references/structure.md +164 -164
- package/template/.claude/skills/hallmark/references/study.md +511 -511
- package/template/.claude/skills/hallmark/references/typography.md +243 -243
- package/template/.claude/skills/hallmark/references/verbs/audit.md +25 -25
- package/template/.claude/skills/hallmark/references/verbs/redesign.md +269 -269
- package/template/.claude/skills/hallmark-loop/SKILL.md +105 -105
- package/template/.claude/skills/hallmark-loop/references/auditor-call.md +60 -60
- package/template/.claude/skills/hallmark-loop/references/capture.md +78 -78
- package/template/.claude/skills/hallmark-loop/references/loop-control.md +79 -79
- package/template/.claude/skills/handoff/SKILL.md +15 -15
- package/template/.claude/skills/knowledge-crunching/SKILL.md +94 -94
- package/template/.claude/skills/logical-components/.gitattributes +2 -0
- package/template/.claude/skills/logical-components/SKILL.md +102 -0
- package/template/.claude/skills/logical-components/references/component-classifier-prompt.md +53 -0
- package/template/.claude/skills/logical-components/references/responsibility-agent-prompt.md +67 -0
- package/template/.claude/skills/logical-components/references/responsibility-verifier-prompt.md +39 -0
- package/template/.claude/skills/logical-components/scripts/Directory.Build.props +7 -0
- package/template/.claude/skills/logical-components/scripts/Directory.Packages.props +8 -0
- package/template/.claude/skills/logical-components/scripts/LogicalComponents/BatchPlanning.cs +69 -0
- package/template/.claude/skills/logical-components/scripts/LogicalComponents/BatchesCommand.cs +39 -0
- package/template/.claude/skills/logical-components/scripts/LogicalComponents/CandidatesCommand.cs +70 -0
- package/template/.claude/skills/logical-components/scripts/LogicalComponents/CitableSource.cs +39 -0
- package/template/.claude/skills/logical-components/scripts/LogicalComponents/Citation.cs +37 -0
- package/template/.claude/skills/logical-components/scripts/LogicalComponents/ClassifyBatchesCommand.cs +65 -0
- package/template/.claude/skills/logical-components/scripts/LogicalComponents/ClassifyMergeCommand.cs +187 -0
- package/template/.claude/skills/logical-components/scripts/LogicalComponents/ComponentDiscovery.cs +166 -0
- package/template/.claude/skills/logical-components/scripts/LogicalComponents/ComponentRule.cs +87 -0
- package/template/.claude/skills/logical-components/scripts/LogicalComponents/ComponentsFile.cs +83 -0
- package/template/.claude/skills/logical-components/scripts/LogicalComponents/CouplingResolver.cs +196 -0
- package/template/.claude/skills/logical-components/scripts/LogicalComponents/DisplayName.cs +14 -0
- package/template/.claude/skills/logical-components/scripts/LogicalComponents/EdgeExtraction.cs +111 -0
- package/template/.claude/skills/logical-components/scripts/LogicalComponents/ExtractCommand.cs +72 -0
- package/template/.claude/skills/logical-components/scripts/LogicalComponents/ExtractConfig.cs +79 -0
- package/template/.claude/skills/logical-components/scripts/LogicalComponents/LogicalComponents.csproj +15 -0
- package/template/.claude/skills/logical-components/scripts/LogicalComponents/MarkdownRenderer.cs +73 -0
- package/template/.claude/skills/logical-components/scripts/LogicalComponents/MemberUseResolution.cs +203 -0
- package/template/.claude/skills/logical-components/scripts/LogicalComponents/MemberUses.cs +155 -0
- package/template/.claude/skills/logical-components/scripts/LogicalComponents/PortResolution.cs +75 -0
- package/template/.claude/skills/logical-components/scripts/LogicalComponents/Program.cs +27 -0
- package/template/.claude/skills/logical-components/scripts/LogicalComponents/ProjectFilters.cs +76 -0
- package/template/.claude/skills/logical-components/scripts/LogicalComponents/PruneCommand.cs +132 -0
- package/template/.claude/skills/logical-components/scripts/LogicalComponents/RenderCommand.cs +173 -0
- package/template/.claude/skills/logical-components/scripts/LogicalComponents/ResponsibilityBatches.cs +84 -0
- package/template/.claude/skills/logical-components/scripts/LogicalComponents/ResponsibilityValidation.cs +178 -0
- package/template/.claude/skills/logical-components/scripts/LogicalComponents/SeamDispatch.cs +59 -0
- package/template/.claude/skills/logical-components/scripts/LogicalComponents/SymbolNames.cs +53 -0
- package/template/.claude/skills/logical-components/scripts/LogicalComponents/TypeMap.cs +75 -0
- package/template/.claude/skills/logical-components/scripts/LogicalComponents/WalkRoots.cs +63 -0
- package/template/.claude/skills/logical-components/scripts/LogicalComponents/WorkspaceLoader.cs +227 -0
- package/template/.claude/skills/logical-components/scripts/LogicalComponents.Tests/AssignIdsTests.cs +41 -0
- package/template/.claude/skills/logical-components/scripts/LogicalComponents.Tests/BatchPlanningTests.cs +82 -0
- package/template/.claude/skills/logical-components/scripts/LogicalComponents.Tests/CandidatesCommandTests.cs +34 -0
- package/template/.claude/skills/logical-components/scripts/LogicalComponents.Tests/CitationTests.cs +42 -0
- package/template/.claude/skills/logical-components/scripts/LogicalComponents.Tests/ClassifyCommandsTests.cs +176 -0
- package/template/.claude/skills/logical-components/scripts/LogicalComponents.Tests/ComponentDiscoveryTests.cs +190 -0
- package/template/.claude/skills/logical-components/scripts/LogicalComponents.Tests/CouplingExtractionTests.cs +174 -0
- package/template/.claude/skills/logical-components/scripts/LogicalComponents.Tests/DisplayNameTests.cs +17 -0
- package/template/.claude/skills/logical-components/scripts/LogicalComponents.Tests/ExtractConfigTests.cs +72 -0
- package/template/.claude/skills/logical-components/scripts/LogicalComponents.Tests/FixturePaths.cs +32 -0
- package/template/.claude/skills/logical-components/scripts/LogicalComponents.Tests/LogicalComponents.Tests.csproj +23 -0
- package/template/.claude/skills/logical-components/scripts/LogicalComponents.Tests/MarkdownRendererTests.cs +50 -0
- package/template/.claude/skills/logical-components/scripts/LogicalComponents.Tests/ProjectFiltersTests.cs +65 -0
- package/template/.claude/skills/logical-components/scripts/LogicalComponents.Tests/PruneCommandTests.cs +119 -0
- package/template/.claude/skills/logical-components/scripts/LogicalComponents.Tests/RenderCommandTests.cs +162 -0
- package/template/.claude/skills/logical-components/scripts/LogicalComponents.Tests/RenderGoldenTests.cs +34 -0
- package/template/.claude/skills/logical-components/scripts/LogicalComponents.Tests/RenderTestData.cs +49 -0
- package/template/.claude/skills/logical-components/scripts/LogicalComponents.Tests/ResponsibilityValidationTests.cs +227 -0
- package/template/.claude/skills/logical-components/scripts/LogicalComponents.Tests/SampleAppWorkspace.cs +27 -0
- package/template/.claude/skills/logical-components/scripts/LogicalComponents.Tests/WorkspaceLoaderTests.cs +87 -0
- package/template/.claude/skills/logical-components/scripts/fixtures/BrokenApp/src/Broken.Application/Broken.Application.csproj +7 -0
- package/template/.claude/skills/logical-components/scripts/fixtures/BrokenApp/src/Broken.Application/Broken.cs +7 -0
- package/template/.claude/skills/logical-components/scripts/fixtures/MultiTargetApp/MultiTargetApp.slnx +6 -0
- package/template/.claude/skills/logical-components/scripts/fixtures/MultiTargetApp/src/Legacy.FSharp/Legacy.FSharp.fsproj +8 -0
- package/template/.claude/skills/logical-components/scripts/fixtures/MultiTargetApp/src/Legacy.FSharp/Library.fs +5 -0
- package/template/.claude/skills/logical-components/scripts/fixtures/MultiTargetApp/src/Multi.Application/Multi.Application.csproj +7 -0
- package/template/.claude/skills/logical-components/scripts/fixtures/MultiTargetApp/src/Multi.Application/Scheduling.cs +14 -0
- package/template/.claude/skills/logical-components/scripts/fixtures/NoSolutionApp/src/Solo.Application/Solo.Application.csproj +7 -0
- package/template/.claude/skills/logical-components/scripts/fixtures/NoSolutionApp/src/Solo.Application/SoloGreeting.cs +7 -0
- package/template/.claude/skills/logical-components/scripts/fixtures/NoSolutionApp/src/Solo.Application.Tests/FakeGreeting.cs +6 -0
- package/template/.claude/skills/logical-components/scripts/fixtures/NoSolutionApp/src/Solo.Application.Tests/Solo.Application.Tests.csproj +11 -0
- package/template/.claude/skills/logical-components/scripts/fixtures/RenderGolden/components.json +63 -0
- package/template/.claude/skills/logical-components/scripts/fixtures/RenderGolden/expected.md +28 -0
- package/template/.claude/skills/logical-components/scripts/fixtures/RenderGolden/repo/src/App/OrderAcceptance.cs +16 -0
- package/template/.claude/skills/logical-components/scripts/fixtures/RenderGolden/repo/src/Infra/OrderQueue.cs +10 -0
- package/template/.claude/skills/logical-components/scripts/fixtures/RenderGolden/resp/batch-01.json +18 -0
- package/template/.claude/skills/logical-components/scripts/fixtures/SampleApp/SampleApp.slnx +10 -0
- package/template/.claude/skills/logical-components/scripts/fixtures/SampleApp/logical-components.json +78 -0
- package/template/.claude/skills/logical-components/scripts/fixtures/SampleApp/src/Sample.Application/CandidateCases.cs +37 -0
- package/template/.claude/skills/logical-components/scripts/fixtures/SampleApp/src/Sample.Application/CouplingCases.cs +33 -0
- package/template/.claude/skills/logical-components/scripts/fixtures/SampleApp/src/Sample.Application/DependencyInjection.cs +18 -0
- package/template/.claude/skills/logical-components/scripts/fixtures/SampleApp/src/Sample.Application/EdgeCases.cs +63 -0
- package/template/.claude/skills/logical-components/scripts/fixtures/SampleApp/src/Sample.Application/LoudNotifying.Base.cs +5 -0
- package/template/.claude/skills/logical-components/scripts/fixtures/SampleApp/src/Sample.Application/LoudNotifying.cs +7 -0
- package/template/.claude/skills/logical-components/scripts/fixtures/SampleApp/src/Sample.Application/OrderAcceptance.cs +17 -0
- package/template/.claude/skills/logical-components/scripts/fixtures/SampleApp/src/Sample.Application/OrderOptions.cs +9 -0
- package/template/.claude/skills/logical-components/scripts/fixtures/SampleApp/src/Sample.Application/OrderRejectedException.cs +7 -0
- package/template/.claude/skills/logical-components/scripts/fixtures/SampleApp/src/Sample.Application/OrderRequest.cs +4 -0
- package/template/.claude/skills/logical-components/scripts/fixtures/SampleApp/src/Sample.Application/OrderRunning.cs +18 -0
- package/template/.claude/skills/logical-components/scripts/fixtures/SampleApp/src/Sample.Application/OrderValidation.cs +6 -0
- package/template/.claude/skills/logical-components/scripts/fixtures/SampleApp/src/Sample.Application/Ports.cs +19 -0
- package/template/.claude/skills/logical-components/scripts/fixtures/SampleApp/src/Sample.Application/PriceRules.cs +7 -0
- package/template/.claude/skills/logical-components/scripts/fixtures/SampleApp/src/Sample.Application/ReceiptPrinting.Totals.cs +6 -0
- package/template/.claude/skills/logical-components/scripts/fixtures/SampleApp/src/Sample.Application/ReceiptPrinting.cs +7 -0
- package/template/.claude/skills/logical-components/scripts/fixtures/SampleApp/src/Sample.Application/ReviewCases.cs +107 -0
- package/template/.claude/skills/logical-components/scripts/fixtures/SampleApp/src/Sample.Application/ReviewFixCases.cs +143 -0
- package/template/.claude/skills/logical-components/scripts/fixtures/SampleApp/src/Sample.Application/RunClock.cs +12 -0
- package/template/.claude/skills/logical-components/scripts/fixtures/SampleApp/src/Sample.Application/Sample.Application.csproj +10 -0
- package/template/.claude/skills/logical-components/scripts/fixtures/SampleApp/src/Sample.Application/SeeThroughCases.cs +89 -0
- package/template/.claude/skills/logical-components/scripts/fixtures/SampleApp/src/Sample.Billing.Application/OrderRunning.cs +7 -0
- package/template/.claude/skills/logical-components/scripts/fixtures/SampleApp/src/Sample.Billing.Application/Sample.Billing.Application.csproj +11 -0
- package/template/.claude/skills/logical-components/scripts/fixtures/SampleApp/src/Sample.Infrastructure/ForwardedNotifier.cs +8 -0
- package/template/.claude/skills/logical-components/scripts/fixtures/SampleApp/src/Sample.Infrastructure/InfrastructureDependencyInjection.cs +16 -0
- package/template/.claude/skills/logical-components/scripts/fixtures/SampleApp/src/Sample.Infrastructure/Mailer.cs +6 -0
- package/template/.claude/skills/logical-components/scripts/fixtures/SampleApp/src/Sample.Infrastructure/OrderQueue.cs +11 -0
- package/template/.claude/skills/logical-components/scripts/fixtures/SampleApp/src/Sample.Infrastructure/QueueEntry.cs +4 -0
- package/template/.claude/skills/logical-components/scripts/fixtures/SampleApp/src/Sample.Infrastructure/QueueStore.cs +8 -0
- package/template/.claude/skills/logical-components/scripts/fixtures/SampleApp/src/Sample.Infrastructure/ReviewCases.cs +35 -0
- package/template/.claude/skills/logical-components/scripts/fixtures/SampleApp/src/Sample.Infrastructure/ReviewFixCases.cs +13 -0
- package/template/.claude/skills/logical-components/scripts/fixtures/SampleApp/src/Sample.Infrastructure/Sample.Infrastructure.csproj +13 -0
- package/template/.claude/skills/logical-components/scripts/fixtures/SampleApp/src/Sample.Infrastructure/SeeThroughCases.cs +18 -0
- package/template/.claude/skills/logical-components/scripts/fixtures/SampleApp/src/Sample.Infrastructure/UnreachedPlumbing.cs +7 -0
- package/template/.claude/skills/logical-components/scripts/fixtures/SampleApp/tests/Sample.Tests/FakeOrderQueue.cs +11 -0
- package/template/.claude/skills/logical-components/scripts/fixtures/SampleApp/tests/Sample.Tests/Sample.Tests.csproj +11 -0
- package/template/.claude/skills/logical-components/scripts/fixtures/SharedOutsideRepo/SharedClock.cs +7 -0
- package/template/.claude/skills/logical-components/scripts/global.json +5 -0
- package/template/.claude/skills/logical-components/scripts/smoke-sample.sh +26 -0
- package/template/.claude/skills/research/SKILL.md +69 -69
- package/template/.claude/skills/tdd/SKILL.md +142 -142
- package/template/.claude/skills/tdd/deep-modules.md +15 -15
- package/template/.claude/skills/tdd/interface-design.md +31 -31
- package/template/.claude/skills/tdd/mocking.md +59 -59
- package/template/.claude/skills/tdd/refactoring.md +10 -10
- package/template/.claude/skills/tdd/tests.md +61 -61
- package/template/.claude/statusline.cjs +100 -37
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
{
|
|
2
|
+
"components": [
|
|
3
|
+
"Sample.Application.Archiving",
|
|
4
|
+
"Sample.Application.BatchRunning",
|
|
5
|
+
"Sample.Application.Builder",
|
|
6
|
+
"Sample.Application.Cache",
|
|
7
|
+
"Sample.Application.Cache`1",
|
|
8
|
+
"Sample.Application.CallbackNormalizing",
|
|
9
|
+
"Sample.Application.CrashSettling",
|
|
10
|
+
"Sample.Application.Echoing",
|
|
11
|
+
"Sample.Application.FallbackPricing",
|
|
12
|
+
"Sample.Application.JobCounting",
|
|
13
|
+
"Sample.Application.JobReporting",
|
|
14
|
+
"Sample.Application.JobShowing",
|
|
15
|
+
"Sample.Application.LabelMaking",
|
|
16
|
+
"Sample.Application.Labelling",
|
|
17
|
+
"Sample.Application.LazyWork",
|
|
18
|
+
"Sample.Application.Limits",
|
|
19
|
+
"Sample.Application.LineCounting",
|
|
20
|
+
"Sample.Application.LoudNotifying",
|
|
21
|
+
"Sample.Application.Measuring",
|
|
22
|
+
"Sample.Application.NotifyAll",
|
|
23
|
+
"Sample.Application.Notifying",
|
|
24
|
+
"Sample.Application.OrderAcceptance",
|
|
25
|
+
"Sample.Application.OrderHandling",
|
|
26
|
+
"Sample.Application.OrderNumberFormat",
|
|
27
|
+
"Sample.Application.OrderRunning",
|
|
28
|
+
"Sample.Application.OrderTextExtensions",
|
|
29
|
+
"Sample.Application.OrderValidation",
|
|
30
|
+
"Sample.Application.PingSending",
|
|
31
|
+
"Sample.Application.PongViaSeam",
|
|
32
|
+
"Sample.Application.PriceFormatting",
|
|
33
|
+
"Sample.Application.PriceRules",
|
|
34
|
+
"Sample.Application.ReceiptIssuing",
|
|
35
|
+
"Sample.Application.ReceiptPrinting",
|
|
36
|
+
"Sample.Application.Receipts",
|
|
37
|
+
"Sample.Application.RecoveryRouting",
|
|
38
|
+
"Sample.Application.RegistryReading",
|
|
39
|
+
"Sample.Application.RunClock",
|
|
40
|
+
"Sample.Application.ShapeListing",
|
|
41
|
+
"Sample.Application.ShippingStage",
|
|
42
|
+
"Sample.Application.Stamping",
|
|
43
|
+
"Sample.Application.TickCounter",
|
|
44
|
+
"Sample.Application.TickReading",
|
|
45
|
+
"Sample.Application.TitleReading",
|
|
46
|
+
"Sample.Application.TrackedReading",
|
|
47
|
+
"Sample.Application.TrackedWriting",
|
|
48
|
+
"Sample.Application.UrgentNotifying",
|
|
49
|
+
"Sample.Billing.Application.OrderRunning",
|
|
50
|
+
"Sample.Infrastructure.DefaultPricing",
|
|
51
|
+
"Sample.Infrastructure.DiskStorage",
|
|
52
|
+
"Sample.Infrastructure.DwgDrawing",
|
|
53
|
+
"Sample.Infrastructure.ExportRecovery",
|
|
54
|
+
"Sample.Infrastructure.ForwardedNotifier",
|
|
55
|
+
"Sample.Infrastructure.ImportRecovery",
|
|
56
|
+
"Sample.Infrastructure.LoggingHandler`1",
|
|
57
|
+
"Sample.Infrastructure.Mailer",
|
|
58
|
+
"Sample.Infrastructure.OrderQueue",
|
|
59
|
+
"Sample.Infrastructure.OrderRequestHandler",
|
|
60
|
+
"Sample.Infrastructure.PingHandling",
|
|
61
|
+
"Sample.Infrastructure.PongHandling",
|
|
62
|
+
"Sample.Infrastructure.QueueStore",
|
|
63
|
+
"Sample.Infrastructure.TextHandler",
|
|
64
|
+
"Sample.Infrastructure.UnreachedPlumbing"
|
|
65
|
+
],
|
|
66
|
+
"helpers": {
|
|
67
|
+
"Sample.Application.Dispatch": "Generic dispatch to handlers; no decision.",
|
|
68
|
+
"Sample.Application.LabelFormat": "Formats a label with the elapsed time; no decision.",
|
|
69
|
+
"Sample.Application.OrderNumber": "Value object: validates its own value.",
|
|
70
|
+
"Sample.Application.PaymentMethod": "Value object: one accepted-code check.",
|
|
71
|
+
"Sample.Application.PingText": "Text formatting.",
|
|
72
|
+
"Sample.Application.PongText": "Text formatting.",
|
|
73
|
+
"Sample.Application.Quantity": "Value object: arithmetic on its own value.",
|
|
74
|
+
"Sample.Application.StampedText": "Appends a fixed stamp to text.",
|
|
75
|
+
"Sample.Application.Ticks": "Enumerates ticks.",
|
|
76
|
+
"Sample.Application.TwoWay": "Handler pair used as a helper."
|
|
77
|
+
}
|
|
78
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
namespace Sample.Application;
|
|
2
|
+
|
|
3
|
+
// A value object that validates itself: a record with a method of its own, so a candidate (the config calls it a helper).
|
|
4
|
+
public sealed record OrderNumber(string Value)
|
|
5
|
+
{
|
|
6
|
+
public static OrderNumber Create(string raw) =>
|
|
7
|
+
raw.Length > 0 ? new OrderNumber(raw) : throw new ArgumentException("empty order number", nameof(raw));
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
// An abstract record holding a decision: a candidate, even though abstract records are never seams.
|
|
11
|
+
public abstract record PaymentMethod
|
|
12
|
+
{
|
|
13
|
+
public static bool IsAccepted(string code) => code == "card";
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// A record struct with behaviour: a candidate.
|
|
17
|
+
public readonly record struct Quantity(int Value)
|
|
18
|
+
{
|
|
19
|
+
public Quantity Add(int more) => new(Value + more);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// Only overrides object.ToString: formatting what it holds is not behaviour, so not a candidate.
|
|
23
|
+
public sealed record Money(decimal Amount)
|
|
24
|
+
{
|
|
25
|
+
public override string ToString() => $"{Amount:0.00}";
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// Properties and a constructor only: not a candidate.
|
|
29
|
+
public sealed class OrderSnapshot
|
|
30
|
+
{
|
|
31
|
+
public OrderSnapshot(int id)
|
|
32
|
+
{
|
|
33
|
+
Id = id;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
public int Id { get; }
|
|
37
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
namespace Sample.Application;
|
|
2
|
+
|
|
3
|
+
// Injects RunClock and also news one: a single edge with both kinds. Calls a C# 14 extension member: a static edge.
|
|
4
|
+
// Also takes a framework interface (IReadOnlyList<string>): not a port, never an edge.
|
|
5
|
+
public sealed class BatchRunning(RunClock clock, IReadOnlyList<string> labels)
|
|
6
|
+
{
|
|
7
|
+
public int LabelCount() => labels.Count;
|
|
8
|
+
|
|
9
|
+
public TimeSpan Run()
|
|
10
|
+
{
|
|
11
|
+
using var fresh = new RunClock();
|
|
12
|
+
return clock.Elapsed() + fresh.Elapsed();
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
public string Cost(decimal price) => price.AsMoney();
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// A multi-registration: IEnumerable<INotifier> resolves to every INotifier implementation. Calls a classic extension method.
|
|
19
|
+
public sealed class NotifyAll(IEnumerable<INotifier> notifiers)
|
|
20
|
+
{
|
|
21
|
+
public void Send(string message)
|
|
22
|
+
{
|
|
23
|
+
foreach (var notifier in notifiers)
|
|
24
|
+
{
|
|
25
|
+
notifier.Notify(message.Shout());
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
public static class OrderTextExtensions
|
|
31
|
+
{
|
|
32
|
+
public static string Shout(this string text) => text.ToUpperInvariant();
|
|
33
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
using Microsoft.Extensions.DependencyInjection;
|
|
2
|
+
|
|
3
|
+
namespace Sample.Application;
|
|
4
|
+
|
|
5
|
+
// Composition root: it `new`s everything, so it must never become a component or an edge source.
|
|
6
|
+
public static class DependencyInjection
|
|
7
|
+
{
|
|
8
|
+
public static IServiceCollection AddSampleApplication(this IServiceCollection services)
|
|
9
|
+
{
|
|
10
|
+
services.AddSingleton(new OrderValidation());
|
|
11
|
+
services.AddSingleton(sp => new OrderAcceptance(
|
|
12
|
+
sp.GetRequiredService<IOrderQueue>(),
|
|
13
|
+
sp.GetRequiredService<OrderValidation>(),
|
|
14
|
+
sp.GetRequiredService<INotifier>()));
|
|
15
|
+
services.AddSingleton(sp => new OrderRunning(sp.GetRequiredService<IAuditTrail>()));
|
|
16
|
+
return services;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
using System.Text.RegularExpressions;
|
|
2
|
+
using Microsoft.Extensions.DependencyInjection;
|
|
3
|
+
|
|
4
|
+
namespace Sample.Application;
|
|
5
|
+
|
|
6
|
+
// File-local: its metadata name embeds a hash of the absolute path, so it must never become a component.
|
|
7
|
+
file static class FileHelper
|
|
8
|
+
{
|
|
9
|
+
public static int Twice(int value) => value * 2;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
// Partial with a source-generated half: only this file may appear in its spans.
|
|
13
|
+
public sealed partial class OrderNumberFormat
|
|
14
|
+
{
|
|
15
|
+
[GeneratedRegex("^[0-9]+$")]
|
|
16
|
+
private static partial Regex Digits();
|
|
17
|
+
|
|
18
|
+
public bool IsValid(string orderNumber) => Digits().IsMatch(orderNumber);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// C# 14 extension block: its methods are behaviour, so this is a component.
|
|
22
|
+
public static class PriceFormatting
|
|
23
|
+
{
|
|
24
|
+
extension(decimal price)
|
|
25
|
+
{
|
|
26
|
+
public string AsMoney() => price.ToString("0.00");
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Composition root written as an extension block, with an ordinary helper beside it: still not a component.
|
|
31
|
+
public static class BillingSetup
|
|
32
|
+
{
|
|
33
|
+
extension(IServiceCollection services)
|
|
34
|
+
{
|
|
35
|
+
public IServiceCollection AddBilling() => services;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
public static int DefaultCurrencyDigits() => 2;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Only explicit interface implementations: still behaviour, so a component.
|
|
42
|
+
public interface ITick
|
|
43
|
+
{
|
|
44
|
+
void Tick();
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
public sealed class TickCounter : ITick
|
|
48
|
+
{
|
|
49
|
+
void ITick.Tick()
|
|
50
|
+
{
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// Same simple name, same module: the module prefix alone cannot tell these apart.
|
|
55
|
+
public sealed class Cache
|
|
56
|
+
{
|
|
57
|
+
public int Size() => 0;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
public sealed class Cache<T>
|
|
61
|
+
{
|
|
62
|
+
public T? Get() => default;
|
|
63
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
namespace Sample.Application;
|
|
2
|
+
|
|
3
|
+
// Primary constructor: DI of a port (IOrderQueue), a class (OrderValidation) and a forwarded port (INotifier).
|
|
4
|
+
public sealed class OrderAcceptance(IOrderQueue queue, OrderValidation validation, INotifier notifier)
|
|
5
|
+
{
|
|
6
|
+
public bool Accept(OrderRequest request)
|
|
7
|
+
{
|
|
8
|
+
if (!validation.IsValid(request))
|
|
9
|
+
{
|
|
10
|
+
notifier.Notify($"Rejected order {request.Id}");
|
|
11
|
+
return false;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
queue.Enqueue(request);
|
|
15
|
+
return true;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
namespace Sample.Application;
|
|
2
|
+
|
|
3
|
+
// An exception with a method of its own: still never a logical component.
|
|
4
|
+
public sealed class OrderRejectedException(string reason) : Exception(reason)
|
|
5
|
+
{
|
|
6
|
+
public static OrderRejectedException ForPrice(decimal price) => new($"Price {price} is not allowed");
|
|
7
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
namespace Sample.Application;
|
|
2
|
+
|
|
3
|
+
// Classic constructor: DI of a port with no implementation, plus a `new` edge inside a method body.
|
|
4
|
+
public sealed class OrderRunning
|
|
5
|
+
{
|
|
6
|
+
private readonly IAuditTrail _audit;
|
|
7
|
+
|
|
8
|
+
public OrderRunning(IAuditTrail audit)
|
|
9
|
+
{
|
|
10
|
+
_audit = audit;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
public void Run()
|
|
14
|
+
{
|
|
15
|
+
using var clock = new RunClock();
|
|
16
|
+
_audit.Record($"Ran in {clock.Elapsed()}");
|
|
17
|
+
}
|
|
18
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
namespace Sample.Application;
|
|
2
|
+
|
|
3
|
+
// Port implemented in Infrastructure: edges through it resolve to OrderQueue.
|
|
4
|
+
public interface IOrderQueue
|
|
5
|
+
{
|
|
6
|
+
void Enqueue(OrderRequest request);
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
// Port implemented in Infrastructure by a class registered through forwarding.
|
|
10
|
+
public interface INotifier
|
|
11
|
+
{
|
|
12
|
+
void Notify(string message);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
// Port with no implementation anywhere: must surface as an unresolved port.
|
|
16
|
+
public interface IAuditTrail
|
|
17
|
+
{
|
|
18
|
+
void Record(string entry);
|
|
19
|
+
}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
namespace Sample.Application;
|
|
2
|
+
|
|
3
|
+
// Generic port: IHandler<OrderRequest> resolves only to implementations of that construction, or open generic ones.
|
|
4
|
+
public interface IHandler<T>
|
|
5
|
+
{
|
|
6
|
+
void Handle(T item);
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
public sealed class OrderHandling(IHandler<OrderRequest> handler)
|
|
10
|
+
{
|
|
11
|
+
public void Run(OrderRequest request) => handler.Handle(request);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
// A nested type used from outside: the edge goes to its outer component, never to a top-level namesake.
|
|
15
|
+
public sealed class Receipts
|
|
16
|
+
{
|
|
17
|
+
public sealed class Builder
|
|
18
|
+
{
|
|
19
|
+
public string Build() => "receipt";
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
public string Prefix() => "R-";
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
public sealed class Builder
|
|
26
|
+
{
|
|
27
|
+
public string Build() => "top-level";
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
public sealed class ReceiptIssuing
|
|
31
|
+
{
|
|
32
|
+
public string Issue() => new Receipts.Builder().Build();
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// A static member on an interface runs no implementation code: no edge to implementations.
|
|
36
|
+
public interface IPricingDefaults
|
|
37
|
+
{
|
|
38
|
+
static decimal Fallback() => 1m;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
public sealed class FallbackPricing
|
|
42
|
+
{
|
|
43
|
+
public decimal Price() => IPricingDefaults.Fallback();
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// Consts are copied in at compile time: reading one is not coupling.
|
|
47
|
+
public static class Limits
|
|
48
|
+
{
|
|
49
|
+
public const int MaxLines = 100;
|
|
50
|
+
|
|
51
|
+
public static int Clamp(int lines) => Math.Min(lines, MaxLines);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
public sealed class LineCounting
|
|
55
|
+
{
|
|
56
|
+
public int Count(int lines) => lines > Limits.MaxLines ? Limits.MaxLines : lines;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// An abstract dependency resolves to its concrete subclasses, like an interface.
|
|
60
|
+
public abstract class StorageBase
|
|
61
|
+
{
|
|
62
|
+
public abstract void Save(string text);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
public sealed class Archiving(StorageBase storage)
|
|
66
|
+
{
|
|
67
|
+
public void Archive(string text) => storage.Save(text);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// A non-component abstract base: its own code counts toward the classes deriving from it.
|
|
71
|
+
public abstract class StageBase
|
|
72
|
+
{
|
|
73
|
+
protected string Stamp() => PriceRules.Check(1m) ? "ok" : "no";
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
public sealed class ShippingStage : StageBase
|
|
77
|
+
{
|
|
78
|
+
public string Run() => Stamp();
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// Inheriting from a component is an 'inherits' edge.
|
|
82
|
+
public class Notifying
|
|
83
|
+
{
|
|
84
|
+
public virtual string Channel() => "default";
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
public sealed class UrgentNotifying : Notifying
|
|
88
|
+
{
|
|
89
|
+
public override string Channel() => "urgent";
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// An abstract record is a data hierarchy, not a seam: holding a list of them is not coupling.
|
|
93
|
+
public abstract record Shape;
|
|
94
|
+
|
|
95
|
+
public sealed record Circle(double Radius) : Shape;
|
|
96
|
+
|
|
97
|
+
public sealed class ShapeListing(IReadOnlyList<Shape> shapes)
|
|
98
|
+
{
|
|
99
|
+
public int Count() => shapes.Count;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// Wrapped dependencies are dependencies on what they wrap.
|
|
103
|
+
public sealed class LazyWork(
|
|
104
|
+
Lazy<OrderValidation> validation, Func<RunClock> clocks, INotifier[] notifiers, IReadOnlyList<IOrderQueue> queues)
|
|
105
|
+
{
|
|
106
|
+
public int Count() => notifiers.Length + queues.Count + (validation.IsValueCreated ? 1 : 0) + (clocks() is null ? 0 : 1);
|
|
107
|
+
}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
namespace Sample.Application;
|
|
2
|
+
|
|
3
|
+
// A generic seam used inside a generic helper: only the construction the caller asks for is reached.
|
|
4
|
+
public interface ICommandHandler<T>
|
|
5
|
+
{
|
|
6
|
+
void Handle(T command);
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
public sealed record Ping(int N);
|
|
10
|
+
|
|
11
|
+
public sealed record Pong(int N);
|
|
12
|
+
|
|
13
|
+
public sealed class Dispatch(IEnumerable<object> handlers)
|
|
14
|
+
{
|
|
15
|
+
public void Send<T>(T command)
|
|
16
|
+
{
|
|
17
|
+
foreach (var handler in handlers.OfType<ICommandHandler<T>>())
|
|
18
|
+
{
|
|
19
|
+
handler.Handle(command);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
public sealed class PingSending(Dispatch dispatch)
|
|
25
|
+
{
|
|
26
|
+
public void Send() => dispatch.Send(new Ping(1));
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// A helper implementing two constructions of one seam: the member for the requested construction is the one that runs.
|
|
30
|
+
public sealed class TwoWay(RunClock clock) : ICommandHandler<Ping>, ICommandHandler<Pong>
|
|
31
|
+
{
|
|
32
|
+
public void Handle(Ping command)
|
|
33
|
+
{
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
public void Handle(Pong command)
|
|
37
|
+
{
|
|
38
|
+
clock.Elapsed();
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
public sealed class PongViaSeam(ICommandHandler<Pong> handler)
|
|
43
|
+
{
|
|
44
|
+
public void Run(Pong pong) => handler.Handle(pong);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Compiler-written record members (ToString, Equals) run nothing of the record's own code.
|
|
48
|
+
public sealed class JobShowing
|
|
49
|
+
{
|
|
50
|
+
public string Show(Job job) => job.ToString();
|
|
51
|
+
|
|
52
|
+
public bool Same(Job first, Job second) => first.Equals(second);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// Only the accessor that runs counts: reading a property never runs its setter.
|
|
56
|
+
public sealed class Tracked
|
|
57
|
+
{
|
|
58
|
+
private string _value = "";
|
|
59
|
+
|
|
60
|
+
public string Value
|
|
61
|
+
{
|
|
62
|
+
get => _value;
|
|
63
|
+
set => _value = CallbackNormalizing.Normalize(value);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
public sealed class TrackedReading
|
|
68
|
+
{
|
|
69
|
+
public string Read(Tracked tracked) => tracked.Value;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
public sealed class TrackedWriting
|
|
73
|
+
{
|
|
74
|
+
public void Write(Tracked tracked) => tracked.Value = "x";
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// An indexer, a user-defined operator and a foreach enumerator are calls too.
|
|
78
|
+
public sealed class Registry(RunClock clock)
|
|
79
|
+
{
|
|
80
|
+
public TimeSpan this[int index] => clock.Elapsed();
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
public sealed class RegistryReading
|
|
84
|
+
{
|
|
85
|
+
public TimeSpan Read(Registry registry) => registry[0];
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
public readonly struct Metres(int value)
|
|
89
|
+
{
|
|
90
|
+
public int Value => value;
|
|
91
|
+
|
|
92
|
+
public static Metres operator +(Metres first, Metres second) =>
|
|
93
|
+
new(first.Value + second.Value + (PriceRules.Check(1m) ? 0 : 1));
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
public sealed class Measuring
|
|
97
|
+
{
|
|
98
|
+
public Metres Sum(Metres first, Metres second) => first + second;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
public sealed class Ticks
|
|
102
|
+
{
|
|
103
|
+
public IEnumerator<int> GetEnumerator()
|
|
104
|
+
{
|
|
105
|
+
PriceRules.Check(1m);
|
|
106
|
+
yield return 1;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
public sealed class TickReading
|
|
111
|
+
{
|
|
112
|
+
public int Sum(Ticks ticks)
|
|
113
|
+
{
|
|
114
|
+
var sum = 0;
|
|
115
|
+
foreach (var tick in ticks)
|
|
116
|
+
{
|
|
117
|
+
sum += tick;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
return sum;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// Constructing a helper runs its base class's initializers too.
|
|
125
|
+
public class LabelBase
|
|
126
|
+
{
|
|
127
|
+
protected readonly TimeSpan Started = new RunClock().Elapsed();
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
public sealed class ShortLabel : LabelBase
|
|
131
|
+
{
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
public sealed class LabelMaking
|
|
135
|
+
{
|
|
136
|
+
public object Make() => new ShortLabel();
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// A partial method with no implementation has no body: not behaviour.
|
|
140
|
+
public sealed partial class Hooks
|
|
141
|
+
{
|
|
142
|
+
partial void OnStart();
|
|
143
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
<Project Sdk="Microsoft.NET.Sdk">
|
|
2
|
+
<PropertyGroup>
|
|
3
|
+
<TargetFramework>net10.0</TargetFramework>
|
|
4
|
+
<Nullable>enable</Nullable>
|
|
5
|
+
<ImplicitUsings>enable</ImplicitUsings>
|
|
6
|
+
</PropertyGroup>
|
|
7
|
+
<ItemGroup>
|
|
8
|
+
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="10.0.0" />
|
|
9
|
+
</ItemGroup>
|
|
10
|
+
</Project>
|