From 3ba18f6f70f395c208341692dc712f036b8c6edf Mon Sep 17 00:00:00 2001 From: csjones Date: Wed, 24 Sep 2025 10:33:39 -0700 Subject: [PATCH] Initial Working CLI App --- .github/workflows/pr.yml | 33 + .github/workflows/release.yml | 162 +++++ .gitignore | 93 +++ .specify/memory/constitution.md | 112 +++- .specify/templates/plan-template.md | 2 +- .vscode/launch.json | 22 + .windsurf/workflows/analyze.md | 101 +++ .windsurf/workflows/clarify.md | 158 +++++ .windsurf/workflows/plan.md | 1 + Dockerfile | 39 ++ Package.swift | 59 ++ README.md | 302 +++++++++ Sources/Subtree/Commands/AddCommand.swift | 343 ++++++++++ Sources/Subtree/Commands/ExtractCommand.swift | 284 +++++++++ Sources/Subtree/Commands/InitCommand.swift | 175 +++++ Sources/Subtree/Commands/RemoveCommand.swift | 152 +++++ Sources/Subtree/Commands/SubtreeCLI.swift | 28 + Sources/Subtree/Commands/UpdateCommand.swift | 542 ++++++++++++++++ .../Subtree/Commands/ValidateCommand.swift | 210 ++++++ Sources/Subtree/Git/GitPlumbing.swift | 427 +++++++++++++ Sources/Subtree/IO/ConfigIO.swift | 112 ++++ Sources/Subtree/Models/CopyMapping.swift | 14 + Sources/Subtree/Models/SubtreeConfig.swift | 13 + Sources/Subtree/Models/SubtreeEntry.swift | 31 + Sources/Subtree/Models/SubtreeError.swift | 46 ++ Sources/Subtree/Models/UpdatePolicy.swift | 25 + .../Utilities/CommitMessageBuilder.swift | 209 ++++++ .../Subtree/Utilities/RemoteURLParser.swift | 53 ++ Sources/Subtree/main.swift | 12 + .../Add/AddOverrideTests.swift | 260 ++++++++ .../Add/AddSmartDefaultsTests.swift | 269 ++++++++ Tests/IntegrationTests/Add/AddTests.swift | 126 ++++ .../Config/ConfigUpdateTests.swift | 184 ++++++ .../Copy/CopyAdvancedTests.swift | 224 +++++++ Tests/IntegrationTests/Copy/CopyTests.swift | 187 ++++++ .../Git/GitValidationTests.swift | 97 +++ .../Init/InitExtensionsTests.swift | 54 ++ Tests/IntegrationTests/Init/InitTests.swift | 75 +++ .../Remove/RemoveEnhancedTests.swift | 303 +++++++++ .../IntegrationTests/Remove/RemoveTests.swift | 131 ++++ .../TestUtils/RepoFixture.swift | 121 ++++ .../TestUtils/SubprocessHelpers.swift | 71 +++ .../Update/UpdateAdvancedTests.swift | 192 ++++++ .../Update/UpdateApplyTests.swift | 206 ++++++ .../Update/UpdateBasicTests.swift | 153 +++++ .../Update/UpdateBranchTests.swift | 254 ++++++++ .../Update/UpdateNetworkTests.swift | 126 ++++ .../Update/UpdateOverrideTests.swift | 187 ++++++ .../Update/UpdateReportTests.swift | 187 ++++++ .../Update/UpdateSafetyTests.swift | 206 ++++++ .../Utilities/CommitMessageBuilderTests.swift | 158 +++++ .../Utilities/RemoteURLParserTests.swift | 149 +++++ .../IntegrationTests/Verify/VerifyTests.swift | 209 ++++++ .../Utilities/CommitMessageBuilderTests.swift | 158 +++++ .../Utilities/RemoteURLParserTests.swift | 149 +++++ .../contracts/cli-commands.md | 142 +++++ specs/001-i-am-building/data-model.md | 87 +++ specs/001-i-am-building/plan.md | 223 +++++++ specs/001-i-am-building/quickstart.md | 101 +++ specs/001-i-am-building/research.md | 38 ++ specs/001-i-am-building/spec.md | 153 +++++ specs/001-i-am-building/tasks.md | 596 ++++++++++++++++++ subtree.yaml | 1 + 63 files changed, 9502 insertions(+), 35 deletions(-) create mode 100644 .github/workflows/pr.yml create mode 100644 .github/workflows/release.yml create mode 100644 .gitignore create mode 100644 .vscode/launch.json create mode 100644 .windsurf/workflows/analyze.md create mode 100644 .windsurf/workflows/clarify.md create mode 100644 Dockerfile create mode 100644 Package.swift create mode 100644 README.md create mode 100644 Sources/Subtree/Commands/AddCommand.swift create mode 100644 Sources/Subtree/Commands/ExtractCommand.swift create mode 100644 Sources/Subtree/Commands/InitCommand.swift create mode 100644 Sources/Subtree/Commands/RemoveCommand.swift create mode 100644 Sources/Subtree/Commands/SubtreeCLI.swift create mode 100644 Sources/Subtree/Commands/UpdateCommand.swift create mode 100644 Sources/Subtree/Commands/ValidateCommand.swift create mode 100644 Sources/Subtree/Git/GitPlumbing.swift create mode 100644 Sources/Subtree/IO/ConfigIO.swift create mode 100644 Sources/Subtree/Models/CopyMapping.swift create mode 100644 Sources/Subtree/Models/SubtreeConfig.swift create mode 100644 Sources/Subtree/Models/SubtreeEntry.swift create mode 100644 Sources/Subtree/Models/SubtreeError.swift create mode 100644 Sources/Subtree/Models/UpdatePolicy.swift create mode 100644 Sources/Subtree/Utilities/CommitMessageBuilder.swift create mode 100644 Sources/Subtree/Utilities/RemoteURLParser.swift create mode 100644 Sources/Subtree/main.swift create mode 100644 Tests/IntegrationTests/Add/AddOverrideTests.swift create mode 100644 Tests/IntegrationTests/Add/AddSmartDefaultsTests.swift create mode 100644 Tests/IntegrationTests/Add/AddTests.swift create mode 100644 Tests/IntegrationTests/Config/ConfigUpdateTests.swift create mode 100644 Tests/IntegrationTests/Copy/CopyAdvancedTests.swift create mode 100644 Tests/IntegrationTests/Copy/CopyTests.swift create mode 100644 Tests/IntegrationTests/Git/GitValidationTests.swift create mode 100644 Tests/IntegrationTests/Init/InitExtensionsTests.swift create mode 100644 Tests/IntegrationTests/Init/InitTests.swift create mode 100644 Tests/IntegrationTests/Remove/RemoveEnhancedTests.swift create mode 100644 Tests/IntegrationTests/Remove/RemoveTests.swift create mode 100644 Tests/IntegrationTests/TestUtils/RepoFixture.swift create mode 100644 Tests/IntegrationTests/TestUtils/SubprocessHelpers.swift create mode 100644 Tests/IntegrationTests/Update/UpdateAdvancedTests.swift create mode 100644 Tests/IntegrationTests/Update/UpdateApplyTests.swift create mode 100644 Tests/IntegrationTests/Update/UpdateBasicTests.swift create mode 100644 Tests/IntegrationTests/Update/UpdateBranchTests.swift create mode 100644 Tests/IntegrationTests/Update/UpdateNetworkTests.swift create mode 100644 Tests/IntegrationTests/Update/UpdateOverrideTests.swift create mode 100644 Tests/IntegrationTests/Update/UpdateReportTests.swift create mode 100644 Tests/IntegrationTests/Update/UpdateSafetyTests.swift create mode 100644 Tests/IntegrationTests/Utilities/CommitMessageBuilderTests.swift create mode 100644 Tests/IntegrationTests/Utilities/RemoteURLParserTests.swift create mode 100644 Tests/IntegrationTests/Verify/VerifyTests.swift create mode 100644 Tests/SubtreeTests/Utilities/CommitMessageBuilderTests.swift create mode 100644 Tests/SubtreeTests/Utilities/RemoteURLParserTests.swift create mode 100644 specs/001-i-am-building/contracts/cli-commands.md create mode 100644 specs/001-i-am-building/data-model.md create mode 100644 specs/001-i-am-building/plan.md create mode 100644 specs/001-i-am-building/quickstart.md create mode 100644 specs/001-i-am-building/research.md create mode 100644 specs/001-i-am-building/spec.md create mode 100644 specs/001-i-am-building/tasks.md create mode 100644 subtree.yaml diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml new file mode 100644 index 0000000..511086f --- /dev/null +++ b/.github/workflows/pr.yml @@ -0,0 +1,33 @@ +name: PR Validation + +on: + pull_request: + branches: [ main ] + push: + branches: [ main ] + +jobs: + macos: + name: Test on macOS + runs-on: macos-15 + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Run test suite + run: swift test --filter "SubtreeTests" + + linux: + name: Test on Linux + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + # - name: Set up Docker Buildx + # uses: docker/setup-buildx-action@v3 + + - name: Run Linux test suite + run: | + docker run --rm -v "$(pwd):/workspace" -w /workspace swift:6.1 \ + bash -c "swift package resolve && swift test --filter 'SubtreeTests'" diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..13c3c01 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,162 @@ +name: Build Release Artifacts + +on: + release: + types: [published] + +jobs: + macos: + name: Build macOS binary + runs-on: macos-15 + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Build macOS binary + run: swift build -c release --arch arm64 --arch x86_64 -Xswiftc -Osize + + - name: Strip macOS binary + run: strip -rSTx .build/apple/Products/Release/subtree + + - name: Test binary functionality + run: | + .build/apple/Products/Release/subtree --help + echo "✅ macOS binary responds to --help" + + - name: Upload artifacts + uses: actions/upload-artifact@v4 + with: + name: subtree_macos + path: .build/apple/Products/Release/subtree + retention-days: 5 + + linux: + name: Build Linux binaries + runs-on: ubuntu-20.04 + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Install cross-binutils for aarch64 + run: sudo apt install -y binutils-aarch64-linux-gnu + + - name: Build and export binaries + uses: docker/build-push-action@v5 + with: + context: . + platforms: linux/amd64,linux/arm64 + target: output + outputs: type=local,dest=artifacts + + - name: Test and organize binaries + run: | + # Test that binaries were built successfully + echo "✅ Linux AMD64 binary built: $(file artifacts/linux_amd64/subtree)" + echo "✅ Linux ARM64 binary built: $(file artifacts/linux_arm64/subtree)" + + # Strip and organize AMD64 binary + strip artifacts/linux_amd64/subtree + mv artifacts/linux_amd64/subtree "${HOME}/subtree_linux" + + # Strip and organize ARM64 binary + aarch64-linux-gnu-strip artifacts/linux_arm64/subtree + mv artifacts/linux_arm64/subtree "${HOME}/subtree_linux_aarch64" + + - name: Upload AMD64 Artifact + uses: actions/upload-artifact@v4 + with: + name: subtree_linux + path: ~/subtree_linux + retention-days: 5 + + - name: Upload ARM64 Artifact + uses: actions/upload-artifact@v4 + with: + name: subtree_linux_aarch64 + path: ~/subtree_linux_aarch64 + retention-days: 5 + + upload: + name: Upload release artifacts + runs-on: ubuntu-20.04 + needs: [macos, linux] + steps: + - name: Checkout the repository + uses: actions/checkout@v4 + + - name: Download artifacts + uses: actions/download-artifact@v4 + with: + path: downloaded_artifacts + + - name: Display structure of downloaded files + run: ls -R downloaded_artifacts + + - name: Prepare release binaries + run: | + VERSION="${{ github.event.release.tag_name }}" + + # Copy and rename binaries for release upload + cp downloaded_artifacts/subtree_macos/subtree "subtree_${VERSION}_macos" + cp downloaded_artifacts/subtree_linux/subtree_linux "subtree_${VERSION}_linux_x86_64" + cp downloaded_artifacts/subtree_linux_aarch64/subtree_linux_aarch64 "subtree_${VERSION}_linux_arm64" + + # Make all binaries executable + chmod +x subtree_${VERSION}_* + + - name: Build artifact bundle + run: | + VERSION="${{ github.event.release.tag_name }}" + BUNDLE_DIR="subtree.artifactbundle" + + mkdir -p "${BUNDLE_DIR}" + + # Organize binaries by platform (universal macOS binary) + mkdir -p "${BUNDLE_DIR}/macos" + mkdir -p "${BUNDLE_DIR}/linux-x86_64" + mkdir -p "${BUNDLE_DIR}/linux-arm64" + + # Copy binaries to bundle structure + cp downloaded_artifacts/subtree_macos/subtree "${BUNDLE_DIR}/macos/subtree" + cp downloaded_artifacts/subtree_linux/subtree_linux "${BUNDLE_DIR}/linux-x86_64/subtree" + cp downloaded_artifacts/subtree_linux_aarch64/subtree_linux_aarch64 "${BUNDLE_DIR}/linux-arm64/subtree" + + # Create artifact bundle manifest + cat > "${BUNDLE_DIR}/artifactbundle.json" << EOF + { + "schemaVersion": "1.0", + "artifacts": { + "subtree": { + "version": "${VERSION}", + "type": "executable", + "variants": [ + { + "path": "macos/subtree", + "supportedTriples": ["arm64-apple-macosx", "x86_64-apple-macosx"] + }, + { + "path": "linux-x86_64/subtree", + "supportedTriples": ["x86_64-unknown-linux-gnu"] + }, + { + "path": "linux-arm64/subtree", + "supportedTriples": ["aarch64-unknown-linux-gnu"] + } + ] + } + } + } + EOF + + # Create zip archive + zip -r "subtree.artifactbundle.zip" "${BUNDLE_DIR}" + + - name: Upload release binaries + uses: skx/github-action-publish-binaries@master + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + args: 'subtree_${{ github.event.release.tag_name }}_macos subtree_${{ github.event.release.tag_name }}_linux_x86_64 subtree_${{ github.event.release.tag_name }}_linux_arm64 subtree.artifactbundle.zip' diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c197381 --- /dev/null +++ b/.gitignore @@ -0,0 +1,93 @@ +# Xcode +# +# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore + +## User settings +xcuserdata/ + +## compatibility with Xcode 8 and earlier (ignoring not required starting Xcode 9) +*.xcscmblueprint +*.xccheckout + +## compatibility with Xcode 3 and earlier (ignoring not required starting Xcode 4) +build/ +DerivedData/ +*.moved-aside +*.pbxuser +!default.pbxuser +*.mode1v3 +!default.mode1v3 +*.mode2v3 +!default.mode2v3 +*.perspectivev3 +!default.perspectivev3 + +## Obj-C/Swift specific +*.hmap + +## App packaging +*.ipa +*.dSYM.zip +*.dSYM + +## Playgrounds +timeline.xctimeline +playground.xcworkspace + +## macOS +.DS_Store + +# Swift Package Manager +# +# Add this line if you want to avoid checking in source code from Swift Package Manager dependencies. +Packages/ +Package.pins +Package.resolved +*.xcodeproj + +# Xcode automatically generates this directory with a .xcworkspacedata file and xcuserdata +# hence it is not needed unless you have added a package configuration file to your project +.swiftpm + +.build/ + +# CocoaPods +# +# We recommend against adding the Pods directory to your .gitignore. However +# you should judge for yourself, the pros and cons are mentioned at: +# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control +# +# Pods/ +# +# Add this line if you want to avoid checking in source code from the Xcode workspace +*.xcworkspace + +# Carthage +# +# Add this line if you want to avoid checking in source code from Carthage dependencies. +# Carthage/Checkouts + +Carthage/Build/ + +# Accio dependency management +Dependencies/ +.accio/ + +# fastlane +# +# It is recommended to not store the screenshots in the git repo. +# Instead, use fastlane to re-generate the screenshots whenever they are needed. +# For more information about the recommended setup visit: +# https://docs.fastlane.tools/best-practices/source-control/#source-control + +fastlane/report.xml +fastlane/Preview.html +fastlane/screenshots/**/*.png +fastlane/test_output + +# Code Injection +# +# After new code Injection tools there's a generated folder /iOSInjectionProject +# https://github.com/johnno1962/injectionforxcode + +iOSInjectionProject/ \ No newline at end of file diff --git a/.specify/memory/constitution.md b/.specify/memory/constitution.md index 1ed8d77..2fbbfe6 100644 --- a/.specify/memory/constitution.md +++ b/.specify/memory/constitution.md @@ -1,50 +1,94 @@ -# [PROJECT_NAME] Constitution - + + +# Subtree Constitution ## Core Principles -### [PRINCIPLE_1_NAME] - -[PRINCIPLE_1_DESCRIPTION] - +### I. CLI I/O Contract +Subtree is a non-interactive, pipeline-friendly CLI by default. +- Input: command-line args and STDIN; Output: STDOUT; Errors/warnings: STDERR. +- Default output is human-readable. When `--json` is provided, output MUST be valid JSON and stable across patch releases. +- Exit codes: `0` success, `1` general failure, `2` usage/argument error, `3` I/O/environment error. Additional codes MAY be defined per subcommand and documented in `--help`. +- No interactive prompts unless `--interactive` (or equivalent) is explicitly passed and TTY is detected. +- Color and TTY behavior: enable colors only when attached to a TTY; support `--no-color` to disable. +- Required flags across all binaries: `--help`, `--version`, `--json` (where applicable), and `--quiet` to suppress non-essential output. + +### II. Test-First & CI (NON-NEGOTIABLE) +Test-Driven Development is mandatory for all changes. +- Red-Green-Refactor: write failing tests before implementation; refactor only with tests green. +- CI MUST run `swift build` and `swift test` on all supported platforms/architectures where feasible. +- New flags/behavior MUST include tests for success, failure, and edge cases; JSON mode outputs MUST have schema assertions. +- No PR may merge with failing tests or without coverage of new behavior. -### [PRINCIPLE_2_NAME] - -[PRINCIPLE_2_DESCRIPTION] - +### III. Versioning & Releases +We use Semantic Versioning for the public CLI surface and output schemas. +- Versioning: MAJOR.MINOR.PATCH. Breaking CLI or JSON changes require a MAJOR release. +- Tags: `vX.Y.Z`. Releases are published as GitHub Releases with asset checksums. +- Deliverables: prebuilt binaries for all supported OS/architectures; include SHA-256 checksums and a plaintext CHANGELOG entry. +- Deprecations MUST be announced one MINOR release before removal, when feasible. -### [PRINCIPLE_3_NAME] - -[PRINCIPLE_3_DESCRIPTION] - +### IV. Cross-Platform Builds +Subtree MUST build and function on the defined matrix without code divergence. +- Targets: macOS (arm64, x86_64), Linux glibc (x86_64, arm64), Windows (arm64, x86_64). +- Source MUST avoid OS-specific assumptions (paths, encodings, newlines). Use Swift standard library and portability utilities. +- CI SHOULD produce artifacts for each target or validate via matrix builds where native toolchains exist. -### [PRINCIPLE_4_NAME] - -[PRINCIPLE_4_DESCRIPTION] - +### V. Exit Codes & Error Handling +All commands MUST return deterministic exit codes and clear diagnostics. +- Human-readable errors go to STDERR; JSON mode emits `{ "error": { "code": , "message": , "details": } }` on STDERR. +- Verbosity controls: `--quiet` suppresses info-level logs; `--trace` may include stack traces for debugging. +- Never print secrets or tokens. Redact in logs and error messages. -### [PRINCIPLE_5_NAME] - -[PRINCIPLE_5_DESCRIPTION] - +## Additional Constraints -## [SECTION_2_NAME] - +- Language/Runtime: Swift + Swift Package Manager (SPM). No alternate build systems. +- Baseline commands: `--help`, `--version`, `--json` (where applicable), `--quiet`. +- Distribution: GitHub Releases with prebuilt binaries; include SHA-256 checksums and a CHANGELOG entry. +- Dependency policy: all dependencies pinned via `Package.resolved`; reproducible builds required. +- Security: no network calls during execution unless explicitly required by a subcommand and documented. -[SECTION_2_CONTENT] - +## Development Workflow & Quality Gates -## [SECTION_3_NAME] - +1) Tests First +- All new behavior lands with failing tests first, then implementation. +- JSON output schemas validated in tests. -[SECTION_3_CONTENT] - +2) CI Matrix +- Build and test across the supported OS/arch matrix where toolchains are available. +- Release pipelines produce artifacts and checksums; verify signatures/checksums before publish. + +3) Review Gating +- PRs MUST assert compliance with all Core Principles in the description. +- Any deviation requires a documented justification and follow-up task to restore compliance. ## Governance -[GOVERNANCE_RULES] - +This constitution supersedes conflicting practices. Compliance is required for all changes. + +- Amendments: via PR with impact analysis (CLI flags, JSON schema, exit codes). Bump version per SemVer rules. +- Breaking changes: require migration notes and clear release notes; deprecate before removal when feasible. +- Compliance Review: reviewers verify Core Principles checkboxes in PR description; CI enforces tests and matrix builds. +- Runtime Guidance: see `.specify/templates/plan-template.md`, `spec-template.md`, and `tasks-template.md` for process checkpoints that mirror these principles. -**Version**: [CONSTITUTION_VERSION] | **Ratified**: [RATIFICATION_DATE] | **Last Amended**: [LAST_AMENDED_DATE] - \ No newline at end of file +**Version**: 1.0.0 | **Ratified**: 2025-09-22 | **Last Amended**: 2025-09-22 \ No newline at end of file diff --git a/.specify/templates/plan-template.md b/.specify/templates/plan-template.md index bc799ae..9115d1a 100644 --- a/.specify/templates/plan-template.md +++ b/.specify/templates/plan-template.md @@ -209,4 +209,4 @@ ios/ or android/ - [ ] Complexity deviations documented --- -*Based on Constitution v2.1.1 - See `/memory/constitution.md`* +*Based on Constitution v1.0.0 - See `.specify/memory/constitution.md`* diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..198a860 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,22 @@ +{ + "configurations": [ + { + "type": "swift", + "request": "launch", + "args": [], + "cwd": "${workspaceFolder:subtree}", + "name": "Debug subtree", + "program": "${workspaceFolder:subtree}/.build/debug/subtree", + "preLaunchTask": "swift: Build Debug subtree" + }, + { + "type": "swift", + "request": "launch", + "args": [], + "cwd": "${workspaceFolder:subtree}", + "name": "Release subtree", + "program": "${workspaceFolder:subtree}/.build/release/subtree", + "preLaunchTask": "swift: Build Release subtree" + } + ] +} \ No newline at end of file diff --git a/.windsurf/workflows/analyze.md b/.windsurf/workflows/analyze.md new file mode 100644 index 0000000..f4c1a7b --- /dev/null +++ b/.windsurf/workflows/analyze.md @@ -0,0 +1,101 @@ +--- +description: Perform a non-destructive cross-artifact consistency and quality analysis across spec.md, plan.md, and tasks.md after task generation. +--- + +The user input to you can be provided directly by the agent or as a command argument - you **MUST** consider it before proceeding with the prompt (if not empty). + +User input: + +$ARGUMENTS + +Goal: Identify inconsistencies, duplications, ambiguities, and underspecified items across the three core artifacts (`spec.md`, `plan.md`, `tasks.md`) before implementation. This command MUST run only after `/tasks` has successfully produced a complete `tasks.md`. + +STRICTLY READ-ONLY: Do **not** modify any files. Output a structured analysis report. Offer an optional remediation plan (user must explicitly approve before any follow-up editing commands would be invoked manually). + +Constitution Authority: The project constitution (`.specify/memory/constitution.md`) is **non-negotiable** within this analysis scope. Constitution conflicts are automatically CRITICAL and require adjustment of the spec, plan, or tasks—not dilution, reinterpretation, or silent ignoring of the principle. If a principle itself needs to change, that must occur in a separate, explicit constitution update outside `/analyze`. + +Execution steps: + +1. Run `.specify/scripts/bash/check-prerequisites.sh --json --require-tasks --include-tasks` once from repo root and parse JSON for FEATURE_DIR and AVAILABLE_DOCS. Derive absolute paths: + - SPEC = FEATURE_DIR/spec.md + - PLAN = FEATURE_DIR/plan.md + - TASKS = FEATURE_DIR/tasks.md + Abort with an error message if any required file is missing (instruct the user to run missing prerequisite command). + +2. Load artifacts: + - Parse spec.md sections: Overview/Context, Functional Requirements, Non-Functional Requirements, User Stories, Edge Cases (if present). + - Parse plan.md: Architecture/stack choices, Data Model references, Phases, Technical constraints. + - Parse tasks.md: Task IDs, descriptions, phase grouping, parallel markers [P], referenced file paths. + - Load constitution `.specify/memory/constitution.md` for principle validation. + +3. Build internal semantic models: + - Requirements inventory: Each functional + non-functional requirement with a stable key (derive slug based on imperative phrase; e.g., "User can upload file" -> `user-can-upload-file`). + - User story/action inventory. + - Task coverage mapping: Map each task to one or more requirements or stories (inference by keyword / explicit reference patterns like IDs or key phrases). + - Constitution rule set: Extract principle names and any MUST/SHOULD normative statements. + +4. Detection passes: + A. Duplication detection: + - Identify near-duplicate requirements. Mark lower-quality phrasing for consolidation. + B. Ambiguity detection: + - Flag vague adjectives (fast, scalable, secure, intuitive, robust) lacking measurable criteria. + - Flag unresolved placeholders (TODO, TKTK, ???, , etc.). + C. Underspecification: + - Requirements with verbs but missing object or measurable outcome. + - User stories missing acceptance criteria alignment. + - Tasks referencing files or components not defined in spec/plan. + D. Constitution alignment: + - Any requirement or plan element conflicting with a MUST principle. + - Missing mandated sections or quality gates from constitution. + E. Coverage gaps: + - Requirements with zero associated tasks. + - Tasks with no mapped requirement/story. + - Non-functional requirements not reflected in tasks (e.g., performance, security). + F. Inconsistency: + - Terminology drift (same concept named differently across files). + - Data entities referenced in plan but absent in spec (or vice versa). + - Task ordering contradictions (e.g., integration tasks before foundational setup tasks without dependency note). + - Conflicting requirements (e.g., one requires to use Next.js while other says to use Vue as the framework). + +5. Severity assignment heuristic: + - CRITICAL: Violates constitution MUST, missing core spec artifact, or requirement with zero coverage that blocks baseline functionality. + - HIGH: Duplicate or conflicting requirement, ambiguous security/performance attribute, untestable acceptance criterion. + - MEDIUM: Terminology drift, missing non-functional task coverage, underspecified edge case. + - LOW: Style/wording improvements, minor redundancy not affecting execution order. + +6. Produce a Markdown report (no file writes) with sections: + + ### Specification Analysis Report + | ID | Category | Severity | Location(s) | Summary | Recommendation | + |----|----------|----------|-------------|---------|----------------| + | A1 | Duplication | HIGH | spec.md:L120-134 | Two similar requirements ... | Merge phrasing; keep clearer version | + (Add one row per finding; generate stable IDs prefixed by category initial.) + + Additional subsections: + - Coverage Summary Table: + | Requirement Key | Has Task? | Task IDs | Notes | + - Constitution Alignment Issues (if any) + - Unmapped Tasks (if any) + - Metrics: + * Total Requirements + * Total Tasks + * Coverage % (requirements with >=1 task) + * Ambiguity Count + * Duplication Count + * Critical Issues Count + +7. At end of report, output a concise Next Actions block: + - If CRITICAL issues exist: Recommend resolving before `/implement`. + - If only LOW/MEDIUM: User may proceed, but provide improvement suggestions. + - Provide explicit command suggestions: e.g., "Run /specify with refinement", "Run /plan to adjust architecture", "Manually edit tasks.md to add coverage for 'performance-metrics'". + +8. Ask the user: "Would you like me to suggest concrete remediation edits for the top N issues?" (Do NOT apply them automatically.) + +Behavior rules: +- NEVER modify files. +- NEVER hallucinate missing sections—if absent, report them. +- KEEP findings deterministic: if rerun without changes, produce consistent IDs and counts. +- LIMIT total findings in the main table to 50; aggregate remainder in a summarized overflow note. +- If zero issues found, emit a success report with coverage statistics and proceed recommendation. + +Context: $ARGUMENTS diff --git a/.windsurf/workflows/clarify.md b/.windsurf/workflows/clarify.md new file mode 100644 index 0000000..26ff530 --- /dev/null +++ b/.windsurf/workflows/clarify.md @@ -0,0 +1,158 @@ +--- +description: Identify underspecified areas in the current feature spec by asking up to 5 highly targeted clarification questions and encoding answers back into the spec. +--- + +The user input to you can be provided directly by the agent or as a command argument - you **MUST** consider it before proceeding with the prompt (if not empty). + +User input: + +$ARGUMENTS + +Goal: Detect and reduce ambiguity or missing decision points in the active feature specification and record the clarifications directly in the spec file. + +Note: This clarification workflow is expected to run (and be completed) BEFORE invoking `/plan`. If the user explicitly states they are skipping clarification (e.g., exploratory spike), you may proceed, but must warn that downstream rework risk increases. + +Execution steps: + +1. Run `.specify/scripts/bash/check-prerequisites.sh --json --paths-only` from repo root **once** (combined `--json --paths-only` mode / `-Json -PathsOnly`). Parse minimal JSON payload fields: + - `FEATURE_DIR` + - `FEATURE_SPEC` + - (Optionally capture `IMPL_PLAN`, `TASKS` for future chained flows.) + - If JSON parsing fails, abort and instruct user to re-run `/specify` or verify feature branch environment. + +2. Load the current spec file. Perform a structured ambiguity & coverage scan using this taxonomy. For each category, mark status: Clear / Partial / Missing. Produce an internal coverage map used for prioritization (do not output raw map unless no questions will be asked). + + Functional Scope & Behavior: + - Core user goals & success criteria + - Explicit out-of-scope declarations + - User roles / personas differentiation + + Domain & Data Model: + - Entities, attributes, relationships + - Identity & uniqueness rules + - Lifecycle/state transitions + - Data volume / scale assumptions + + Interaction & UX Flow: + - Critical user journeys / sequences + - Error/empty/loading states + - Accessibility or localization notes + + Non-Functional Quality Attributes: + - Performance (latency, throughput targets) + - Scalability (horizontal/vertical, limits) + - Reliability & availability (uptime, recovery expectations) + - Observability (logging, metrics, tracing signals) + - Security & privacy (authN/Z, data protection, threat assumptions) + - Compliance / regulatory constraints (if any) + + Integration & External Dependencies: + - External services/APIs and failure modes + - Data import/export formats + - Protocol/versioning assumptions + + Edge Cases & Failure Handling: + - Negative scenarios + - Rate limiting / throttling + - Conflict resolution (e.g., concurrent edits) + + Constraints & Tradeoffs: + - Technical constraints (language, storage, hosting) + - Explicit tradeoffs or rejected alternatives + + Terminology & Consistency: + - Canonical glossary terms + - Avoided synonyms / deprecated terms + + Completion Signals: + - Acceptance criteria testability + - Measurable Definition of Done style indicators + + Misc / Placeholders: + - TODO markers / unresolved decisions + - Ambiguous adjectives ("robust", "intuitive") lacking quantification + + For each category with Partial or Missing status, add a candidate question opportunity unless: + - Clarification would not materially change implementation or validation strategy + - Information is better deferred to planning phase (note internally) + +3. Generate (internally) a prioritized queue of candidate clarification questions (maximum 5). Do NOT output them all at once. Apply these constraints: + - Maximum of 5 total questions across the whole session. + - Each question must be answerable with EITHER: + * A short multiple‑choice selection (2–5 distinct, mutually exclusive options), OR + * A one-word / short‑phrase answer (explicitly constrain: "Answer in <=5 words"). + - Only include questions whose answers materially impact architecture, data modeling, task decomposition, test design, UX behavior, operational readiness, or compliance validation. + - Ensure category coverage balance: attempt to cover the highest impact unresolved categories first; avoid asking two low-impact questions when a single high-impact area (e.g., security posture) is unresolved. + - Exclude questions already answered, trivial stylistic preferences, or plan-level execution details (unless blocking correctness). + - Favor clarifications that reduce downstream rework risk or prevent misaligned acceptance tests. + - If more than 5 categories remain unresolved, select the top 5 by (Impact * Uncertainty) heuristic. + +4. Sequential questioning loop (interactive): + - Present EXACTLY ONE question at a time. + - For multiple‑choice questions render options as a Markdown table: + + | Option | Description | + |--------|-------------| + | A |