diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json index a5ef231..d2bed27 100644 --- a/.config/dotnet-tools.json +++ b/.config/dotnet-tools.json @@ -2,6 +2,13 @@ "version": 1, "isRoot": true, "tools": { + "dotnet-sonarscanner": { + "version": "11.2.1", + "commands": [ + "dotnet-sonarscanner" + ], + "rollForward": false + }, "demaconsulting.pandoctool": { "version": "3.10.0", "commands": [ @@ -59,7 +66,7 @@ "rollForward": false }, "demaconsulting.sysml2tools.tool": { - "version": "0.1.0-beta.11", + "version": "0.1.0-beta.13", "commands": [ "sysml2tools" ], diff --git a/.cspell.yaml b/.cspell.yaml index 58cc918..6477d62 100644 --- a/.cspell.yaml +++ b/.cspell.yaml @@ -14,9 +14,13 @@ words: - Argb - axaml - BGRA + - Blockquotes - bursty - buildmark + - dcterms - Dema + - doctitle + - docversion - Dockable - Dockables - fileassert @@ -24,6 +28,7 @@ words: - LOCALAPPDATA - Mvvm - Pandoc + - pagetitle - pasteable - postconditions - renderable diff --git a/.github/codeql-config.yml b/.github/codeql-config.yml new file mode 100644 index 0000000..ca3e447 --- /dev/null +++ b/.github/codeql-config.yml @@ -0,0 +1,4 @@ +--- +# CodeQL configuration for SysML2Workbench + +name: "SysML2Workbench CodeQL Config" diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml new file mode 100644 index 0000000..084f2b7 --- /dev/null +++ b/.github/workflows/build.yaml @@ -0,0 +1,938 @@ +--- +on: + workflow_call: + inputs: + version: + required: true + type: string + secrets: + SONAR_TOKEN: + required: true + +jobs: + # Performs quick quality checks for project formatting consistency including + # markdown linting, spell checking, and YAML validation. + quality-checks: + name: Quality Checks + runs-on: ubuntu-latest + permissions: + contents: read + steps: + # === INSTALL DEPENDENCIES === + # This section installs all required dependencies and tools for quality checks. + # Downstream projects: Add any additional dependency installations here. + + - name: Checkout + uses: actions/checkout@v7 + + - name: Setup dotnet + uses: actions/setup-dotnet@v5 + with: + dotnet-version: 9.x + + - name: Restore Tools + run: > + dotnet tool restore + + - name: Setup Node.js + uses: actions/setup-node@v6 + with: + node-version: 24.x + + - name: Setup Python + uses: actions/setup-python@v6 + with: + python-version: '3.14' + + # === CAPTURE TOOL VERSIONS === + # This section captures the versions of all tools used in the build process. + # Downstream projects: Add any additional tools to capture here. + + - name: Capture tool versions + shell: bash + run: | + mkdir -p artifacts + echo "Capturing tool versions..." + dotnet versionmark --capture --job-id "quality" \ + --output "artifacts/versionmark-quality.json" -- \ + dotnet git versionmark + echo "✓ Tool versions captured" + + # === CAPTURE OTS SELF-VALIDATION RESULTS === + # This section runs the self-validation of each OTS tool and saves TRX results + # so that OTS Software Requirements in requirements.yaml can be satisfied. + # Downstream projects: Add any additional OTS tool self-validation steps here. + + - name: Run VersionMark self-validation + run: > + dotnet versionmark + --validate + --results artifacts/versionmark-self-validation-quality.trx + + # === RUN QUALITY CHECKS === + # This section runs the linting and quality checks for the project. + # Downstream projects: Add any additional quality check steps here. + + - name: Run linters + shell: pwsh + run: ./lint.ps1 + + # === UPLOAD ARTIFACTS === + # This section uploads all generated artifacts for use by downstream jobs. + # Downstream projects: Add any additional artifact uploads here. + + - name: Upload quality artifacts + uses: actions/upload-artifact@v7 + with: + name: artifacts-quality + path: artifacts/ + + # Builds and unit-tests the project on supported operating systems to ensure + # unit-tests operate on all platforms and to run SonarScanner for generating + # the code quality report. + build: + name: Build ${{ matrix.os }} + needs: quality-checks + permissions: + contents: read + pull-requests: write + + strategy: + matrix: + os: [windows-latest, ubuntu-latest, macos-latest] + + runs-on: ${{ matrix.os }} + + steps: + + # === INSTALL DEPENDENCIES === + # This section installs all required dependencies and tools for building the project. + # Downstream projects: Add any additional dependency installations here. + + - name: Checkout + uses: actions/checkout@v7 + with: + fetch-depth: 0 + + - name: Setup dotnet + uses: actions/setup-dotnet@v5 + with: + dotnet-version: 9.x + + - name: Restore Tools + run: > + dotnet tool restore + + # === CAPTURE TOOL VERSIONS === + # This section captures the versions of all tools used in the build process. + # Downstream projects: Add any additional tools to capture here. + + - name: Capture tool versions + shell: bash + run: | + mkdir -p artifacts + echo "Capturing tool versions..." + # Create short job ID: build-windows, build-ubuntu, build-macos + OS_SHORT=$(echo "${{ matrix.os }}" | sed 's/-latest//') + JOB_ID="build-${OS_SHORT}" + dotnet versionmark --capture --job-id "${JOB_ID}" \ + --output "artifacts/versionmark-${JOB_ID}.json" -- \ + dotnet git dotnet-sonarscanner versionmark + echo "✓ Tool versions captured" + + # === CAPTURE OTS SELF-VALIDATION RESULTS === + # This section runs the self-validation of each OTS tool and saves TRX results + # so that OTS Software Requirements in requirements.yaml can be satisfied. + # Downstream projects: Add any additional OTS tool self-validation steps here. + + - name: Run VersionMark self-validation + run: > + dotnet versionmark + --validate + --results artifacts/versionmark-self-validation-${{ matrix.os }}.trx + + # === BUILD AND TEST === + # This section builds and tests the project. + # Downstream projects: Add any additional build or test steps here. + + - name: Restore Dependencies + run: > + dotnet restore + + - name: Start Sonar Scanner + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: > + dotnet dotnet-sonarscanner + begin + /k:"demaconsulting_SysML2Workbench" + /o:"demaconsulting" + /d:sonar.token="${{ secrets.SONAR_TOKEN }}" + /d:sonar.host.url="https://sonarcloud.io" + /d:sonar.cs.opencover.reportsPaths=**/*.opencover.xml + /d:sonar.scanner.scanAll=false + + - name: Build + run: > + dotnet build + --no-restore + --configuration Release + --property:Version=${{ inputs.version }} + + - name: Test + run: > + dotnet test + --no-build + --configuration Release + --property:Version=${{ inputs.version }} + --collect "XPlat Code Coverage;Format=opencover" + --logger "trx;LogFilePrefix=${{ matrix.os }}" + --results-directory artifacts + + - name: End Sonar Scanner + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: > + dotnet dotnet-sonarscanner + end + /d:sonar.token="${{ secrets.SONAR_TOKEN }}" + + # === PACKAGE DISTRIBUTABLES === + # This section publishes self-contained distributables and zips/packages them for the + # matrix leg's native RID(s), reusing the restore/tool-setup already done above instead + # of spinning up separate jobs that would repeat the checkout, dotnet setup, and tool + # restore. Windows also builds the MSI installer here since it is the only leg that can + # (Windows Installer format is a Windows-only dependency). + # Downstream projects: Add any additional packaging steps here. + + - name: Publish self-contained build (win-x64) + if: matrix.os == 'windows-latest' + run: > + dotnet publish + src/DemaConsulting.SysML2Workbench.Desktop/DemaConsulting.SysML2Workbench.Desktop.csproj + --configuration Release + --runtime win-x64 + --self-contained true + --property:Version=${{ inputs.version }} + --property:PublishSingleFile=true + --output publish/win-x64 + + - name: Remove debug symbols and docs from published output (win-x64) + if: matrix.os == 'windows-latest' + shell: pwsh + run: | + Get-ChildItem publish/win-x64 -Include *.pdb,*.xml -Recurse | Remove-Item -Force + + - name: Zip published output (win-x64) + if: matrix.os == 'windows-latest' + shell: pwsh + run: | + New-Item -ItemType Directory -Force -Path package | Out-Null + Compress-Archive -Path publish/win-x64/* -DestinationPath "package/SysML2Workbench-${{ inputs.version }}-win-x64.zip" + + - name: Compute MSI version + if: matrix.os == 'windows-latest' + shell: bash + run: | + MSI_VERSION=$(echo "${{ inputs.version }}" | cut -d'-' -f1) + echo "MSI_VERSION=${MSI_VERSION}" >> "$GITHUB_ENV" + echo "Computed MSI version: ${MSI_VERSION}" + + - name: Build MSI installer + if: matrix.os == 'windows-latest' + run: > + dotnet build + src/DemaConsulting.SysML2Workbench.Installer/DemaConsulting.SysML2Workbench.Installer.wixproj + --configuration Release + --property:Version=${{ env.MSI_VERSION }} + --property:SysML2WorkbenchPublishDir=${{ github.workspace }}/publish/win-x64/ + + - name: Copy MSI to package directory + if: matrix.os == 'windows-latest' + shell: pwsh + run: | + New-Item -ItemType Directory -Force -Path package | Out-Null + Copy-Item "src/DemaConsulting.SysML2Workbench.Installer/bin/x64/Release/*.msi" ` + "package/SysML2Workbench-${{ inputs.version }}-win-x64.msi" + + - name: Publish self-contained build (linux-x64) + if: matrix.os == 'ubuntu-latest' + run: > + dotnet publish + src/DemaConsulting.SysML2Workbench.Desktop/DemaConsulting.SysML2Workbench.Desktop.csproj + --configuration Release + --runtime linux-x64 + --self-contained true + --property:Version=${{ inputs.version }} + --property:PublishSingleFile=true + --output publish/linux-x64 + + - name: Remove debug symbols and docs from published output (linux-x64) + if: matrix.os == 'ubuntu-latest' + shell: bash + run: find publish/linux-x64 -type f \( -name '*.pdb' -o -name '*.xml' \) -delete + + - name: Zip published output (linux-x64) + if: matrix.os == 'ubuntu-latest' + shell: bash + run: | + mkdir -p package + (cd publish/linux-x64 && zip -r "../../package/SysML2Workbench-${{ inputs.version }}-linux-x64.zip" .) + + - name: Publish self-contained build (osx-x64) + if: matrix.os == 'macos-latest' + run: > + dotnet publish + src/DemaConsulting.SysML2Workbench.Desktop/DemaConsulting.SysML2Workbench.Desktop.csproj + --configuration Release + --runtime osx-x64 + --self-contained true + --property:Version=${{ inputs.version }} + --property:PublishSingleFile=true + --output publish/osx-x64 + + - name: Publish self-contained build (osx-arm64) + if: matrix.os == 'macos-latest' + run: > + dotnet publish + src/DemaConsulting.SysML2Workbench.Desktop/DemaConsulting.SysML2Workbench.Desktop.csproj + --configuration Release + --runtime osx-arm64 + --self-contained true + --property:Version=${{ inputs.version }} + --property:PublishSingleFile=true + --output publish/osx-arm64 + + - name: Remove debug symbols and docs from published output (osx-x64, osx-arm64) + if: matrix.os == 'macos-latest' + shell: bash + run: | + find publish/osx-x64 -type f \( -name '*.pdb' -o -name '*.xml' \) -delete + find publish/osx-arm64 -type f \( -name '*.pdb' -o -name '*.xml' \) -delete + + - name: Zip published output (osx-x64, osx-arm64) + if: matrix.os == 'macos-latest' + shell: bash + run: | + mkdir -p package + (cd publish/osx-x64 && zip -r "../../package/SysML2Workbench-${{ inputs.version }}-osx-x64.zip" .) + (cd publish/osx-arm64 && zip -r "../../package/SysML2Workbench-${{ inputs.version }}-osx-arm64.zip" .) + + # === UPLOAD ARTIFACTS === + # This section uploads all generated artifacts for use by downstream jobs. + # Downstream projects: Add any additional artifact uploads here. + + - name: Upload build artifacts + uses: actions/upload-artifact@v7 + with: + name: artifacts-build-${{ matrix.os }} + path: artifacts/ + + - name: Upload zip package artifacts + uses: actions/upload-artifact@v7 + with: + name: package-zip-${{ matrix.os }} + path: package/*.zip + + - name: Upload MSI package artifact + if: matrix.os == 'windows-latest' + uses: actions/upload-artifact@v7 + with: + name: package-msi + path: package/*.msi + + # Runs CodeQL security and quality analysis, gathering results to include + # in the code quality report. + codeql: + name: CodeQL Analysis + runs-on: ubuntu-latest + needs: quality-checks + permissions: + actions: read + contents: read + security-events: write + + steps: + # === INSTALL DEPENDENCIES === + # This section installs all required dependencies and tools for CodeQL analysis. + # Downstream projects: Add any additional dependency installations here. + + - name: Checkout + uses: actions/checkout@v7 + with: + fetch-depth: 0 + + - name: Initialize CodeQL + uses: github/codeql-action/init@v4 + with: + languages: csharp + build-mode: manual + queries: security-and-quality + config-file: ./.github/codeql-config.yml + + - name: Setup dotnet + uses: actions/setup-dotnet@v5 + with: + dotnet-version: 9.x + + - name: Restore Tools + run: > + dotnet tool restore + + - name: Restore Dependencies + run: > + dotnet restore + + # === BUILD AND ANALYZE === + # This section builds the project and performs CodeQL analysis. + # Downstream projects: Add any additional analysis steps here. + + - name: Build + run: > + dotnet build + --no-restore + --configuration Release + --property:Version=${{ inputs.version }} + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v4 + with: + category: "/language:csharp" + output: artifacts + upload: false + + # === UPLOAD ARTIFACTS === + # This section uploads all generated artifacts for use by downstream jobs. + # Downstream projects: Add any additional artifact uploads here. + + - name: Upload CodeQL artifacts + uses: actions/upload-artifact@v7 + with: + name: artifacts-codeql + path: artifacts/ + + # Builds the supporting documentation including user guides, requirements, + # trace matrices, code quality reports, and build notes. + build-docs: + name: Build Documents + runs-on: windows-latest + needs: [build, codeql] + permissions: + contents: read + + steps: + # === CHECKOUT AND DOWNLOAD ARTIFACTS === + # This section retrieves the code and all necessary artifacts from previous jobs. + # Downstream projects: Add any additional artifact downloads here. + + - name: Checkout + uses: actions/checkout@v7 + + - name: Download all job artifacts + uses: actions/download-artifact@v8 + with: + path: artifacts + pattern: 'artifacts-*' + merge-multiple: true + continue-on-error: true + + # === INSTALL DEPENDENCIES === + # This section installs all required dependencies and tools for document generation. + # Downstream projects: Add any additional dependency installations here. + + - name: Setup Node.js + uses: actions/setup-node@v6 + with: + node-version: 'lts/*' + + - name: Setup dotnet + uses: actions/setup-dotnet@v5 + with: + dotnet-version: 9.x + + - name: Install npm dependencies + env: + PUPPETEER_SKIP_DOWNLOAD: "true" + run: npm install + + - name: Set browser path for Mermaid (Windows) + shell: pwsh + run: | + $chromePaths = @( + "C:\Program Files\Google\Chrome\Application\chrome.exe", + "C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" + ) + foreach ($path in $chromePaths) { + if (Test-Path $path) { + "PUPPETEER_EXECUTABLE_PATH=$path" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append + Write-Host "Set PUPPETEER_EXECUTABLE_PATH to $path" + break + } + } + + - name: Restore Tools + run: dotnet tool restore + + # === CAPTURE TOOL VERSIONS === + # This section captures the versions of all tools used in the build process. + # Downstream projects: Add any additional tools to capture here. + + - name: Capture tool versions for build-docs + shell: bash + run: | + mkdir -p artifacts + echo "Capturing tool versions..." + dotnet versionmark --capture --job-id "build-docs" \ + --output "artifacts/versionmark-build-docs.json" -- \ + dotnet git node npm pandoc weasyprint sarifmark sonarmark reqstream \ + buildmark versionmark reviewmark fileassert sysml2tools + echo "✓ Tool versions captured" + + # === PREPARE DOCUMENT OUTPUT === + # Creates the shared docs/generated/ folder that all document sections write PDFs into. + # This step is intentionally separate from the document sections so any individual + # section can be commented out without breaking the shared output directory. + + - name: Create documents output directory + shell: bash + run: mkdir -p docs/generated + + # === COMPILE BUILD NOTES === + # This section generates the Build Notes document. BuildMark and VersionMark self-validations + # run here to co-locate their evidence with the document that depends on their output. + # Pandoc converts the markdown to HTML, WeasyPrint renders the HTML to PDF, and FileAssert + # validates the outputs contain expected content. + # Downstream projects: Add any additional build notes steps here. + + - name: Create build notes output directories + shell: bash + run: mkdir -p docs/build_notes/generated + + - name: Run BuildMark self-validation + run: > + dotnet buildmark + --validate + --results artifacts/buildmark-self-validation.trx + + - name: Run VersionMark self-validation + run: > + dotnet versionmark + --validate + --results artifacts/versionmark-self-validation.trx + + - name: Generate Build Notes with BuildMark + shell: bash + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: > + dotnet buildmark + --build-version ${{ inputs.version }} + --report docs/build_notes/generated/build_notes.md + --report-depth 1 + + - name: Display Build Notes Report + shell: bash + run: | + echo "=== Build Notes Report ===" + cat docs/build_notes/generated/build_notes.md + + - name: Publish Tool Versions + shell: bash + run: | + echo "Publishing tool versions..." + dotnet versionmark --publish --report docs/build_notes/generated/versions.md --report-depth 1 \ + -- "artifacts/**/versionmark-*.json" + echo "✓ Tool versions published" + + - name: Display Tool Versions Report + shell: bash + run: | + echo "=== Tool Versions Report ===" + cat docs/build_notes/generated/versions.md + + - name: Generate Build Notes HTML with Pandoc + shell: bash + run: > + dotnet pandoc + --defaults docs/build_notes/definition.yaml + --filter node_modules/.bin/mermaid-filter.cmd + --metadata version="${{ inputs.version }}" + --metadata date="$(date +'%Y-%m-%d')" + --output docs/build_notes/generated/build_notes.html + + - name: Generate Build Notes PDF with WeasyPrint + run: > + dotnet weasyprint + --pdf-variant pdf/a-3u + docs/build_notes/generated/build_notes.html + "docs/generated/SysML2Workbench Build Notes.pdf" + + - name: Assert Build Notes Documents with FileAssert + run: > + dotnet fileassert + --results artifacts/fileassert-build-notes.trx + build-notes + + - name: Copy Build Notes report to docs/generated + shell: bash + run: cp docs/build_notes/generated/build_notes.md docs/generated/build_notes.md + + # === COMPILE CODE QUALITY REPORT === + # This section generates the Code Quality document. SarifMark and SonarMark self-validations + # run here to co-locate their evidence with the document that depends on their output. + # Pandoc converts the markdown to HTML, WeasyPrint renders the HTML to PDF, and FileAssert + # validates the outputs contain expected content. + # Downstream projects: Add any additional code quality steps here. + + - name: Create code quality output directory + shell: bash + run: mkdir -p docs/code_quality/generated + + - name: Run SarifMark self-validation + run: > + dotnet sarifmark + --validate + --results artifacts/sarifmark-self-validation.trx + + - name: Run SonarMark self-validation + run: > + dotnet sonarmark + --validate + --results artifacts/sonarmark-self-validation.trx + + - name: Generate CodeQL Quality Report with SarifMark + run: > + dotnet sarifmark + --sarif artifacts/csharp.sarif + --report docs/code_quality/generated/codeql-quality.md + --heading "SysML2Workbench CodeQL Analysis" + --report-depth 1 + + - name: Display CodeQL Quality Report + shell: bash + run: | + echo "=== CodeQL Quality Report ===" + cat docs/code_quality/generated/codeql-quality.md + + - name: Generate SonarCloud Quality Report + shell: bash + env: + SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} + run: > + dotnet sonarmark + --server https://sonarcloud.io + --project-key demaconsulting_SysML2Workbench + --branch ${{ github.ref_name }} + --token "$SONAR_TOKEN" + --report docs/code_quality/generated/sonar-quality.md + --report-depth 1 + + - name: Display SonarCloud Quality Report + shell: bash + run: | + echo "=== SonarCloud Quality Report ===" + cat docs/code_quality/generated/sonar-quality.md + + - name: Generate Code Quality HTML with Pandoc + shell: bash + run: > + dotnet pandoc + --defaults docs/code_quality/definition.yaml + --filter node_modules/.bin/mermaid-filter.cmd + --metadata version="${{ inputs.version }}" + --metadata date="$(date +'%Y-%m-%d')" + --output docs/code_quality/generated/quality.html + + - name: Generate Code Quality PDF with WeasyPrint + run: > + dotnet weasyprint + --pdf-variant pdf/a-3u + docs/code_quality/generated/quality.html + "docs/generated/SysML2Workbench Code Quality Report.pdf" + + - name: Assert Code Quality Documents with FileAssert + run: > + dotnet fileassert + --results artifacts/fileassert-code-quality.trx + code-quality + + # === COMPILE CODE REVIEW === + # This section generates the Code Review Plan and Report documents. ReviewMark + # self-validation runs here to co-locate its evidence with the documents that depend + # on its output. Pandoc converts the markdown to HTML, WeasyPrint renders the HTML to + # PDF, and FileAssert validates the outputs contain expected content. + # Downstream projects: Add any additional code review steps here. + + - name: Create code review output directories + shell: bash + run: mkdir -p docs/code_review_plan/generated docs/code_review_report/generated + + - name: Run ReviewMark self-validation + run: > + dotnet reviewmark + --validate + --results artifacts/reviewmark-self-validation.trx + + - name: Generate Review Plan and Review Report with ReviewMark + shell: bash + # TODO: Add --enforce once reviews branch is populated with review evidence PDFs and index.json + run: > + dotnet reviewmark + --plan docs/code_review_plan/generated/plan.md + --plan-depth 1 + --report docs/code_review_report/generated/report.md + --report-depth 1 + + - name: Display Review Plan + shell: bash + run: | + echo "=== Review Plan ===" + cat docs/code_review_plan/generated/plan.md + + - name: Display Review Report + shell: bash + run: | + echo "=== Review Report ===" + cat docs/code_review_report/generated/report.md + + - name: Generate Review Plan HTML with Pandoc + shell: bash + run: > + dotnet pandoc + --defaults docs/code_review_plan/definition.yaml + --filter node_modules/.bin/mermaid-filter.cmd + --metadata version="${{ inputs.version }}" + --metadata date="$(date +'%Y-%m-%d')" + --output docs/code_review_plan/generated/plan.html + + - name: Generate Review Plan PDF with WeasyPrint + run: > + dotnet weasyprint + --pdf-variant pdf/a-3u + docs/code_review_plan/generated/plan.html + "docs/generated/SysML2Workbench Code Review Plan.pdf" + + - name: Generate Review Report HTML with Pandoc + shell: bash + run: > + dotnet pandoc + --defaults docs/code_review_report/definition.yaml + --filter node_modules/.bin/mermaid-filter.cmd + --metadata version="${{ inputs.version }}" + --metadata date="$(date +'%Y-%m-%d')" + --output docs/code_review_report/generated/report.html + + - name: Generate Review Report PDF with WeasyPrint + run: > + dotnet weasyprint + --pdf-variant pdf/a-3u + docs/code_review_report/generated/report.html + "docs/generated/SysML2Workbench Code Review Report.pdf" + + - name: Assert Code Review Documents with FileAssert + run: > + dotnet fileassert + --results artifacts/fileassert-code-review.trx + code-review + + # === COMPILE DESIGN DOCUMENT === + # This section generates the Design document using Pandoc and WeasyPrint. + # FileAssert validates that the HTML and PDF outputs contain expected content. + # Downstream projects: Add any additional design document steps here. + + - name: Create design output directory + shell: bash + run: mkdir -p docs/design/generated + + - name: Run SysML2Tools self-validation + run: > + dotnet sysml2tools + --validate + --results artifacts/sysml2tools-self-validation.trx + + - name: Render Software Structure diagrams with SysML2Tools + shell: pwsh + run: > + dotnet sysml2tools render + --output docs/design/generated --format svg + 'docs/sysml2/model/**/*.sysml' + 'docs/sysml2/views/design-views.sysml' + + - name: Generate Design HTML with Pandoc + shell: bash + run: > + dotnet pandoc + --defaults docs/design/definition.yaml + --filter node_modules/.bin/mermaid-filter.cmd + --metadata version="${{ inputs.version }}" + --metadata date="$(date +'%Y-%m-%d')" + --output docs/design/generated/design.html + + - name: Generate Design PDF with WeasyPrint + run: > + dotnet weasyprint + --pdf-variant pdf/a-3u + docs/design/generated/design.html + "docs/generated/SysML2Workbench Software Design Document.pdf" + + - name: Assert Design Documents with FileAssert + run: > + dotnet fileassert + --results artifacts/fileassert-design.trx + design + + # === COMPILE VERIFICATION DOCUMENT === + # This section generates the Verification Design document using Pandoc and WeasyPrint. + # FileAssert validates that the HTML and PDF outputs contain expected content. + # Downstream projects: Add any additional verification document steps here. + + - name: Create verification output directory + shell: bash + run: mkdir -p docs/verification/generated + + - name: Generate Verification HTML with Pandoc + shell: bash + run: > + dotnet pandoc + --defaults docs/verification/definition.yaml + --filter node_modules/.bin/mermaid-filter.cmd + --metadata version="${{ inputs.version }}" + --metadata date="$(date +'%Y-%m-%d')" + --output docs/verification/generated/verification.html + + - name: Generate Verification PDF with WeasyPrint + run: > + dotnet weasyprint + --pdf-variant pdf/a-3u + docs/verification/generated/verification.html + "docs/generated/SysML2Workbench Verification Design Document.pdf" + + - name: Assert Verification Documents with FileAssert + run: > + dotnet fileassert + --results artifacts/fileassert-verification.trx + verification + + # === COMPILE USER GUIDE === + # This section generates the User Guide document using Pandoc and WeasyPrint. + # FileAssert validates that the HTML and PDF outputs contain expected content. + # Downstream projects: Add any additional user guide steps here. + + - name: Create user guide output directory + shell: bash + run: mkdir -p docs/user_guide/generated + + - name: Generate User Guide HTML with Pandoc + shell: bash + run: > + dotnet pandoc + --defaults docs/user_guide/definition.yaml + --filter node_modules/.bin/mermaid-filter.cmd + --metadata version="${{ inputs.version }}" + --metadata date="$(date +'%Y-%m-%d')" + --output docs/user_guide/generated/user_guide.html + + - name: Generate User Guide PDF with WeasyPrint + run: > + dotnet weasyprint + --pdf-variant pdf/a-3u + docs/user_guide/generated/user_guide.html + "docs/generated/SysML2Workbench User Guide.pdf" + + - name: Assert User Guide Documents with FileAssert + run: > + dotnet fileassert + --results artifacts/fileassert-user-guide.trx + user-guide + + # === FILEASSERT SELF-VALIDATION === + # By this point Pandoc and WeasyPrint have each produced several validated documents + # (Build Notes, Code Quality, Review Plan, Review Report, Design, Verification, User + # Guide), providing strong OTS evidence for both tools before ReqStream runs. FileAssert + # self-validation confirms the assertion tool itself is operational. + # Downstream projects: Add any additional FileAssert self-validation steps here. + + - name: Run FileAssert self-validation + run: > + dotnet fileassert + --validate + --results artifacts/fileassert-self-validation.trx + + # === COMPILE REQUIREMENTS AND TRACE MATRIX === + # This section generates the Requirements and Trace Matrix documents. ReqStream + # self-validation runs here, then ReqStream --enforce consumes all previously generated + # TRX evidence (including FileAssert results for Pandoc, WeasyPrint, and FileAssert OTS + # requirements). Pandoc and WeasyPrint compile the final documents, and FileAssert + # validates their outputs. These final assertions do not contribute to OTS evidence but + # confirm the requirements pipeline produced well-formed documents. + # Downstream projects: Add any additional requirements steps here. + + - name: Create requirements output directories + shell: bash + run: mkdir -p docs/requirements_doc/generated docs/requirements_report/generated + + - name: Run ReqStream self-validation + run: > + dotnet reqstream + --validate + --results artifacts/reqstream-self-validation.trx + + - name: Generate Requirements Report, Justifications, and Trace Matrix + run: > + dotnet reqstream + --requirements requirements.yaml + --tests "artifacts/**/*.trx" + --report docs/requirements_doc/generated/requirements.md + --justifications docs/requirements_doc/generated/justifications.md + --matrix docs/requirements_report/generated/trace_matrix.md + --enforce + + - name: Generate Requirements HTML with Pandoc + shell: bash + run: > + dotnet pandoc + --defaults docs/requirements_doc/definition.yaml + --filter node_modules/.bin/mermaid-filter.cmd + --metadata version="${{ inputs.version }}" + --metadata date="$(date +'%Y-%m-%d')" + --output docs/requirements_doc/generated/requirements.html + + - name: Generate Requirements PDF with WeasyPrint + run: > + dotnet weasyprint + --pdf-variant pdf/a-3u + docs/requirements_doc/generated/requirements.html + "docs/generated/SysML2Workbench Requirements Document.pdf" + + - name: Generate Trace Matrix HTML with Pandoc + shell: bash + run: > + dotnet pandoc + --defaults docs/requirements_report/definition.yaml + --filter node_modules/.bin/mermaid-filter.cmd + --metadata version="${{ inputs.version }}" + --metadata date="$(date +'%Y-%m-%d')" + --output docs/requirements_report/generated/trace_matrix.html + + - name: Generate Trace Matrix PDF with WeasyPrint + run: > + dotnet weasyprint + --pdf-variant pdf/a-3u + docs/requirements_report/generated/trace_matrix.html + "docs/generated/SysML2Workbench Trace Matrix.pdf" + + - name: Assert Requirements Documents with FileAssert + run: > + dotnet fileassert + --results artifacts/fileassert-requirements.trx + requirements + + # === UPLOAD ARTIFACTS === + # This section uploads all generated documentation artifacts. + # Downstream projects: Add any additional artifact uploads here. + + - name: Upload documentation + uses: actions/upload-artifact@v7 + with: + name: documents + path: docs/generated/* diff --git a/.github/workflows/build_on_push.yaml b/.github/workflows/build_on_push.yaml new file mode 100644 index 0000000..344b21a --- /dev/null +++ b/.github/workflows/build_on_push.yaml @@ -0,0 +1,22 @@ +--- +name: Build on Push + +on: + push: + workflow_dispatch: + schedule: + - cron: '0 17 * * 1' # 5PM UTC every Monday + +jobs: + build: + name: Build + permissions: + actions: read + contents: read + pull-requests: write + security-events: write + uses: ./.github/workflows/build.yaml + with: + version: 0.0.0-run.${{ github.run_number }} + secrets: + SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml new file mode 100644 index 0000000..52ddcc9 --- /dev/null +++ b/.github/workflows/release.yaml @@ -0,0 +1,71 @@ +--- +name: Release + +on: + workflow_dispatch: + inputs: + version: + description: 'Release version (1.0.0)' + required: true + type: string + publish: + description: 'Publish type' + required: true + type: choice + options: + - none + - release + +jobs: + # Calls the reusable build workflow to build, test, package, and generate + # documentation for the release version. + build: + name: Build + permissions: + actions: read + contents: read + pull-requests: write + security-events: write + uses: ./.github/workflows/build.yaml + with: + version: ${{ inputs.version }} + secrets: + SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} + + # Cuts and publishes the release, creating a GitHub release with the cross-platform + # zip archives, the Windows MSI installer, and the generated documents. + release: + name: Release + runs-on: ubuntu-latest + needs: build + permissions: + contents: write + + steps: + - name: Download zip package artifacts + uses: actions/download-artifact@v8 + with: + path: artifacts + pattern: 'package-zip-*' + merge-multiple: true + + - name: Download MSI package artifact + uses: actions/download-artifact@v8 + with: + name: package-msi + path: artifacts + + - name: Download documents artifact + uses: actions/download-artifact@v8 + with: + name: documents + path: artifacts + + - name: Create GitHub Release + if: inputs.publish == 'release' + uses: ncipollo/release-action@v1 + with: + tag: ${{ inputs.version }} + artifacts: artifacts/* + bodyFile: artifacts/build_notes.md + generateReleaseNotes: false diff --git a/.gitignore b/.gitignore index cf26c37..5f01e82 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,8 @@ bin/ obj/ artifacts/ +publish/ +package/ # .NET *.user diff --git a/.versionmark.yaml b/.versionmark.yaml index 4cfe18f..807acc6 100644 --- a/.versionmark.yaml +++ b/.versionmark.yaml @@ -22,6 +22,11 @@ tools: command: npm --version regex: (?\d+\.\d+\.\d+) + # SonarScanner for .NET (from dotnet tool list) + dotnet-sonarscanner: + command: dotnet tool list + regex: (?i)dotnet-sonarscanner\s+(?\d+\.\d+\.\d+(?:-[a-zA-Z0-9.]+)?) + # Pandoc (DemaConsulting.PandocTool from dotnet tool list) pandoc: command: dotnet tool list diff --git a/Icon.ico b/Icon.ico new file mode 100644 index 0000000..5321bff Binary files /dev/null and b/Icon.ico differ diff --git a/Icon.png b/Icon.png new file mode 100644 index 0000000..fe8a0ae Binary files /dev/null and b/Icon.png differ diff --git a/docs/code_quality/definition.yaml b/docs/code_quality/definition.yaml index d6ec857..fed5f02 100644 --- a/docs/code_quality/definition.yaml +++ b/docs/code_quality/definition.yaml @@ -5,6 +5,8 @@ resource-path: input-files: - docs/code_quality/title.txt - docs/code_quality/introduction.md + - docs/code_quality/generated/codeql-quality.md + - docs/code_quality/generated/sonar-quality.md template: template.html table-of-contents: true number-sections: true diff --git a/docs/design/definition.yaml b/docs/design/definition.yaml new file mode 100644 index 0000000..0cb7423 --- /dev/null +++ b/docs/design/definition.yaml @@ -0,0 +1,39 @@ +--- +resource-path: + - docs/design + - docs/design/sysml2-workbench + - docs/design/ots + - docs/template + +input-files: + - docs/design/title.txt + - docs/design/introduction.md + - docs/design/sysml2-workbench.md + - docs/design/sysml2-workbench/app-shell-subsystem.md + - docs/design/sysml2-workbench/app-shell-subsystem/main-window-shell.md + - docs/design/sysml2-workbench/workspace-subsystem.md + - docs/design/sysml2-workbench/workspace-subsystem/workspace-model.md + - docs/design/sysml2-workbench/workspace-subsystem/file-watcher.md + - docs/design/sysml2-workbench/workspace-subsystem/diagnostics-aggregator.md + - docs/design/sysml2-workbench/view-catalog-subsystem.md + - docs/design/sysml2-workbench/view-catalog-subsystem/view-catalog-presenter.md + - docs/design/sysml2-workbench/view-builder-subsystem.md + - docs/design/sysml2-workbench/view-builder-subsystem/view-definition-model.md + - docs/design/sysml2-workbench/view-builder-subsystem/sysml-snippet-generator.md + - docs/design/sysml2-workbench/layout-rendering-subsystem.md + - docs/design/sysml2-workbench/layout-rendering-subsystem/layout-invoker.md + - docs/design/sysml2-workbench/layout-rendering-subsystem/svg-canvas-host.md + - docs/design/sysml2-workbench/diagnostics-panel-subsystem.md + - docs/design/sysml2-workbench/diagnostics-panel-subsystem/diagnostics-list-view.md + - docs/design/sysml2-workbench/logging-subsystem.md + - docs/design/sysml2-workbench/logging-subsystem/rolling-file-logger.md + - docs/design/ots.md + - docs/design/ots/avalonia.md + - docs/design/ots/communitytoolkit-mvvm.md + - docs/design/ots/dock.md + - docs/design/ots/rendering.md + - docs/design/ots/sysml2-tools.md + - docs/design/ots/xunit.md +template: template.html +table-of-contents: true +number-sections: true diff --git a/docs/design/title.txt b/docs/design/title.txt new file mode 100644 index 0000000..dd34fa4 --- /dev/null +++ b/docs/design/title.txt @@ -0,0 +1,14 @@ +--- +title: "SysML2Workbench Software Design Document" +subtitle: "Cross-platform desktop viewer and IDE for SysML v2 models" +author: "DEMA Consulting" +description: "Software Design Document for SysML2Workbench" +lang: en-US +keywords: + - Design + - Architecture + - .NET + - Avalonia + - SysML v2 + - SysML2Tools +--- diff --git a/docs/reqstream/ots/avalonia.yaml b/docs/reqstream/ots/avalonia.yaml index 633f536..c05b90d 100644 --- a/docs/reqstream/ots/avalonia.yaml +++ b/docs/reqstream/ots/avalonia.yaml @@ -9,11 +9,11 @@ sections: justification: | Avalonia provides the cross-platform desktop UI surface required by the product's Windows, Linux, and macOS scope. tests: - - 'AvaloniaTests.Startup_HostsDesktopShellControls' + - 'Startup_HostsDesktopShellControls' - id: 'Avalonia-HostInteractiveDiagramSurface' title: 'The SysML2Workbench shall use Avalonia to host the interactive SVG diagram surface and supporting workspace and diagnostics panels.' justification: | The workbench depends on Avalonia to compose the major UI regions around the rendered SVG viewer. tests: - - 'AvaloniaTests.MainWindow_HostsDiagramAndDiagnosticsPanels' + - 'MainWindow_HostsDiagramAndDiagnosticsPanels' diff --git a/docs/reqstream/ots/communitytoolkit-mvvm.yaml b/docs/reqstream/ots/communitytoolkit-mvvm.yaml index 37e8bf8..c4965ff 100644 --- a/docs/reqstream/ots/communitytoolkit-mvvm.yaml +++ b/docs/reqstream/ots/communitytoolkit-mvvm.yaml @@ -9,11 +9,11 @@ sections: justification: | The Dock panel view models rely on CommunityToolkit.Mvvm to generate bindable properties and change notification without hand-written boilerplate. tests: - - 'DockTests.CreateLayout_ComposesFourPanelDockables' + - 'CreateLayout_ComposesFourPanelDockables' - id: 'CommunityToolkitMvvm-NotifySelectionChanges' title: 'The SysML2Workbench shall use CommunityToolkit.Mvvm-generated partial change handlers to react to panel selection changes and refresh the diagram.' justification: | Selecting a predefined view must update the diagram surface, which depends on the generated OnChanged partial method being invoked. tests: - - 'AvaloniaTests.MainWindow_HostsDiagramAndDiagnosticsPanels' + - 'MainWindow_HostsDiagramAndDiagnosticsPanels' diff --git a/docs/reqstream/ots/dock.yaml b/docs/reqstream/ots/dock.yaml index 3fb2679..c57e681 100644 --- a/docs/reqstream/ots/dock.yaml +++ b/docs/reqstream/ots/dock.yaml @@ -9,27 +9,27 @@ sections: justification: | Dock provides the panel-docking layout engine required to replace the fixed four-region layout with one users can resize, float, and close. tests: - - 'DockTests.CreateLayout_ComposesFourPanelDockables' + - 'CreateLayout_ComposesFourPanelDockables' - id: 'Dock-HostLayoutInDockControl' title: 'The SysML2Workbench shall use Dock.Avalonia''s DockControl to host the composed panel layout inside the main window.' justification: | DockControl is the real Avalonia control that renders and manages the composed layout at runtime. tests: - - 'DockTests.DockControl_HostsWorkbenchLayout' + - 'DockControl_HostsWorkbenchLayout' - id: 'Dock-RestoreClosedTool' title: 'The SysML2Workbench shall let a user restore a closed Dock tool panel to its original dock via a View menu, reusing the panel''s existing view model instance.' justification: | Dock's own chrome lets a user close a Tool panel, but without a restore mechanism the panel would be permanently lost for the rest of the session; a View menu backed by Dock's HideToolsOnClose/RestoreDockable pattern lets a closed panel be brought back without losing its in-progress state. tests: - - 'DockTests.RestoreDockable_ReopensClosedToolInOriginalDock' + - 'RestoreDockable_ReopensClosedToolInOriginalDock' - id: 'Dock-PersistEmptyDocumentArea' title: 'The SysML2Workbench shall keep the diagram document area visibly present in the layout even when zero diagram tabs are open, using Dock''s IsCollapsable flag.' justification: | Diagram documents have no restore path once closed (unlike Tool panels), so the diagram document area must remain a first-class, always-present part of the layout at zero open tabs rather than collapsing/disappearing, which would otherwise create a dead end once the last diagram tab closed. tests: - - 'DockTests.DocumentDock_StaysInLayoutTree_AfterLastDocumentCloses' - - 'DockTests.AddDockable_And_CloseDockable_DynamicallyManageDiagramDocuments' - - 'DockTests.FocusedDockableChanged_FiresForActiveDockableChangesOnDiagramDocuments' + - 'DocumentDock_StaysInLayoutTree_AfterLastDocumentCloses' + - 'AddDockable_And_CloseDockable_DynamicallyManageDiagramDocuments' + - 'FocusedDockableChanged_FiresForActiveDockableChangesOnDiagramDocuments' diff --git a/docs/reqstream/ots/rendering.yaml b/docs/reqstream/ots/rendering.yaml index 35dfcc2..d44cd79 100644 --- a/docs/reqstream/ots/rendering.yaml +++ b/docs/reqstream/ots/rendering.yaml @@ -9,11 +9,11 @@ sections: justification: | The architecture reuses the mature rendering package so the workbench can focus on desktop interaction instead of implementing a new renderer. tests: - - 'RenderingTests.RenderLayout_ProducesSvgDocument' + - 'RenderLayout_ProducesSvgDocument' - id: 'Rendering-PreserveDiagramPrimitives' title: 'The SysML2Workbench shall use DemaConsulting.Rendering output that preserves the diagram primitives needed for interactive viewing in the shell.' justification: | Rendered diagrams must retain the expected diagram content and structure when displayed in the desktop SVG canvas. tests: - - 'RenderingTests.RenderLayout_PreservesDiagramPrimitives' + - 'RenderLayout_PreservesDiagramPrimitives' diff --git a/docs/reqstream/ots/sysml2-tools.yaml b/docs/reqstream/ots/sysml2-tools.yaml index 8375e46..5795bc5 100644 --- a/docs/reqstream/ots/sysml2-tools.yaml +++ b/docs/reqstream/ots/sysml2-tools.yaml @@ -9,11 +9,11 @@ sections: justification: | SysML2Workbench is intentionally a thin shell over the published SysML2Tools libraries instead of reimplementing parsing and semantic resolution. tests: - - 'SysML2ToolsTests.LoadWorkspaceModel_ParsesAndResolvesImports' + - 'LoadWorkspaceModel_ParsesAndResolvesImports' - id: 'SysML2Tools-GenerateViewLayouts' title: 'The SysML2Workbench shall use SysML2Tools to generate layout data for supported predefined and custom views.' justification: | The product depends on the existing SysML2Tools layout strategies to produce diagram structure for rendering. tests: - - 'SysML2ToolsTests.RenderView_GeneratesLayoutGraph' + - 'RenderView_GeneratesLayoutGraph' diff --git a/docs/reqstream/ots/xunit.yaml b/docs/reqstream/ots/xunit.yaml index 5ccc218..d8cf83e 100644 --- a/docs/reqstream/ots/xunit.yaml +++ b/docs/reqstream/ots/xunit.yaml @@ -9,11 +9,11 @@ sections: justification: | The repository's compliance workflow needs a test framework that can run the automated evidence linked from requirements. tests: - - 'XUnitTests.RunVerificationSuite_ReportsPassingResults' + - 'RunVerificationSuite_ReportsPassingResults' - id: 'XUnit-ProvideTraceableTestEvidence' title: 'The SysML2Workbench repository shall use xUnit test results as traceable evidence for ReqStream-linked requirement verification.' justification: | ReqStream traceability depends on consistent automated test method names and pass/fail results from the repository's verification framework. tests: - - 'XUnitTests.GenerateResults_ProvideReqStreamEvidence' + - 'GenerateResults_ProvideReqStreamEvidence' diff --git a/docs/reqstream/sysml2-workbench.yaml b/docs/reqstream/sysml2-workbench.yaml index dad2c79..26bb536 100644 --- a/docs/reqstream/sysml2-workbench.yaml +++ b/docs/reqstream/sysml2-workbench.yaml @@ -10,7 +10,7 @@ sections: - 'SysML2Workbench-WorkspaceSubsystem-ManageWorkspace' - 'SysML2Workbench-WorkspaceSubsystem-RefreshWorkspaceState' tests: - - 'SysML2WorkbenchTests.OpenWorkspace_LoadsAndRefreshesWorkspace' + - 'OpenWorkspace_LoadsAndRefreshesWorkspace' - id: 'SysML2Workbench-BrowsePredefinedViews' title: 'The SysML2Workbench shall let users browse supported predefined SysML views from the loaded model and render the selected view in the desktop shell.' @@ -21,7 +21,7 @@ sections: - 'SysML2Workbench-LayoutRenderingSubsystem-RenderSelectedView' - 'SysML2Workbench-AppShellSubsystem-PresentSelectedView' tests: - - 'SysML2WorkbenchTests.SelectPredefinedView_RendersDiagram' + - 'SelectPredefinedView_RendersDiagram' - id: 'SysML2Workbench-AuthorCustomViews' title: 'The SysML2Workbench shall let users build ad hoc custom views, preview them, and export equivalent SysML view text for promotion into model files.' @@ -33,7 +33,7 @@ sections: - 'SysML2Workbench-LayoutRenderingSubsystem-RenderCustomView' - 'SysML2Workbench-AppShellSubsystem-HostCustomViewWorkflow' tests: - - 'SysML2WorkbenchTests.BuildCustomView_PreviewsAndExportsSnippet' + - 'BuildCustomView_PreviewsAndExportsSnippet' - id: 'SysML2Workbench-PresentWorkspaceDiagnostics' title: 'The SysML2Workbench shall collect parser and reference-resolution diagnostics for the whole workspace and present them in a dedicated diagnostics panel.' @@ -43,7 +43,7 @@ sections: - 'SysML2Workbench-WorkspaceSubsystem-AggregateWorkspaceDiagnostics' - 'SysML2Workbench-DiagnosticsPanelSubsystem-DisplayWorkspaceDiagnostics' tests: - - 'SysML2WorkbenchTests.OpenWorkspace_ShowsWorkspaceDiagnostics' + - 'OpenWorkspace_ShowsWorkspaceDiagnostics' - id: 'SysML2Workbench-OperateAsDesktopShell' title: 'The SysML2Workbench shall provide a cross-platform desktop shell with local rolling logs for navigating workspaces, rendered diagrams, and diagnostics during a user session.' @@ -53,4 +53,4 @@ sections: - 'SysML2Workbench-LoggingSubsystem-PersistOperationalEvents' - 'SysML2Workbench-AppShellSubsystem-CoordinateSessionWorkspace' tests: - - 'SysML2WorkbenchTests.StartSession_OpensShellAndWritesOperationalLogs' + - 'StartSession_OpensShellAndWritesOperationalLogs' diff --git a/docs/reqstream/sysml2-workbench/app-shell-subsystem.yaml b/docs/reqstream/sysml2-workbench/app-shell-subsystem.yaml index b1b5d79..d149ccc 100644 --- a/docs/reqstream/sysml2-workbench/app-shell-subsystem.yaml +++ b/docs/reqstream/sysml2-workbench/app-shell-subsystem.yaml @@ -12,7 +12,7 @@ sections: - 'SysML2Workbench-AppShellSubsystem-MainWindowShell-ArrangePrimaryRegions' - 'SysML2Workbench-AppShellSubsystem-MainWindowShell-ManageViewTabs' tests: - - 'AppShellSubsystemTests.Startup_ShowsWorkspaceDiagramAndDiagnosticsRegions' + - 'Startup_ShowsWorkspaceDiagramAndDiagnosticsRegions' - id: 'SysML2Workbench-AppShellSubsystem-CoordinateSessionWorkspace' title: 'The AppShellSubsystem shall coordinate active workspace, view-selection, custom-view, and diagnostics state across the main window session.' @@ -21,7 +21,7 @@ sections: children: - 'SysML2Workbench-AppShellSubsystem-MainWindowShell-SynchronizeSessionState' tests: - - 'AppShellSubsystemTests.SessionChanges_SynchronizeShellState' + - 'SessionChanges_SynchronizeShellState' - id: 'SysML2Workbench-AppShellSubsystem-HostCustomViewWorkflow' title: 'The AppShellSubsystem shall expose commands and surfaces that let users preview and export custom views without leaving the main window.' @@ -31,4 +31,4 @@ sections: - 'SysML2Workbench-AppShellSubsystem-MainWindowShell-ArrangePrimaryRegions' - 'SysML2Workbench-AppShellSubsystem-MainWindowShell-SynchronizeSessionState' tests: - - 'AppShellSubsystemTests.CustomViewWorkflow_PreviewsAndExportsFromShell' + - 'CustomViewWorkflow_PreviewsAndExportsFromShell' diff --git a/docs/reqstream/sysml2-workbench/app-shell-subsystem/main-window-shell.yaml b/docs/reqstream/sysml2-workbench/app-shell-subsystem/main-window-shell.yaml index 2bd76b0..55170bd 100644 --- a/docs/reqstream/sysml2-workbench/app-shell-subsystem/main-window-shell.yaml +++ b/docs/reqstream/sysml2-workbench/app-shell-subsystem/main-window-shell.yaml @@ -11,25 +11,25 @@ sections: justification: | The shell unit is responsible for turning the subsystem's capabilities into a usable desktop layout. tests: - - 'MainWindowShellTests.Startup_ArrangesPrimaryWorkspaceAndDiagramRegions' + - 'Startup_ArrangesPrimaryWorkspaceAndDiagramRegions' - id: 'SysML2Workbench-AppShellSubsystem-MainWindowShell-ManageViewTabs' title: 'The MainWindowShell shall manage tabbed view presentation for rendered diagrams during a user session.' justification: | The architecture calls out tabbed views as part of the desktop shell experience, including multiple independent diagram tabs, predefined-view tab duplicate-avoidance/focus, custom-view-preview in-place-update-or-new-tab semantics, and tab close/active-tab reassignment. tests: - - 'MainWindowShellTests.OpenViews_ManagesTabbedPresentation' - - 'MainWindowShellTests.PreviewCustomView_WhenActiveTabIsCustomPreview_UpdatesInPlace' - - 'MainWindowShellTests.PreviewCustomView_WhenActiveTabIsPredefinedView_OpensNewTab' - - 'MainWindowShellTests.PreviewCustomView_WithNoTabsOpen_OpensNewTab' - - 'MainWindowShellTests.OpenNewCustomPreviewTab_OpensEmptyActiveTab_AndSubsequentPreviewUpdatesIt' - - 'MainWindowShellTests.CloseDiagramTab_RemovesTab_AndReassignsActiveTab' - - 'MainWindowShellTests.NotifyActiveDiagramTab_UnknownId_IsIgnored' - - 'MainWindowShellTests.SelectPredefinedView_TabsHaveIndependentCanvases' + - 'OpenViews_ManagesTabbedPresentation' + - 'PreviewCustomView_WhenActiveTabIsCustomPreview_UpdatesInPlace' + - 'PreviewCustomView_WhenActiveTabIsPredefinedView_OpensNewTab' + - 'PreviewCustomView_WithNoTabsOpen_OpensNewTab' + - 'OpenNewCustomPreviewTab_OpensEmptyActiveTab_AndSubsequentPreviewUpdatesIt' + - 'CloseDiagramTab_RemovesTab_AndReassignsActiveTab' + - 'NotifyActiveDiagramTab_UnknownId_IsIgnored' + - 'SelectPredefinedView_TabsHaveIndependentCanvases' - id: 'SysML2Workbench-AppShellSubsystem-MainWindowShell-SynchronizeSessionState' title: 'The MainWindowShell shall synchronize active workspace, view selection, custom-view state, and diagnostics across the visible shell regions.' justification: | Users need shell regions to stay in sync as they browse the workspace and interact with rendered or custom views. tests: - - 'MainWindowShellTests.SessionStateChanges_SynchronizeVisibleRegions' + - 'SessionStateChanges_SynchronizeVisibleRegions' diff --git a/docs/reqstream/sysml2-workbench/diagnostics-panel-subsystem.yaml b/docs/reqstream/sysml2-workbench/diagnostics-panel-subsystem.yaml index 3614b6c..c7922dd 100644 --- a/docs/reqstream/sysml2-workbench/diagnostics-panel-subsystem.yaml +++ b/docs/reqstream/sysml2-workbench/diagnostics-panel-subsystem.yaml @@ -11,7 +11,7 @@ sections: children: - 'SysML2Workbench-DiagnosticsPanelSubsystem-DiagnosticsListView-DisplayDiagnosticDetails' tests: - - 'DiagnosticsPanelSubsystemTests.BindDiagnostics_ShowsDiagnosticDetails' + - 'BindDiagnostics_ShowsDiagnosticDetails' - id: 'SysML2Workbench-DiagnosticsPanelSubsystem-RefreshDisplayedDiagnostics' title: 'The DiagnosticsPanelSubsystem shall refresh the displayed diagnostic list when the aggregated workspace diagnostics change.' @@ -20,4 +20,4 @@ sections: children: - 'SysML2Workbench-DiagnosticsPanelSubsystem-DiagnosticsListView-RefreshDiagnosticCollection' tests: - - 'DiagnosticsPanelSubsystemTests.DiagnosticsChanged_RefreshesList' + - 'DiagnosticsChanged_RefreshesList' diff --git a/docs/reqstream/sysml2-workbench/diagnostics-panel-subsystem/diagnostics-list-view.yaml b/docs/reqstream/sysml2-workbench/diagnostics-panel-subsystem/diagnostics-list-view.yaml index 42151b5..6a8b114 100644 --- a/docs/reqstream/sysml2-workbench/diagnostics-panel-subsystem/diagnostics-list-view.yaml +++ b/docs/reqstream/sysml2-workbench/diagnostics-panel-subsystem/diagnostics-list-view.yaml @@ -11,11 +11,11 @@ sections: justification: | Users need enough structured detail in the diagnostics list to understand and act on workspace problems. tests: - - 'DiagnosticsListViewTests.BindDiagnostics_ShowsSeverityMessageAndLocation' + - 'BindDiagnostics_ShowsSeverityMessageAndLocation' - id: 'SysML2Workbench-DiagnosticsPanelSubsystem-DiagnosticsListView-RefreshDiagnosticCollection' title: 'The DiagnosticsListView shall refresh its displayed collection when workspace diagnostics change.' justification: | The live workspace model requires the UI list to update as diagnostics are added, removed, or reordered. tests: - - 'DiagnosticsListViewTests.DiagnosticsChanged_RefreshesVisibleList' + - 'DiagnosticsChanged_RefreshesVisibleList' diff --git a/docs/reqstream/sysml2-workbench/layout-rendering-subsystem.yaml b/docs/reqstream/sysml2-workbench/layout-rendering-subsystem.yaml index 555557a..c272453 100644 --- a/docs/reqstream/sysml2-workbench/layout-rendering-subsystem.yaml +++ b/docs/reqstream/sysml2-workbench/layout-rendering-subsystem.yaml @@ -12,7 +12,7 @@ sections: - 'SysML2Workbench-LayoutRenderingSubsystem-LayoutInvoker-BuildPredefinedViewLayout' - 'SysML2Workbench-LayoutRenderingSubsystem-SvgCanvasHost-DisplayRenderedSvg' tests: - - 'LayoutRenderingSubsystemTests.RenderPredefinedView_DisplaysSvgDiagram' + - 'RenderPredefinedView_DisplaysSvgDiagram' - id: 'SysML2Workbench-LayoutRenderingSubsystem-RenderCustomView' title: 'The LayoutRenderingSubsystem shall render GUI-defined custom views and support pan-and-zoom navigation over the resulting diagram.' @@ -22,4 +22,4 @@ sections: - 'SysML2Workbench-LayoutRenderingSubsystem-LayoutInvoker-BuildCustomViewLayout' - 'SysML2Workbench-LayoutRenderingSubsystem-SvgCanvasHost-SupportPanAndZoom' tests: - - 'LayoutRenderingSubsystemTests.RenderCustomView_SupportsPanAndZoom' + - 'RenderCustomView_SupportsPanAndZoom' diff --git a/docs/reqstream/sysml2-workbench/layout-rendering-subsystem/layout-invoker.yaml b/docs/reqstream/sysml2-workbench/layout-rendering-subsystem/layout-invoker.yaml index c6a9027..a2039cf 100644 --- a/docs/reqstream/sysml2-workbench/layout-rendering-subsystem/layout-invoker.yaml +++ b/docs/reqstream/sysml2-workbench/layout-rendering-subsystem/layout-invoker.yaml @@ -11,13 +11,13 @@ sections: justification: | Rendering predefined diagrams depends on translating the current model view into the layout engine's input and output contract. tests: - - 'LayoutInvokerTests.RenderPredefinedView_DisplaysSvgDiagram' + - 'RenderPredefinedView_DisplaysSvgDiagram' - id: 'SysML2Workbench-LayoutRenderingSubsystem-LayoutInvoker-BuildCustomViewLayout' title: 'The LayoutInvoker shall request layout data for a GUI-defined custom view using the same workspace model context as predefined views.' justification: | Custom views must be previewed through the same rendering pipeline as persisted model views to keep user results consistent. tests: - - 'LayoutInvokerTests.RenderCustomView_SupportsPanAndZoom' - - 'LayoutInvokerTests.RenderCustomView_ScopesOutputToSelectedTargetsOnly' - - 'LayoutInvokerTests.RenderCustomView_SameQualifiedNameTwoRecursionKinds_RendersWithoutError' + - 'RenderCustomView_SupportsPanAndZoom' + - 'RenderCustomView_ScopesOutputToSelectedTargetsOnly' + - 'RenderCustomView_SameQualifiedNameTwoRecursionKinds_RendersWithoutError' diff --git a/docs/reqstream/sysml2-workbench/layout-rendering-subsystem/svg-canvas-host.yaml b/docs/reqstream/sysml2-workbench/layout-rendering-subsystem/svg-canvas-host.yaml index b6afd04..d966001 100644 --- a/docs/reqstream/sysml2-workbench/layout-rendering-subsystem/svg-canvas-host.yaml +++ b/docs/reqstream/sysml2-workbench/layout-rendering-subsystem/svg-canvas-host.yaml @@ -11,11 +11,11 @@ sections: justification: | The diagram viewer is the user-facing result of the layout and rendering pipeline. tests: - - 'SvgCanvasHostTests.LoadSvgDocument_DisplaysDiagramCanvas' + - 'LoadSvgDocument_DisplaysDiagramCanvas' - id: 'SysML2Workbench-LayoutRenderingSubsystem-SvgCanvasHost-SupportPanAndZoom' title: 'The SvgCanvasHost shall support pan and zoom interaction over the displayed diagram.' justification: | Pan-and-zoom navigation is part of the defined Phase 0 scope for working with rendered diagrams. tests: - - 'SvgCanvasHostTests.UserInteraction_PansAndZoomsDiagram' + - 'UserInteraction_PansAndZoomsDiagram' diff --git a/docs/reqstream/sysml2-workbench/logging-subsystem.yaml b/docs/reqstream/sysml2-workbench/logging-subsystem.yaml index db385d9..bcd01cb 100644 --- a/docs/reqstream/sysml2-workbench/logging-subsystem.yaml +++ b/docs/reqstream/sysml2-workbench/logging-subsystem.yaml @@ -11,7 +11,7 @@ sections: children: - 'SysML2Workbench-LoggingSubsystem-RollingFileLogger-WriteTimestampedEntries' tests: - - 'LoggingSubsystemTests.LogEvent_WritesLocalEntry' + - 'LogEvent_WritesLocalEntry' - id: 'SysML2Workbench-LoggingSubsystem-RetainRecentLogHistory' title: 'The LoggingSubsystem shall retain recent operational history by rotating log files without unbounded growth.' @@ -20,4 +20,4 @@ sections: children: - 'SysML2Workbench-LoggingSubsystem-RollingFileLogger-RotateLogFiles' tests: - - 'LoggingSubsystemTests.LogGrowth_RotatesRetainedFiles' + - 'LogGrowth_RotatesRetainedFiles' diff --git a/docs/reqstream/sysml2-workbench/logging-subsystem/rolling-file-logger.yaml b/docs/reqstream/sysml2-workbench/logging-subsystem/rolling-file-logger.yaml index d570186..bb312f5 100644 --- a/docs/reqstream/sysml2-workbench/logging-subsystem/rolling-file-logger.yaml +++ b/docs/reqstream/sysml2-workbench/logging-subsystem/rolling-file-logger.yaml @@ -11,11 +11,11 @@ sections: justification: | Troubleshooting desktop sessions requires a readable local event history that can be attached to bug reports. tests: - - 'RollingFileLoggerTests.LogEvent_WritesTimestampedEntry' + - 'LogEvent_WritesTimestampedEntry' - id: 'SysML2Workbench-LoggingSubsystem-RollingFileLogger-RotateLogFiles' title: 'The RollingFileLogger shall rotate retained log files according to the configured retention policy.' justification: | The logger must keep recent history available without allowing the on-disk log footprint to grow indefinitely. tests: - - 'RollingFileLoggerTests.RetentionLimit_RotatesLogFiles' + - 'RetentionLimit_RotatesLogFiles' diff --git a/docs/reqstream/sysml2-workbench/platform-requirements.yaml b/docs/reqstream/sysml2-workbench/platform-requirements.yaml index 0b8a895..cb753fc 100644 --- a/docs/reqstream/sysml2-workbench/platform-requirements.yaml +++ b/docs/reqstream/sysml2-workbench/platform-requirements.yaml @@ -9,25 +9,25 @@ sections: justification: | Windows is an explicitly supported desktop target for the shared Avalonia shell and must be verifiable independently from other operating systems. tests: - - 'windows@SysML2WorkbenchTests.StartSession_OpensShellAndWritesOperationalLogs' + - 'windows@StartSession_OpensShellAndWritesOperationalLogs' - id: 'SysML2Workbench-Platform-Ubuntu' title: 'The SysML2Workbench shall run as a desktop application on Ubuntu Linux operating systems.' justification: | Linux desktop support is part of the project scope, and Ubuntu-based validation provides explicit evidence for that platform family. tests: - - 'ubuntu@SysML2WorkbenchTests.StartSession_OpensShellAndWritesOperationalLogs' + - 'ubuntu@StartSession_OpensShellAndWritesOperationalLogs' - id: 'SysML2Workbench-Platform-MacOS' title: 'The SysML2Workbench shall run as a desktop application on macOS operating systems.' justification: | macOS is one of the intended desktop targets for the Avalonia-based application and requires platform-specific verification evidence. tests: - - 'macos@SysML2WorkbenchTests.StartSession_OpensShellAndWritesOperationalLogs' + - 'macos@StartSession_OpensShellAndWritesOperationalLogs' - id: 'SysML2Workbench-Platform-DotNet9' title: 'The SysML2Workbench shall support the .NET 9.0 runtime.' justification: | The project is expected to run on modern .NET desktop runtimes, and explicit runtime requirements keep compatibility evidence separate from operating-system support evidence. tests: - - 'net9.0@SysML2WorkbenchTests.OpenWorkspace_LoadsAndRefreshesWorkspace' + - 'net9.0@OpenWorkspace_LoadsAndRefreshesWorkspace' diff --git a/docs/reqstream/sysml2-workbench/view-builder-subsystem.yaml b/docs/reqstream/sysml2-workbench/view-builder-subsystem.yaml index 727dc3d..6d51401 100644 --- a/docs/reqstream/sysml2-workbench/view-builder-subsystem.yaml +++ b/docs/reqstream/sysml2-workbench/view-builder-subsystem.yaml @@ -14,7 +14,7 @@ sections: - 'SysML2Workbench-ViewBuilderSubsystem-ViewDefinitionModel-StoreExposeRecursionAndFilter' - 'SysML2Workbench-ViewBuilderSubsystem-ViewDefinitionModel-ReportDefinitionReadiness' tests: - - 'ViewBuilderSubsystemTests.EditDefinition_TracksCustomViewInputs' + - 'EditDefinition_TracksCustomViewInputs' - id: 'SysML2Workbench-ViewBuilderSubsystem-GenerateCustomViewSnippet' title: 'The ViewBuilderSubsystem shall generate copy-pasteable SysML text from the current custom view definition.' @@ -25,4 +25,4 @@ sections: - 'SysML2Workbench-ViewBuilderSubsystem-SysmlSnippetGenerator-PreserveDefinitionSemantics' - 'SysML2Workbench-ViewBuilderSubsystem-SysmlSnippetGenerator-EmitRecursionKindForms' tests: - - 'ViewBuilderSubsystemTests.ExportDefinition_GeneratesSysmlSnippet' + - 'ExportDefinition_GeneratesSysmlSnippet' diff --git a/docs/reqstream/sysml2-workbench/view-builder-subsystem/sysml-snippet-generator.yaml b/docs/reqstream/sysml2-workbench/view-builder-subsystem/sysml-snippet-generator.yaml index a445a9d..28a219b 100644 --- a/docs/reqstream/sysml2-workbench/view-builder-subsystem/sysml-snippet-generator.yaml +++ b/docs/reqstream/sysml2-workbench/view-builder-subsystem/sysml-snippet-generator.yaml @@ -11,15 +11,15 @@ sections: justification: | The product uses generated standard SysML text as the persistence path for GUI-authored custom views. tests: - - 'SysmlSnippetGeneratorTests.ExportDefinition_EmitsSysmlViewSnippet' + - 'ExportDefinition_EmitsSysmlViewSnippet' - id: 'SysML2Workbench-ViewBuilderSubsystem-SysmlSnippetGenerator-PreserveDefinitionSemantics' title: 'The SysmlSnippetGenerator shall preserve the selected view kind, expose targets, and filter expression in the generated text.' justification: | Exported text must faithfully represent the current GUI definition so users can promote it into model files without manual reconstruction. tests: - - 'SysmlSnippetGeneratorTests.ExportDefinition_PreservesKindTargetsAndFilter' - - 'SysmlSnippetGeneratorTests.GenerateSnippet_SameQualifiedNameTwoRecursionKinds_EmitsBothExposeClauses' + - 'ExportDefinition_PreservesKindTargetsAndFilter' + - 'GenerateSnippet_SameQualifiedNameTwoRecursionKinds_EmitsBothExposeClauses' - id: 'SysML2Workbench-ViewBuilderSubsystem-SysmlSnippetGenerator-EmitRecursionKindForms' title: 'The SysmlSnippetGenerator shall emit the correct SysML expose textual form for each of the four recursion kinds and optional bracket filter.' @@ -28,4 +28,4 @@ sections: bracket-filter expression; exported text must use the exact textual form matching each target's selected kind and filter so it remains valid, semantically-correct SysML v2 syntax. tests: - - 'SysmlSnippetGeneratorTests.FormatExposeClause_EachRecursionKind_EmitsCorrectExposeStatement' + - 'FormatExposeClause_EachRecursionKind_EmitsCorrectExposeStatement' diff --git a/docs/reqstream/sysml2-workbench/view-builder-subsystem/view-definition-model.yaml b/docs/reqstream/sysml2-workbench/view-builder-subsystem/view-definition-model.yaml index b1637f2..54d3919 100644 --- a/docs/reqstream/sysml2-workbench/view-builder-subsystem/view-definition-model.yaml +++ b/docs/reqstream/sysml2-workbench/view-builder-subsystem/view-definition-model.yaml @@ -11,20 +11,20 @@ sections: justification: | The GUI builder needs a single source of truth for which type of diagram the user is constructing. tests: - - 'ViewDefinitionModelTests.ChangeViewKind_StoresCurrentSelection' + - 'ChangeViewKind_StoresCurrentSelection' - id: 'SysML2Workbench-ViewBuilderSubsystem-ViewDefinitionModel-StoreExposeTargets' title: 'The ViewDefinitionModel shall store one or more selected expose targets for the custom view definition.' justification: | The architecture explicitly supports multi-target expose semantics, so the unit must preserve multiple selected targets. tests: - - 'ViewDefinitionModelTests.AddExposeTarget_StoresMultipleExposeTargetsWithoutDuplicates' - - 'ViewDefinitionModelTests.RemoveExposeTarget_RemovesOnlyMatchingSelection' - - 'ViewDefinitionModelTests.RemoveExposeTarget_UnknownQualifiedName_IsNoOp' - - 'ViewDefinitionModelTests.RemoveExposeTarget_KnownQualifiedNameWrongRecursionKind_IsNoOp' - - 'ViewDefinitionModelTests.AddExposeTarget_ExactQualifiedNameAndKindTwice_IsNoOp' - - 'ViewDefinitionModelTests.AddExposeTarget_SameQualifiedNameDifferentRecursionKind_AddsBothSelections' - - 'ViewDefinitionModelTests.RemoveExposeTarget_OneOfTwoSameQualifiedNameSelections_LeavesOtherUntouched' + - 'AddExposeTarget_StoresMultipleExposeTargetsWithoutDuplicates' + - 'RemoveExposeTarget_RemovesOnlyMatchingSelection' + - 'RemoveExposeTarget_UnknownQualifiedName_IsNoOp' + - 'RemoveExposeTarget_KnownQualifiedNameWrongRecursionKind_IsNoOp' + - 'AddExposeTarget_ExactQualifiedNameAndKindTwice_IsNoOp' + - 'AddExposeTarget_SameQualifiedNameDifferentRecursionKind_AddsBothSelections' + - 'RemoveExposeTarget_OneOfTwoSameQualifiedNameSelections_LeavesOtherUntouched' - id: 'SysML2Workbench-ViewBuilderSubsystem-ViewDefinitionModel-StoreExposeRecursionAndFilter' title: 'The ViewDefinitionModel shall store an optional recursion kind and bracket-filter expression per expose target and reject bracket filters on non-recursive kinds.' @@ -33,17 +33,17 @@ sections: expression on the two recursive kinds; the builder must let users select a kind and filter per target and must flag combinations that are not valid SysML v2 syntax. tests: - - 'ViewDefinitionModelTests.SetExposeRecursionKind_ChangesSelectedTargetKind' - - 'ViewDefinitionModelTests.SetExposeRecursionKind_OneOfTwoSameQualifiedNameSelections_DoesNotAffectOther' - - 'ViewDefinitionModelTests.SetExposeRecursionKind_TargetKindAlreadyTakenBySibling_IsNoOp' - - 'ViewDefinitionModelTests.SetExposeBracketFilter_SetsAndClearsExpression' - - 'ViewDefinitionModelTests.ValidateAgainstWorkspace_ValidBracketFilterOnRecursiveTarget_ReturnsNoDiagnostics' - - 'ViewDefinitionModelTests.ValidateAgainstWorkspace_InvalidBracketFilterExpression_ReturnsDiagnostic' - - 'ViewDefinitionModelTests.ValidateAgainstWorkspace_BracketFilterOnNonRecursiveKind_ReturnsDiagnostic' + - 'SetExposeRecursionKind_ChangesSelectedTargetKind' + - 'SetExposeRecursionKind_OneOfTwoSameQualifiedNameSelections_DoesNotAffectOther' + - 'SetExposeRecursionKind_TargetKindAlreadyTakenBySibling_IsNoOp' + - 'SetExposeBracketFilter_SetsAndClearsExpression' + - 'ValidateAgainstWorkspace_ValidBracketFilterOnRecursiveTarget_ReturnsNoDiagnostics' + - 'ValidateAgainstWorkspace_InvalidBracketFilterExpression_ReturnsDiagnostic' + - 'ValidateAgainstWorkspace_BracketFilterOnNonRecursiveKind_ReturnsDiagnostic' - id: 'SysML2Workbench-ViewBuilderSubsystem-ViewDefinitionModel-ReportDefinitionReadiness' title: 'The ViewDefinitionModel shall report whether the current custom view definition contains enough information to render or export.' justification: | The shell and snippet generator need to know when a user's current selections form a usable custom view definition. tests: - - 'ViewDefinitionModelTests.DefinitionState_ReportsRenderAndExportReadiness' + - 'DefinitionState_ReportsRenderAndExportReadiness' diff --git a/docs/reqstream/sysml2-workbench/view-catalog-subsystem.yaml b/docs/reqstream/sysml2-workbench/view-catalog-subsystem.yaml index 849f8fe..155aa8e 100644 --- a/docs/reqstream/sysml2-workbench/view-catalog-subsystem.yaml +++ b/docs/reqstream/sysml2-workbench/view-catalog-subsystem.yaml @@ -12,7 +12,7 @@ sections: - 'SysML2Workbench-ViewCatalogSubsystem-ViewCatalogPresenter-ListDefinedViews' - 'SysML2Workbench-ViewCatalogSubsystem-ViewCatalogPresenter-DescribeViewKinds' tests: - - 'ViewCatalogSubsystemTests.LoadedModel_ListsSupportedViews' + - 'LoadedModel_ListsSupportedViews' - id: 'SysML2Workbench-ViewCatalogSubsystem-SignalActiveViewSelection' title: 'The ViewCatalogSubsystem shall publish the user-selected predefined view for downstream rendering and shell presentation.' @@ -21,4 +21,4 @@ sections: children: - 'SysML2Workbench-ViewCatalogSubsystem-ViewCatalogPresenter-TrackSelectedView' tests: - - 'ViewCatalogSubsystemTests.SelectView_PublishesActiveSelection' + - 'SelectView_PublishesActiveSelection' diff --git a/docs/reqstream/sysml2-workbench/view-catalog-subsystem/view-catalog-presenter.yaml b/docs/reqstream/sysml2-workbench/view-catalog-subsystem/view-catalog-presenter.yaml index 548ff0e..6e52088 100644 --- a/docs/reqstream/sysml2-workbench/view-catalog-subsystem/view-catalog-presenter.yaml +++ b/docs/reqstream/sysml2-workbench/view-catalog-subsystem/view-catalog-presenter.yaml @@ -11,18 +11,18 @@ sections: justification: | The presenter is the unit responsible for exposing the model's available view definitions to the UI. tests: - - 'ViewCatalogPresenterTests.LoadedModel_ListsSupportedViewDefinitions' + - 'LoadedModel_ListsSupportedViewDefinitions' - id: 'SysML2Workbench-ViewCatalogSubsystem-ViewCatalogPresenter-DescribeViewKinds' title: 'The ViewCatalogPresenter shall present each listed view with its view kind and display name.' justification: | Users need enough metadata in the catalog to choose the correct diagram before rendering it. tests: - - 'ViewCatalogPresenterTests.LoadedModel_ShowsViewKindAndDisplayName' + - 'LoadedModel_ShowsViewKindAndDisplayName' - id: 'SysML2Workbench-ViewCatalogSubsystem-ViewCatalogPresenter-TrackSelectedView' title: 'The ViewCatalogPresenter shall publish the currently selected predefined view for downstream rendering.' justification: | Rendering begins from a single active catalog selection, so the presenter must expose that selection change. tests: - - 'ViewCatalogPresenterTests.SelectView_PublishesCurrentSelection' + - 'SelectView_PublishesCurrentSelection' diff --git a/docs/reqstream/sysml2-workbench/workspace-subsystem.yaml b/docs/reqstream/sysml2-workbench/workspace-subsystem.yaml index 4c23611..e40e1ec 100644 --- a/docs/reqstream/sysml2-workbench/workspace-subsystem.yaml +++ b/docs/reqstream/sysml2-workbench/workspace-subsystem.yaml @@ -12,7 +12,7 @@ sections: - 'SysML2Workbench-WorkspaceSubsystem-WorkspaceModel-MaintainWorkspaceTree' - 'SysML2Workbench-WorkspaceSubsystem-WorkspaceModel-ResolveWorkspaceInputs' tests: - - 'WorkspaceSubsystemTests.OpenWorkspace_BuildsWorkspaceState' + - 'OpenWorkspace_BuildsWorkspaceState' - id: 'SysML2Workbench-WorkspaceSubsystem-RefreshWorkspaceState' title: 'The WorkspaceSubsystem shall detect external workspace changes, update affected model state, and keep workspace diagnostics current for downstream UI consumers.' @@ -25,7 +25,7 @@ sections: - 'SysML2Workbench-WorkspaceSubsystem-DiagnosticsAggregator-CollectWorkspaceDiagnostics' - 'SysML2Workbench-WorkspaceSubsystem-DiagnosticsAggregator-PublishDeterministicDiagnostics' tests: - - 'WorkspaceSubsystemTests.ExternalChange_RefreshesWorkspaceState' + - 'ExternalChange_RefreshesWorkspaceState' - id: 'SysML2Workbench-WorkspaceSubsystem-AggregateWorkspaceDiagnostics' title: 'The WorkspaceSubsystem shall expose a unified set of workspace diagnostics suitable for display without requiring per-file inspection.' @@ -35,4 +35,4 @@ sections: - 'SysML2Workbench-WorkspaceSubsystem-DiagnosticsAggregator-CollectWorkspaceDiagnostics' - 'SysML2Workbench-WorkspaceSubsystem-DiagnosticsAggregator-PublishDeterministicDiagnostics' tests: - - 'WorkspaceSubsystemTests.OpenWorkspace_ProducesUnifiedDiagnostics' + - 'OpenWorkspace_ProducesUnifiedDiagnostics' diff --git a/docs/reqstream/sysml2-workbench/workspace-subsystem/diagnostics-aggregator.yaml b/docs/reqstream/sysml2-workbench/workspace-subsystem/diagnostics-aggregator.yaml index 38370e8..5b60c78 100644 --- a/docs/reqstream/sysml2-workbench/workspace-subsystem/diagnostics-aggregator.yaml +++ b/docs/reqstream/sysml2-workbench/workspace-subsystem/diagnostics-aggregator.yaml @@ -11,11 +11,11 @@ sections: justification: | The diagnostics panel depends on a unified diagnostic source instead of separate per-file error lists. tests: - - 'DiagnosticsAggregatorTests.WorkspaceState_CombinesAllFileDiagnostics' + - 'WorkspaceState_CombinesAllFileDiagnostics' - id: 'SysML2Workbench-WorkspaceSubsystem-DiagnosticsAggregator-PublishDeterministicDiagnostics' title: 'The DiagnosticsAggregator shall publish diagnostics in a deterministic order that preserves source location details for UI consumers.' justification: | Stable diagnostic ordering reduces UI churn during reloads and keeps source context available for future navigation features. tests: - - 'DiagnosticsAggregatorTests.WorkspaceState_PublishesDeterministicDiagnosticOrder' + - 'WorkspaceState_PublishesDeterministicDiagnosticOrder' diff --git a/docs/reqstream/sysml2-workbench/workspace-subsystem/file-watcher.yaml b/docs/reqstream/sysml2-workbench/workspace-subsystem/file-watcher.yaml index 200b99e..ba480d2 100644 --- a/docs/reqstream/sysml2-workbench/workspace-subsystem/file-watcher.yaml +++ b/docs/reqstream/sysml2-workbench/workspace-subsystem/file-watcher.yaml @@ -11,11 +11,11 @@ sections: justification: | Live workspace refresh is driven by external file-system activity, so the unit must observe all change types relevant to the open model set. tests: - - 'FileWatcherTests.ExternalFileChange_RaisesAffectedPathEvent' + - 'ExternalFileChange_RaisesAffectedPathEvent' - id: 'SysML2Workbench-WorkspaceSubsystem-FileWatcher-CoalesceReloadTriggers' title: 'The FileWatcher shall coalesce bursts of file-system notifications into reload triggers that identify the affected workspace paths.' justification: | Editors and source-control operations often emit multiple low-level events, and the workspace refresh pipeline needs stable, actionable reload requests. tests: - - 'FileWatcherTests.NotificationBurst_CoalescesIntoSingleReloadTrigger' + - 'NotificationBurst_CoalescesIntoSingleReloadTrigger' diff --git a/docs/reqstream/sysml2-workbench/workspace-subsystem/workspace-model.yaml b/docs/reqstream/sysml2-workbench/workspace-subsystem/workspace-model.yaml index 20254ca..726ab9f 100644 --- a/docs/reqstream/sysml2-workbench/workspace-subsystem/workspace-model.yaml +++ b/docs/reqstream/sysml2-workbench/workspace-subsystem/workspace-model.yaml @@ -11,18 +11,18 @@ sections: justification: | Users interact with a folder-based workspace, so the unit must keep the current file tree available to the rest of the application. tests: - - 'WorkspaceModelTests.OpenWorkspace_BuildsTrackedFileTree' + - 'OpenWorkspace_BuildsTrackedFileTree' - id: 'SysML2Workbench-WorkspaceSubsystem-WorkspaceModel-ResolveWorkspaceInputs' title: 'The WorkspaceModel shall determine the set of model files to load by combining workspace discovery rules with SysML import resolution.' justification: | The workbench must mirror the multi-file loading behavior users expect from existing SysML2Tools workflows. tests: - - 'WorkspaceModelTests.ResolveInputs_FindsDiscoveredAndImportedFiles' + - 'ResolveInputs_FindsDiscoveredAndImportedFiles' - id: 'SysML2Workbench-WorkspaceSubsystem-WorkspaceModel-TrackPerFileLoadState' title: 'The WorkspaceModel shall retain per-file load state, including successful parses and file-specific failures, so reloads can update only affected content.' justification: | Incremental reload behavior depends on knowing the current state of each tracked file rather than recomputing the entire workspace blindly. tests: - - 'WorkspaceModelTests.ReloadFile_UpdatesOnlyAffectedFileState' + - 'ReloadFile_UpdatesOnlyAffectedFileState' diff --git a/docs/template/template.html b/docs/template/template.html new file mode 100644 index 0000000..eb2ac3a --- /dev/null +++ b/docs/template/template.html @@ -0,0 +1,354 @@ + + + + + + +$if(author-meta)$ + +$endif$ +$if(date-meta)$ + +$endif$ +$if(keywords)$ + +$endif$ +$if(description-meta)$ + +$endif$ + $if(title-prefix)$$title-prefix$ – $endif$$pagetitle$ + +$for(css)$ + +$endfor$ +$if(math)$ + $math$ +$endif$ +$for(header-includes)$ + $header-includes$ +$endfor$ + + +$for(include-before)$ +$include-before$ +$endfor$ +$if(title)$ +
+

$title$

+$if(subtitle)$ +

$subtitle$

+$endif$ +$if(version)$ +

Version $version$

+$endif$ +$for(author)$ +

$author$

+$endfor$ +$if(date)$ +

$date$

+$endif$ +
+$endif$ +$if(toc)$ + +$endif$ +$body$ +$for(include-after)$ +$include-after$ +$endfor$ + + diff --git a/make_icon.py b/make_icon.py new file mode 100644 index 0000000..04b6b29 --- /dev/null +++ b/make_icon.py @@ -0,0 +1,88 @@ +"""Build a Windows .ico containing only the practical app-icon sizes +(title bar, taskbar, Explorer small/medium/large views, Alt-Tab), as +uncompressed 32bpp BMP (DIB) frames per Microsoft's documented recommendation +(PNG compression is only recommended for 256x256 "jumbo" icons - not needed +here since this file is used solely as an exe/window/installer icon, not as +a general-purpose image; the source Icon.png is used directly wherever a +compressed bitmap is wanted). +""" +import struct +from PIL import Image + +SRC = "Icon.png" +BMP_SIZES = [16, 24, 32, 48, 64] + + +def resized_rgba(img, size): + return img.resize((size, size), Image.LANCZOS).convert("RGBA") + + +def bmp_frame(img_rgba): + """Build the DIB (BITMAPINFOHEADER + XOR + AND mask) bytes for one ICO frame.""" + w, h = img_rgba.size + pixels = img_rgba.load() + + # XOR data: BGRA, bottom-to-top row order, 32bpp needs no row padding. + xor = bytearray() + for y in range(h - 1, -1, -1): + for x in range(w): + r, g, b, a = pixels[x, y] + xor += bytes((b, g, r, a)) + + # AND mask: 1bpp, bottom-to-top, rows padded to a 4-byte boundary. + # All-zero (fully "opaque") since the 32bpp XOR alpha channel carries + # real transparency information for any decoder that honors it. + row_bytes = ((w + 31) // 32) * 4 + and_mask = bytearray(row_bytes * h) + + header = struct.pack( + "net9.0 DemaConsulting.SysML2Workbench.Desktop app.manifest + + ..\..\Icon.ico diff --git a/src/DemaConsulting.SysML2Workbench.Installer/DemaConsulting.SysML2Workbench.Installer.wixproj b/src/DemaConsulting.SysML2Workbench.Installer/DemaConsulting.SysML2Workbench.Installer.wixproj new file mode 100644 index 0000000..ed75346 --- /dev/null +++ b/src/DemaConsulting.SysML2Workbench.Installer/DemaConsulting.SysML2Workbench.Installer.wixproj @@ -0,0 +1,28 @@ + + + + + + Package + + x64 + + $(MSBuildThisFileDirectory)..\..\publish\win-x64\ + + $(MSBuildThisFileDirectory)..\..\Icon.ico + + Version=$(Version);SysML2WorkbenchPublishDir=$(SysML2WorkbenchPublishDir);SysML2WorkbenchIconFile=$(SysML2WorkbenchIconFile) + + + diff --git a/src/DemaConsulting.SysML2Workbench.Installer/Package.wxs b/src/DemaConsulting.SysML2Workbench.Installer/Package.wxs new file mode 100644 index 0000000..f29a34a --- /dev/null +++ b/src/DemaConsulting.SysML2Workbench.Installer/Package.wxs @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/DemaConsulting.SysML2Workbench/AppShellSubsystem/MainWindowView.axaml b/src/DemaConsulting.SysML2Workbench/AppShellSubsystem/MainWindowView.axaml index 875d141..b79b0c9 100644 --- a/src/DemaConsulting.SysML2Workbench/AppShellSubsystem/MainWindowView.axaml +++ b/src/DemaConsulting.SysML2Workbench/AppShellSubsystem/MainWindowView.axaml @@ -4,6 +4,7 @@ xmlns:dockControls="using:Dock.Model.Mvvm.Controls" x:Class="DemaConsulting.SysML2Workbench.AppShellSubsystem.MainWindowView" Title="SysML2Workbench" + Icon="avares://DemaConsulting.SysML2Workbench/Assets/Icon.png" Width="1280" Height="800"> diff --git a/src/DemaConsulting.SysML2Workbench/DemaConsulting.SysML2Workbench.csproj b/src/DemaConsulting.SysML2Workbench/DemaConsulting.SysML2Workbench.csproj index 1cebf1e..f52aa8d 100644 --- a/src/DemaConsulting.SysML2Workbench/DemaConsulting.SysML2Workbench.csproj +++ b/src/DemaConsulting.SysML2Workbench/DemaConsulting.SysML2Workbench.csproj @@ -15,10 +15,16 @@ - - - + + + + + + + + diff --git a/test/OtsSoftwareTests/OtsSoftwareTests.csproj b/test/OtsSoftwareTests/OtsSoftwareTests.csproj index ae85167..d7c09e0 100644 --- a/test/OtsSoftwareTests/OtsSoftwareTests.csproj +++ b/test/OtsSoftwareTests/OtsSoftwareTests.csproj @@ -15,8 +15,8 @@ - - + +