feat: add SpecKit project baseline - #235
Conversation
…lution roadmap Establish the speckit feature directory as the canonical product specification and migrate the legacy spec/ corpus into it. - Ratify Metano Constitution v1.0.0 (6 principles: clean code, expressiveness, screaming/feature-semantic organization, ports & adapters, DX, pragmatism) - Add canonical baseline: frontend/IR/backend overview, feature-support matrix with code+test traceability, attribute and diagnostic catalogs corrected against the codebase (27 attributes; diagnostics MS0001-MS0025) - Add prioritized evolution roadmap (RT-01 harden multi-target SPI, RT-02 Dart backend parity, RT-03 frontend-extensibility posture) - Add reconciliation ledger; rename spec/ -> old-spec/ as a comparison reference pending the migration parity gate - Repoint single-source-of-truth references in the constitution and CLAUDE.md to the canonical speckit location
There was a problem hiding this comment.
Code Review
This pull request introduces the Spec Kit toolchain, including core commands, Git workflow extensions, templates, and scripts. It also establishes the canonical product baseline and multi-target evolution roadmap under specs/001-project-baseline-evolution/, migrating legacy specifications. The review feedback focuses on improving the robustness of the Bash scripts. This includes preventing an infinite loop in the template wrapper logic, validating numeric inputs, and replacing unsafe echo calls with printf to handle arbitrary user input safely.
| while [[ "$layer_content" == *'{CORE_TEMPLATE}'* ]]; do | ||
| local before="${layer_content%%\{CORE_TEMPLATE\}*}" | ||
| local after="${layer_content#*\{CORE_TEMPLATE\}}" | ||
| layer_content="${before}${content}${after}" | ||
| done |
There was a problem hiding this comment.
The while loop used in the wrap strategy can result in an infinite loop if the replacement content itself contains the literal string {CORE_TEMPLATE} (for example, in documentation or template files). Replacing the loop with a single bash pattern replacement replaces all occurrences of {CORE_TEMPLATE} in layer_content with $content in a single non-recursive step, completely avoiding the infinite loop.
| while [[ "$layer_content" == *'{CORE_TEMPLATE}'* ]]; do | |
| local before="${layer_content%%\{CORE_TEMPLATE\}*}" | |
| local after="${layer_content#*\{CORE_TEMPLATE\}}" | |
| layer_content="${before}${content}${after}" | |
| done | |
| layer_content="${layer_content//'{CORE_TEMPLATE}'/$content}" |
| BRANCH_NUMBER="$next_arg" | ||
| ;; |
There was a problem hiding this comment.
The --number argument is missing validation to ensure it is a non-negative integer. If a user passes a non-numeric value (e.g., --number abc), the script will crash later with a syntax error when evaluating $((10#$BRANCH_NUMBER)). Adding regex validation ensures the input is a valid non-negative integer.
| BRANCH_NUMBER="$next_arg" | |
| ;; | |
| BRANCH_NUMBER="$next_arg" | |
| if [[ ! "$BRANCH_NUMBER" =~ ^[0-9]+$ ]]; then | |
| echo 'Error: --number must be a non-negative integer' >&2 | |
| exit 1 | |
| fi | |
| ;; |
| # Function to clean and format a branch name | ||
| clean_branch_name() { | ||
| local name="$1" | ||
| echo "$name" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9]/-/g' | sed 's/-\+/-/g' | sed 's/^-//' | sed 's/-$//' |
There was a problem hiding this comment.
Using echo with arbitrary user input can cause unexpected behavior if the input starts with a hyphen (e.g., -n, -e, or -E), as echo will interpret it as an option. Using printf '%s\n' is much safer and more robust.
| echo "$name" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9]/-/g' | sed 's/-\+/-/g' | sed 's/^-//' | sed 's/-$//' | |
| printf '%s\n' "$name" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9]/-/g' | sed 's/-\+/-/g' | sed 's/^-//' | sed 's/-$//' |
|
|
||
| # Function to clean and format a branch name | ||
| clean_branch_name() { | ||
| local name="$1" |
There was a problem hiding this comment.
Using echo with arbitrary user input can cause unexpected behavior if the input starts with a hyphen (e.g., -n, -e, or -E), as echo will interpret it as an option. Using printf '%s\n' is much safer and more robust.
| local name="$1" | |
| printf '%s\n' "$name" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9]/-/g' | sed 's/-\+/-/g' | sed 's/^-//' | sed 's/-$//' |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 18d648296f
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| @@ -0,0 +1,3 @@ | |||
| { | |||
| "feature_directory": "specs/001-project-baseline-evolution" | |||
There was a problem hiding this comment.
Remove the committed feature pin
With this repository-level .specify/feature.json committed, common.sh:get_feature_paths always prefers this path before falling back to the current branch or SPECIFY_FEATURE, so downstream commands such as setup-plan.sh/setup-tasks.sh resolve every feature to specs/001-project-baseline-evolution until the file is rewritten. For example, even SPECIFY_FEATURE=002-new-feature still points at this baseline directory, which can cause a user working on another feature to overwrite or read the wrong plan/tasks. This appears to be per-invocation state and should not be committed, or the lookup should validate it against the active feature before using it.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Pull request overview
Adds a SpecKit-based, canonical documentation baseline for Metano (baseline + roadmap + reconciliation ledger) and installs SpecKit workflow assets/scripts so the repo can run a full “specify → plan → tasks → implement” SDD cycle with Git extension support.
Changes:
- Introduce the
specs/001-project-baseline-evolution/canonical baseline/roadmap/ledger + supporting contracts and quickstart validation commands. - Migrate legacy spec content into
old-spec/and repoint SSOT references (notablyCLAUDE.mdand the new constitution). - Add SpecKit workflow registry/templates/scripts + a Git workflow extension, plus a root
nuget.configto pin package sources.
Reviewed changes
Copilot reviewed 72 out of 84 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| specs/001-project-baseline-evolution/tasks.md | Task breakdown for the baseline/roadmap/reconciliation doc effort |
| specs/001-project-baseline-evolution/roadmap/00-roadmap.md | Ranked roadmap thrusts (RT-01..RT-03) |
| specs/001-project-baseline-evolution/research.md | Captures migration/structure decisions and rationale |
| specs/001-project-baseline-evolution/reconciliation-ledger.md | Records dispositions + SSOT pointer updates + parity gate status |
| specs/001-project-baseline-evolution/quickstart.md | Read order + validation commands for the canonical baseline |
| specs/001-project-baseline-evolution/plan.md | Implementation plan describing the doc migration and validation approach |
| specs/001-project-baseline-evolution/data-model.md | Defines schemas/invariants for baseline matrix, roadmap thrusts, and ledger |
| specs/001-project-baseline-evolution/contracts/roadmap-thrust.contract.md | Roadmap thrust entry contract |
| specs/001-project-baseline-evolution/contracts/reconciliation-ledger.contract.md | Ledger table contract and parity gate rules |
| specs/001-project-baseline-evolution/contracts/baseline-matrix.contract.md | Baseline feature-support matrix contract |
| specs/001-project-baseline-evolution/checklists/requirements.md | Spec quality checklist for this feature |
| specs/001-project-baseline-evolution/baseline/README.md | Canonical entry point into the baseline docs |
| specs/001-project-baseline-evolution/baseline/00-overview.md | Architecture overview framing (frontend/IR/backend) + mermaid diagram |
| specs/001-project-baseline-evolution/baseline/feature-support-matrix.md | Capability matrix with code/test traceability and Dart gaps |
| specs/001-project-baseline-evolution/baseline/attribute-catalog.md | Migrated/corrected attribute catalog |
| specs/001-project-baseline-evolution/baseline/diagnostic-catalog.md | Migrated/corrected diagnostic catalog |
| specs/001-project-baseline-evolution/baseline/.migration-index.md | Working note mapping old-spec docs to new baseline artifacts |
| specs/001-project-baseline-evolution/baseline/.identifier-inventory.md | Working note listing stable identifiers to preserve |
| old-spec/README.md | Legacy spec README preserved under old-spec/ |
| old-spec/01-product-vision.md | Legacy product vision (now reference-only) |
| old-spec/02-problem-scope-and-objectives.md | Legacy scope/objectives (now reference-only) |
| old-spec/03-stakeholders-and-use-cases.md | Legacy stakeholders/use cases (now reference-only) |
| old-spec/04-functional-requirements.md | Legacy FR set (now reference-only) |
| old-spec/05-non-functional-requirements.md | Legacy NFR set (now reference-only) |
| old-spec/06-conceptual-architecture.md | Legacy conceptual architecture (now reference-only) |
| old-spec/07-glossary.md | Legacy glossary (now reference-only) |
| old-spec/08-feature-support-matrix.md | Legacy matrix (now reference-only) |
| old-spec/09-attribute-catalog.md | Legacy attribute catalog (now reference-only) |
| old-spec/10-diagnostic-catalog.md | Legacy diagnostic catalog (now reference-only) |
| old-spec/11-adr-cross-reference.md | Legacy ADR cross-reference (now reference-only) |
| nuget.config | Pins package source(s) to nuget.org for hermetic builds |
| CLAUDE.md | Repoints spec SSOT guidance to the new speckit canonical location |
| .specify/workflows/workflow-registry.json | Registers the bundled “speckit” workflow |
| .specify/workflows/speckit/workflow.yml | Defines the full SDD workflow steps + gates |
| .specify/templates/spec-template.md | Adds SpecKit spec template |
| .specify/templates/plan-template.md | Adds SpecKit plan template |
| .specify/templates/tasks-template.md | Adds SpecKit tasks template |
| .specify/templates/checklist-template.md | Adds SpecKit checklist template |
| .specify/templates/constitution-template.md | Adds constitution template |
| .specify/scripts/bash/setup-plan.sh | Setup helper for plan generation |
| .specify/scripts/bash/setup-tasks.sh | Setup helper for tasks generation |
| .specify/scripts/bash/check-prerequisites.sh | Consolidated prerequisite/feature-path checker |
| .specify/memory/constitution.md | Adds a concrete Metano constitution (principles + governance) |
| .specify/integrations/speckit.manifest.json | Records installed speckit integration file hashes/version |
| .specify/integrations/claude.manifest.json | Records installed claude integration skill hashes/version |
| .specify/integration.json | Sets default integration configuration (claude) |
| .specify/init-options.json | Records initialization options (branch numbering, context file, etc.) |
| .specify/feature.json | Pins active feature directory |
| .specify/extensions.yml | Enables extension hooks execution and registers git hooks |
| .specify/extensions/.registry | Local registry entry for the git extension |
| .specify/extensions/git/README.md | Documentation for the git extension |
| .specify/extensions/git/extension.yml | Git extension manifest (commands + hooks) |
| .specify/extensions/git/git-config.yml | Git extension configuration (branch numbering, auto-commit toggles) |
| .specify/extensions/git/config-template.yml | Template for git extension configuration |
| .specify/extensions/git/commands/speckit.git.feature.md | Spec for “create feature branch” command behavior |
| .specify/extensions/git/commands/speckit.git.validate.md | Spec for feature-branch validation command behavior |
| .specify/extensions/git/commands/speckit.git.remote.md | Spec for git remote discovery command behavior |
| .specify/extensions/git/commands/speckit.git.initialize.md | Spec for initializing a repo command behavior |
| .specify/extensions/git/commands/speckit.git.commit.md | Spec for auto-commit hook command behavior |
| .specify/extensions/git/scripts/bash/initialize-repo.sh | Bash implementation for git init |
| .specify/extensions/git/scripts/bash/git-common.sh | Bash git helpers (branch validation, etc.) |
| .specify/extensions/git/scripts/bash/auto-commit.sh | Bash auto-commit implementation |
| .specify/extensions/git/scripts/powershell/initialize-repo.ps1 | PowerShell implementation for git init |
| .specify/extensions/git/scripts/powershell/git-common.ps1 | PowerShell git helpers (branch validation, etc.) |
| .specify/extensions/git/scripts/powershell/auto-commit.ps1 | PowerShell auto-commit implementation |
| .claude/skills/speckit-plan/SKILL.md | Claude skill definition for plan step |
| .claude/skills/speckit-tasks/SKILL.md | Claude skill definition for tasks step |
| .claude/skills/speckit-taskstoissues/SKILL.md | Claude skill for converting tasks to GitHub issues |
| .claude/skills/speckit-analyze/SKILL.md | Claude skill for read-only consistency analysis |
| .claude/skills/speckit-constitution/SKILL.md | Claude skill for constitution updates |
| .claude/skills/speckit-git-feature/SKILL.md | Claude skill mapping for git feature command |
| .claude/skills/speckit-git-validate/SKILL.md | Claude skill mapping for git validate command |
| .claude/skills/speckit-git-remote/SKILL.md | Claude skill mapping for git remote command |
| .claude/skills/speckit-git-initialize/SKILL.md | Claude skill mapping for git initialize command |
| .claude/skills/speckit-git-commit/SKILL.md | Claude skill mapping for git commit command |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| # Get feature paths and validate branch | ||
| _paths_output=$(get_feature_paths) || { echo "ERROR: Failed to resolve feature paths" >&2; exit 1; } | ||
| eval "$_paths_output" | ||
| unset _paths_output | ||
| check_feature_branch "$CURRENT_BRANCH" "$HAS_GIT" || exit 1 | ||
|
|
| **Parity gate (CR-004)**: `old-spec/` may be deleted only when this ledger has zero `Unprocessed` | ||
| rows and every retained item is present in the canonical source. **Status: NOT yet eligible** | ||
| (populated during US3). |
| - `Disposition` ∈ {`Migrated`, `Retained`, `Retired`}. | ||
| - `Disposition = Retired` (or superseded) ⇒ `Reason` MUST be non-empty (CR-001). | ||
| - `Disposition ≠ Retired` ⇒ `New location` MUST point at the canonical anchor. | ||
| - `Id preserved?` MUST be `true` for every `FR/NFR/MS` identifier (CR-006). |
| | Area | Feature | Backend | Status | Code area | Test | Constraints | | ||
| | --- | --- | --- | --- | --- | --- | --- | | ||
| | Selection | `[Transpile]`, `[TranspileAssembly]`, `[Ignore]` | TS | Implemented | `CSharpSourceFrontend.cs`, `src/Metano/Annotations/TranspileAttribute.cs` | `tests/Metano.Tests/AttributeTranspileTests.cs` | `[Ignore]` is the .NET-only boundary — transpilable code may not reference ignored types (MS0013). | | ||
|
|
No description provided.