diff --git a/.attest.json b/.attest.json new file mode 100644 index 00000000..ba4a0631 --- /dev/null +++ b/.attest.json @@ -0,0 +1,4 @@ +{ + "requireAttestation": true, + "requireTestsPassed": true +} diff --git a/.augur.toml b/.augur.toml new file mode 100644 index 00000000..031b4599 --- /dev/null +++ b/.augur.toml @@ -0,0 +1,3 @@ +[thresholds] +review = 35 +block = 65 diff --git a/.claude/commands/specsync/create-change.md b/.claude/commands/specsync/create-change.md new file mode 100644 index 00000000..04707ccc --- /dev/null +++ b/.claude/commands/specsync/create-change.md @@ -0,0 +1,10 @@ +--- +description: Create and guide a verified spec-sync SDD change through its deterministic interview +argument-hint: +--- + +1. Run `specsync change new "$ARGUMENTS" --json`. +2. Read the returned `questions` array and interview the user one question at a time. +3. Record each answer with `specsync change answer --json`. +4. Continue until the question list is empty, then show the selected artifacts and next action. +5. Do not approve, implement, verify, accept, or archive until the corresponding human gate or work stage is reached. diff --git a/.claude/commands/specsync/create-spec.md b/.claude/commands/specsync/create-spec.md new file mode 100644 index 00000000..bb420ae2 --- /dev/null +++ b/.claude/commands/specsync/create-spec.md @@ -0,0 +1,40 @@ +--- +description: Scaffold a new spec-sync module spec from a module name or a natural-language feature description (full scaffold by default, or minimal with --minimal) +argument-hint: [--minimal] +--- + +Create a new spec-sync module spec. + +Arguments: `$ARGUMENTS` + +1. Parse the arguments above. If they contain `--minimal` (in any position), + remove that flag and remember that minimal mode was requested. Preserve all + other text exactly; do not choose a module name yet. +2. Classify the complete remaining text. It will be one of: + - **A bare module name** — a short identifier like `auth-service` or + `billing`. Use it as-is. + - **A free-text feature description** — a sentence or phrase describing + what to build, e.g. `"I want a feature that lets users export their + data as CSV"`. In this case, invent a short, kebab-case module name that + captures the idea (e.g. `csv-export`). If the right name is ambiguous, + ask the user to confirm or rename it before continuing. Keep the full + description at hand — you'll use it in step 5. +3. If minimal mode was requested, run: + ``` + specsync new + ``` + This creates a minimal spec only (no companion files). +4. Otherwise (default), run: + ``` + specsync scaffold + ``` + This creates the spec, companion files (`tasks.md`, `requirements.md`, + `context.md`, `testing.md`, and `design.md` if `companions.design` is + enabled), a registry entry, and auto-detects related source files. +5. Open the newly created `specs//.spec.md` and fill + in the `Purpose`, `Requirements`, and `Public API` sections. If a free-text + description was given in step 2, use it directly to draft these sections — + ask clarifying questions if it's underspecified, but do not leave the + sections as unfilled placeholder text. Do the same for `requirements.md` + (acceptance criteria) and `tasks.md` (initial task breakdown), if present. +6. Run `specsync check` to confirm the new spec passes validation. diff --git a/.claude/skills/spec-sync/SKILL.md b/.claude/skills/spec-sync/SKILL.md new file mode 100644 index 00000000..de24d12d --- /dev/null +++ b/.claude/skills/spec-sync/SKILL.md @@ -0,0 +1,75 @@ +--- +name: spec-sync +description: Keep markdown module specs in specs// synchronized with source code using spec-sync. Use this whenever creating, editing, or reviewing code in a module that has (or should have) a spec, or whenever the user mentions specs, spec-sync, companion files (tasks.md/requirements.md/context.md/testing.md/design.md), or asks to add/update a module's documentation. +--- + +# Spec-Sync Workflow + +This project uses [spec-sync](https://github.com/CorvidLabs/spec-sync) for bidirectional spec-to-code validation. Specs live in `specs//.spec.md`. + +## Companion files + +## Verified SDD change lifecycle (5.0) + +For every meaningful source, test, public documentation, schema, or configuration change: + +1. Run `specsync change new "" --json` and conduct the returned interview with the user. +2. Use `specsync change answer --json` until no questions remain. +3. Complete the adaptively selected artifacts and semantic deltas. Requirements use stable + `REQ--` IDs, a normative SHALL statement, and acceptance criteria. +4. Ask the user for the definition approval, then run `specsync change approve `. +5. Run `specsync change start ` before editing implementation code. +6. Keep tasks and artifacts current, then run `specsync change verify `. +7. Present verification evidence and ask for closing approval. Only after explicit approval, + run `specsync change accept `; archive separately with `specsync change archive `. + +Never invent or self-grant either human approval. If an approved definition changes, its digest +becomes stale and must be approved again. `specsync check` validates canonical specs plus approved +active deltas, requirement-to-test evidence, change coverage, and CI gates. + +Each canonical spec may have policy-selected companion files. Read and update the ones present; do not create empty companions only for ceremony: + +- **`tasks.md`** — Work items for this module. Check off tasks (`- [x]`) as you complete them. Add new tasks if you discover work needed. +- **`requirements.md`** — Acceptance criteria and user stories. These are permanent invariants, not tasks — do not check them off. Update if requirements change. +- **`context.md`** — Architectural decisions, key files, and current status. Update when you make design decisions or change what's in progress. +- **`testing.md`** — Test strategy: automated test locations, manual QA checklists, and edge cases/boundary conditions. +- **`design.md`** *(opt-in)* — Layout, component hierarchy, design tokens, and asset references. Present when `companions.design` is enabled in config. + +## Before modifying any module + +1. Read the relevant spec in `specs//.spec.md` +2. Read whichever companion files are present (`requirements.md`, `tasks.md`, `context.md`, `testing.md`, `design.md`, or project-defined files) +3. After changes, run `specsync check` to verify specs still pass + +## After completing work + +1. Mark completed items in `tasks.md` — check off finished tasks, add new ones discovered +2. Update `context.md` — record decisions made, update current status +3. If requirements changed, update `requirements.md` acceptance criteria +4. If test coverage changed, update `testing.md` with new test files or edge cases +5. If UI/layout changed, update `design.md` with revised layout, components, or tokens + +## Before creating a PR + +Run `specsync check --strict` — all specs must pass with zero warnings. + +## When adding new modules + +Run `specsync scaffold ` to create a spec, companion files, a registry +entry, and auto-detected source files — or `specsync new ` for a +minimal spec-only draft. Complete the spec before writing code. The +`/specsync:create-spec` command (or tool-equivalent) runs this for you, and +accepts either a bare module name or a natural-language feature description +(e.g. `/specsync:create-spec "I want a feature that lets users export their +data as CSV"`) — pass a description and it will pick a module name and use +the description to draft the spec's Purpose and Requirements. + +## Key commands + +- `specsync check` — validate all specs against source code +- `specsync check --json` — machine-readable validation output +- `specsync coverage` — show which modules lack specs +- `specsync score` — quality score for each spec (0-100) +- `specsync scaffold ` — full scaffold: spec + companions + registry entry + source detection +- `specsync new ` — quick-create a minimal spec (add `--full` for companions) +- `specsync resolve --remote` — verify cross-project dependencies diff --git a/.codex/skills/spec-sync/SKILL.md b/.codex/skills/spec-sync/SKILL.md new file mode 100644 index 00000000..de24d12d --- /dev/null +++ b/.codex/skills/spec-sync/SKILL.md @@ -0,0 +1,75 @@ +--- +name: spec-sync +description: Keep markdown module specs in specs// synchronized with source code using spec-sync. Use this whenever creating, editing, or reviewing code in a module that has (or should have) a spec, or whenever the user mentions specs, spec-sync, companion files (tasks.md/requirements.md/context.md/testing.md/design.md), or asks to add/update a module's documentation. +--- + +# Spec-Sync Workflow + +This project uses [spec-sync](https://github.com/CorvidLabs/spec-sync) for bidirectional spec-to-code validation. Specs live in `specs//.spec.md`. + +## Companion files + +## Verified SDD change lifecycle (5.0) + +For every meaningful source, test, public documentation, schema, or configuration change: + +1. Run `specsync change new "" --json` and conduct the returned interview with the user. +2. Use `specsync change answer --json` until no questions remain. +3. Complete the adaptively selected artifacts and semantic deltas. Requirements use stable + `REQ--` IDs, a normative SHALL statement, and acceptance criteria. +4. Ask the user for the definition approval, then run `specsync change approve `. +5. Run `specsync change start ` before editing implementation code. +6. Keep tasks and artifacts current, then run `specsync change verify `. +7. Present verification evidence and ask for closing approval. Only after explicit approval, + run `specsync change accept `; archive separately with `specsync change archive `. + +Never invent or self-grant either human approval. If an approved definition changes, its digest +becomes stale and must be approved again. `specsync check` validates canonical specs plus approved +active deltas, requirement-to-test evidence, change coverage, and CI gates. + +Each canonical spec may have policy-selected companion files. Read and update the ones present; do not create empty companions only for ceremony: + +- **`tasks.md`** — Work items for this module. Check off tasks (`- [x]`) as you complete them. Add new tasks if you discover work needed. +- **`requirements.md`** — Acceptance criteria and user stories. These are permanent invariants, not tasks — do not check them off. Update if requirements change. +- **`context.md`** — Architectural decisions, key files, and current status. Update when you make design decisions or change what's in progress. +- **`testing.md`** — Test strategy: automated test locations, manual QA checklists, and edge cases/boundary conditions. +- **`design.md`** *(opt-in)* — Layout, component hierarchy, design tokens, and asset references. Present when `companions.design` is enabled in config. + +## Before modifying any module + +1. Read the relevant spec in `specs//.spec.md` +2. Read whichever companion files are present (`requirements.md`, `tasks.md`, `context.md`, `testing.md`, `design.md`, or project-defined files) +3. After changes, run `specsync check` to verify specs still pass + +## After completing work + +1. Mark completed items in `tasks.md` — check off finished tasks, add new ones discovered +2. Update `context.md` — record decisions made, update current status +3. If requirements changed, update `requirements.md` acceptance criteria +4. If test coverage changed, update `testing.md` with new test files or edge cases +5. If UI/layout changed, update `design.md` with revised layout, components, or tokens + +## Before creating a PR + +Run `specsync check --strict` — all specs must pass with zero warnings. + +## When adding new modules + +Run `specsync scaffold ` to create a spec, companion files, a registry +entry, and auto-detected source files — or `specsync new ` for a +minimal spec-only draft. Complete the spec before writing code. The +`/specsync:create-spec` command (or tool-equivalent) runs this for you, and +accepts either a bare module name or a natural-language feature description +(e.g. `/specsync:create-spec "I want a feature that lets users export their +data as CSV"`) — pass a description and it will pick a module name and use +the description to draft the spec's Purpose and Requirements. + +## Key commands + +- `specsync check` — validate all specs against source code +- `specsync check --json` — machine-readable validation output +- `specsync coverage` — show which modules lack specs +- `specsync score` — quality score for each spec (0-100) +- `specsync scaffold ` — full scaffold: spec + companions + registry entry + source detection +- `specsync new ` — quick-create a minimal spec (add `--full` for companions) +- `specsync resolve --remote` — verify cross-project dependencies diff --git a/.cursor/commands/specsync-create-change.md b/.cursor/commands/specsync-create-change.md new file mode 100644 index 00000000..49402f37 --- /dev/null +++ b/.cursor/commands/specsync-create-change.md @@ -0,0 +1,9 @@ +Create a verified spec-sync SDD change. + +Arguments: $ARGUMENTS + +1. Run `specsync change new "$ARGUMENTS" --json`. +2. Read the returned `questions` array and interview the user one question at a time. +3. Record each answer with `specsync change answer --json`. +4. Continue until the question list is empty, then show the selected artifacts and next action. +5. Do not approve, implement, verify, accept, or archive until the corresponding human gate or work stage is reached. diff --git a/.cursor/commands/specsync-create-spec.md b/.cursor/commands/specsync-create-spec.md new file mode 100644 index 00000000..84b88c73 --- /dev/null +++ b/.cursor/commands/specsync-create-spec.md @@ -0,0 +1,34 @@ +Create a new spec-sync module spec. + +Arguments: $ARGUMENTS + +1. Remove `--minimal` wherever it appears and remember that minimal mode was + requested. Preserve the complete remaining text; do not tokenize it yet. +2. Classify the complete remaining text: + - **A bare module name** — a short identifier like `auth-service` or + `billing`, matching `^[A-Za-z0-9][A-Za-z0-9._-]*$`. Use it as-is. + - **A free-text feature description** — a sentence or phrase describing + what to build, e.g. `"I want a feature that lets users export their + data as CSV"`. In this case, invent a short, kebab-case module name that + captures the idea (e.g. `csv-export`). If the right name is ambiguous, + ask the user to confirm or rename it before continuing. Keep the full + description at hand — you'll use it in step 5. +3. If minimal mode was requested, run: + ``` + specsync new + ``` + This creates a minimal spec only (no companion files). +4. Otherwise (default), run: + ``` + specsync scaffold + ``` + This creates the spec, companion files (`tasks.md`, `requirements.md`, + `context.md`, `testing.md`, and `design.md` if `companions.design` is + enabled), a registry entry, and auto-detects related source files. +5. Open the newly created `specs//.spec.md` and fill + in the `Purpose`, `Requirements`, and `Public API` sections. If a free-text + description was given in step 2, use it directly to draft these sections — + ask clarifying questions if it's underspecified, but do not leave the + sections as unfilled placeholder text. Do the same for `requirements.md` + (acceptance criteria) and `tasks.md` (initial task breakdown), if present. +6. Run `specsync check` to confirm the new spec passes validation. diff --git a/.cursor/skills/spec-sync/SKILL.md b/.cursor/skills/spec-sync/SKILL.md new file mode 100644 index 00000000..de24d12d --- /dev/null +++ b/.cursor/skills/spec-sync/SKILL.md @@ -0,0 +1,75 @@ +--- +name: spec-sync +description: Keep markdown module specs in specs// synchronized with source code using spec-sync. Use this whenever creating, editing, or reviewing code in a module that has (or should have) a spec, or whenever the user mentions specs, spec-sync, companion files (tasks.md/requirements.md/context.md/testing.md/design.md), or asks to add/update a module's documentation. +--- + +# Spec-Sync Workflow + +This project uses [spec-sync](https://github.com/CorvidLabs/spec-sync) for bidirectional spec-to-code validation. Specs live in `specs//.spec.md`. + +## Companion files + +## Verified SDD change lifecycle (5.0) + +For every meaningful source, test, public documentation, schema, or configuration change: + +1. Run `specsync change new "" --json` and conduct the returned interview with the user. +2. Use `specsync change answer --json` until no questions remain. +3. Complete the adaptively selected artifacts and semantic deltas. Requirements use stable + `REQ--` IDs, a normative SHALL statement, and acceptance criteria. +4. Ask the user for the definition approval, then run `specsync change approve `. +5. Run `specsync change start ` before editing implementation code. +6. Keep tasks and artifacts current, then run `specsync change verify `. +7. Present verification evidence and ask for closing approval. Only after explicit approval, + run `specsync change accept `; archive separately with `specsync change archive `. + +Never invent or self-grant either human approval. If an approved definition changes, its digest +becomes stale and must be approved again. `specsync check` validates canonical specs plus approved +active deltas, requirement-to-test evidence, change coverage, and CI gates. + +Each canonical spec may have policy-selected companion files. Read and update the ones present; do not create empty companions only for ceremony: + +- **`tasks.md`** — Work items for this module. Check off tasks (`- [x]`) as you complete them. Add new tasks if you discover work needed. +- **`requirements.md`** — Acceptance criteria and user stories. These are permanent invariants, not tasks — do not check them off. Update if requirements change. +- **`context.md`** — Architectural decisions, key files, and current status. Update when you make design decisions or change what's in progress. +- **`testing.md`** — Test strategy: automated test locations, manual QA checklists, and edge cases/boundary conditions. +- **`design.md`** *(opt-in)* — Layout, component hierarchy, design tokens, and asset references. Present when `companions.design` is enabled in config. + +## Before modifying any module + +1. Read the relevant spec in `specs//.spec.md` +2. Read whichever companion files are present (`requirements.md`, `tasks.md`, `context.md`, `testing.md`, `design.md`, or project-defined files) +3. After changes, run `specsync check` to verify specs still pass + +## After completing work + +1. Mark completed items in `tasks.md` — check off finished tasks, add new ones discovered +2. Update `context.md` — record decisions made, update current status +3. If requirements changed, update `requirements.md` acceptance criteria +4. If test coverage changed, update `testing.md` with new test files or edge cases +5. If UI/layout changed, update `design.md` with revised layout, components, or tokens + +## Before creating a PR + +Run `specsync check --strict` — all specs must pass with zero warnings. + +## When adding new modules + +Run `specsync scaffold ` to create a spec, companion files, a registry +entry, and auto-detected source files — or `specsync new ` for a +minimal spec-only draft. Complete the spec before writing code. The +`/specsync:create-spec` command (or tool-equivalent) runs this for you, and +accepts either a bare module name or a natural-language feature description +(e.g. `/specsync:create-spec "I want a feature that lets users export their +data as CSV"`) — pass a description and it will pick a module name and use +the description to draft the spec's Purpose and Requirements. + +## Key commands + +- `specsync check` — validate all specs against source code +- `specsync check --json` — machine-readable validation output +- `specsync coverage` — show which modules lack specs +- `specsync score` — quality score for each spec (0-100) +- `specsync scaffold ` — full scaffold: spec + companions + registry entry + source detection +- `specsync new ` — quick-create a minimal spec (add `--full` for companions) +- `specsync resolve --remote` — verify cross-project dependencies diff --git a/.gemini/commands/specsync/create-change.toml b/.gemini/commands/specsync/create-change.toml new file mode 100644 index 00000000..bf8185af --- /dev/null +++ b/.gemini/commands/specsync/create-change.toml @@ -0,0 +1,11 @@ +description = "Create and guide a verified spec-sync SDD change through its deterministic interview" + +prompt = """ +Arguments: {{args}} + +1. Run `specsync change new "{{args}}" --json`. +2. Read the returned `questions` array and interview the user one question at a time. +3. Record each answer with `specsync change answer --json`. +4. Continue until the question list is empty, then show the selected artifacts and next action. +5. Do not approve, implement, verify, accept, or archive until the corresponding human gate or work stage is reached. +""" diff --git a/.gemini/commands/specsync/create-spec.toml b/.gemini/commands/specsync/create-spec.toml new file mode 100644 index 00000000..6d347924 --- /dev/null +++ b/.gemini/commands/specsync/create-spec.toml @@ -0,0 +1,34 @@ +description = "Scaffold a new spec-sync module spec from a module name or a natural-language feature description (full scaffold by default, or minimal with --minimal)" + +prompt = """ +Create a new spec-sync module spec. + +Arguments: {{args}} + +1. Remove --minimal wherever it appears and remember that minimal mode was + requested. Preserve the complete remaining text; do not tokenize it yet. +2. Classify the complete remaining text: + - A bare module name - a short identifier like auth-service or billing, + matching ^[A-Za-z0-9][A-Za-z0-9._-]*$. Use it as-is. + - A free-text feature description - a sentence or phrase describing what + to build, e.g. "I want a feature that lets users export their data as + CSV". In this case, invent a short, kebab-case module name that captures + the idea (e.g. csv-export). If the right name is ambiguous, ask the user + to confirm or rename it before continuing. Keep the full description at + hand - you'll use it in step 5. +3. If minimal mode was requested, run: + specsync new + This creates a minimal spec only (no companion files). +4. Otherwise (default), run: + specsync scaffold + This creates the spec, companion files (tasks.md, requirements.md, + context.md, testing.md, and design.md if companions.design is enabled), + a registry entry, and auto-detects related source files. +5. Open the newly created specs//.spec.md and fill + in the Purpose, Requirements, and Public API sections. If a free-text + description was given in step 2, use it directly to draft these sections - + ask clarifying questions if it's underspecified, but do not leave the + sections as unfilled placeholder text. Do the same for requirements.md + (acceptance criteria) and tasks.md (initial task breakdown), if present. +6. Run specsync check to confirm the new spec passes validation. +""" diff --git a/.gemini/skills/spec-sync/SKILL.md b/.gemini/skills/spec-sync/SKILL.md new file mode 100644 index 00000000..de24d12d --- /dev/null +++ b/.gemini/skills/spec-sync/SKILL.md @@ -0,0 +1,75 @@ +--- +name: spec-sync +description: Keep markdown module specs in specs// synchronized with source code using spec-sync. Use this whenever creating, editing, or reviewing code in a module that has (or should have) a spec, or whenever the user mentions specs, spec-sync, companion files (tasks.md/requirements.md/context.md/testing.md/design.md), or asks to add/update a module's documentation. +--- + +# Spec-Sync Workflow + +This project uses [spec-sync](https://github.com/CorvidLabs/spec-sync) for bidirectional spec-to-code validation. Specs live in `specs//.spec.md`. + +## Companion files + +## Verified SDD change lifecycle (5.0) + +For every meaningful source, test, public documentation, schema, or configuration change: + +1. Run `specsync change new "" --json` and conduct the returned interview with the user. +2. Use `specsync change answer --json` until no questions remain. +3. Complete the adaptively selected artifacts and semantic deltas. Requirements use stable + `REQ--` IDs, a normative SHALL statement, and acceptance criteria. +4. Ask the user for the definition approval, then run `specsync change approve `. +5. Run `specsync change start ` before editing implementation code. +6. Keep tasks and artifacts current, then run `specsync change verify `. +7. Present verification evidence and ask for closing approval. Only after explicit approval, + run `specsync change accept `; archive separately with `specsync change archive `. + +Never invent or self-grant either human approval. If an approved definition changes, its digest +becomes stale and must be approved again. `specsync check` validates canonical specs plus approved +active deltas, requirement-to-test evidence, change coverage, and CI gates. + +Each canonical spec may have policy-selected companion files. Read and update the ones present; do not create empty companions only for ceremony: + +- **`tasks.md`** — Work items for this module. Check off tasks (`- [x]`) as you complete them. Add new tasks if you discover work needed. +- **`requirements.md`** — Acceptance criteria and user stories. These are permanent invariants, not tasks — do not check them off. Update if requirements change. +- **`context.md`** — Architectural decisions, key files, and current status. Update when you make design decisions or change what's in progress. +- **`testing.md`** — Test strategy: automated test locations, manual QA checklists, and edge cases/boundary conditions. +- **`design.md`** *(opt-in)* — Layout, component hierarchy, design tokens, and asset references. Present when `companions.design` is enabled in config. + +## Before modifying any module + +1. Read the relevant spec in `specs//.spec.md` +2. Read whichever companion files are present (`requirements.md`, `tasks.md`, `context.md`, `testing.md`, `design.md`, or project-defined files) +3. After changes, run `specsync check` to verify specs still pass + +## After completing work + +1. Mark completed items in `tasks.md` — check off finished tasks, add new ones discovered +2. Update `context.md` — record decisions made, update current status +3. If requirements changed, update `requirements.md` acceptance criteria +4. If test coverage changed, update `testing.md` with new test files or edge cases +5. If UI/layout changed, update `design.md` with revised layout, components, or tokens + +## Before creating a PR + +Run `specsync check --strict` — all specs must pass with zero warnings. + +## When adding new modules + +Run `specsync scaffold ` to create a spec, companion files, a registry +entry, and auto-detected source files — or `specsync new ` for a +minimal spec-only draft. Complete the spec before writing code. The +`/specsync:create-spec` command (or tool-equivalent) runs this for you, and +accepts either a bare module name or a natural-language feature description +(e.g. `/specsync:create-spec "I want a feature that lets users export their +data as CSV"`) — pass a description and it will pick a module name and use +the description to draft the spec's Purpose and Requirements. + +## Key commands + +- `specsync check` — validate all specs against source code +- `specsync check --json` — machine-readable validation output +- `specsync coverage` — show which modules lack specs +- `specsync score` — quality score for each spec (0-100) +- `specsync scaffold ` — full scaffold: spec + companions + registry entry + source detection +- `specsync new ` — quick-create a minimal spec (add `--full` for companions) +- `specsync resolve --remote` — verify cross-project dependencies diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8e4dd07d..ec99ad3d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -106,28 +106,37 @@ jobs: spec-check: runs-on: ubuntu-latest - timeout-minutes: 15 + timeout-minutes: 30 outputs: body: ${{ steps.specsync.outputs.body }} steps: - uses: actions/checkout@v5 + with: + fetch-depth: 0 + - uses: dtolnay/rust-toolchain@stable + - uses: Swatinem/rust-cache@v2 + - name: Build the branch Fledge CLI + run: cargo build --locked + - name: Add the branch Fledge CLI to PATH + run: echo "${{ github.workspace }}/target/debug" >> "$GITHUB_PATH" - name: Run spec-sync id: specsync - uses: CorvidLabs/spec-sync@v4.3.2 + uses: CorvidLabs/spec-sync@59bbfa766c6cce01ab815ab47db195b0629cc014 # v5.0.1 with: - # 4.8.0 under-detects exports in multi-file Rust specs and makes this - # strict gate false-fail. Keep the newest verified release pinned - # until spec-sync publishes the scanner fix. - version: 4.7.1 + version: 5.0.1 strict: true comment: false # Enforce reverse coverage: every production source file must be # claimed by a spec (test-only + template CI files are excluded in # .specsync/config.toml). Fails CI if an unclaimed file is added (#448). require-coverage: 100 + lifecycle-enforce: true env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - name: Enforce SpecSync change workspaces + run: specsync change check --strict --require-coverage 100 + corvid-pet: runs-on: ubuntu-latest timeout-minutes: 10 @@ -197,7 +206,7 @@ jobs: attest: name: Record attestation runs-on: ubuntu-latest - needs: [test, lint, audit, spec-check] + needs: [test, lint, audit, spec-check, integration] if: github.event_name == 'push' && github.ref == 'refs/heads/main' # contents: write lets the step push refs/notes/attest. permissions: @@ -225,7 +234,7 @@ jobs: git config user.name "github-actions[bot]" git fetch origin "+refs/notes/attest:refs/notes/attest" 2>/dev/null || true if "$bin" sign --commit HEAD --reviewer agent:ci --confidence 0.9 --tests-passed \ - --verdict proceed --note "CI: cargo test + lint + audit + spec-check green" \ + --verdict proceed --note "CI: tests + integration + lint + audit + spec-check green" \ && git push origin refs/notes/attest ; then echo "attestation recorded for $(git rev-parse --short HEAD)" else diff --git a/.github/workflows/trust.yml b/.github/workflows/trust.yml new file mode 100644 index 00000000..1843df36 --- /dev/null +++ b/.github/workflows/trust.yml @@ -0,0 +1,29 @@ +name: trust + +on: + pull_request: + push: + branches: [main] + +permissions: + contents: read + +jobs: + trust: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v5 + with: + fetch-depth: 0 + - uses: dtolnay/rust-toolchain@stable + with: + components: rustfmt, clippy + - uses: Swatinem/rust-cache@v2 + - name: CorvidLabs Trust gate + id: trust + uses: CorvidLabs/trust@9d32b5786d2e9e4d39fc581c0091c721ee3d4226 # v1.0.0 + + - name: Check managed agent rules + run: | + grep -q "CorvidLabs trust toolchain: BEGIN" AGENTS.md + grep -q "CorvidLabs trust toolchain: END" AGENTS.md diff --git a/.specsync/adoption-report.json b/.specsync/adoption-report.json new file mode 100644 index 00000000..7479e239 --- /dev/null +++ b/.specsync/adoption-report.json @@ -0,0 +1,165 @@ +{ + "bootstrap_policy": { + "base_commit": "695ca94a54371e380be1ffbb603e3ee5cc387454", + "digest": "5e8da30e6bfa76381497a516801b6d2f606d7efcd70ebde615e795642abfc76b", + "path": ".specsync/sdd.json" + }, + "generated_at": 1783831218, + "requirements_needing_ids": [ + { + "action": "review and assign one stable ID per durable requirement", + "path": "specs/init/requirements.md", + "suggested_first_id": "REQ-init-001" + }, + { + "action": "review and assign one stable ID per durable requirement", + "path": "specs/validate/requirements.md", + "suggested_first_id": "REQ-validate-001" + }, + { + "action": "review and assign one stable ID per durable requirement", + "path": "specs/llm/requirements.md", + "suggested_first_id": "REQ-llm-001" + }, + { + "action": "review and assign one stable ID per durable requirement", + "path": "specs/introspect/requirements.md", + "suggested_first_id": "REQ-introspect-001" + }, + { + "action": "review and assign one stable ID per durable requirement", + "path": "specs/ask/requirements.md", + "suggested_first_id": "REQ-ask-001" + }, + { + "action": "review and assign one stable ID per durable requirement", + "path": "specs/changelog/requirements.md", + "suggested_first_id": "REQ-changelog-001" + }, + { + "action": "review and assign one stable ID per durable requirement", + "path": "specs/config/requirements.md", + "suggested_first_id": "REQ-config-001" + }, + { + "action": "review and assign one stable ID per durable requirement", + "path": "specs/create_template/requirements.md", + "suggested_first_id": "REQ-create-template-001" + }, + { + "action": "review and assign one stable ID per durable requirement", + "path": "specs/doctor/requirements.md", + "suggested_first_id": "REQ-doctor-001" + }, + { + "action": "review and assign one stable ID per durable requirement", + "path": "specs/plugin/requirements.md", + "suggested_first_id": "REQ-plugin-001" + }, + { + "action": "review and assign one stable ID per durable requirement", + "path": "specs/spec/requirements.md", + "suggested_first_id": "REQ-spec-001" + }, + { + "action": "review and assign one stable ID per durable requirement", + "path": "specs/meta/requirements.md", + "suggested_first_id": "REQ-meta-001" + }, + { + "action": "review and assign one stable ID per durable requirement", + "path": "specs/utils/requirements.md", + "suggested_first_id": "REQ-utils-001" + }, + { + "action": "review and assign one stable ID per durable requirement", + "path": "specs/release/requirements.md", + "suggested_first_id": "REQ-release-001" + }, + { + "action": "review and assign one stable ID per durable requirement", + "path": "specs/spinner/requirements.md", + "suggested_first_id": "REQ-spinner-001" + }, + { + "action": "review and assign one stable ID per durable requirement", + "path": "specs/lanes/requirements.md", + "suggested_first_id": "REQ-lanes-001" + }, + { + "action": "review and assign one stable ID per durable requirement", + "path": "specs/search/requirements.md", + "suggested_first_id": "REQ-search-001" + }, + { + "action": "review and assign one stable ID per durable requirement", + "path": "specs/envelope/requirements.md", + "suggested_first_id": "REQ-envelope-001" + }, + { + "action": "review and assign one stable ID per durable requirement", + "path": "specs/publish/requirements.md", + "suggested_first_id": "REQ-publish-001" + }, + { + "action": "review and assign one stable ID per durable requirement", + "path": "specs/github/requirements.md", + "suggested_first_id": "REQ-github-001" + }, + { + "action": "review and assign one stable ID per durable requirement", + "path": "specs/ai/requirements.md", + "suggested_first_id": "REQ-ai-001" + }, + { + "action": "review and assign one stable ID per durable requirement", + "path": "specs/review/requirements.md", + "suggested_first_id": "REQ-review-001" + }, + { + "action": "review and assign one stable ID per durable requirement", + "path": "specs/work/requirements.md", + "suggested_first_id": "REQ-work-001" + }, + { + "action": "review and assign one stable ID per durable requirement", + "path": "specs/prompts/requirements.md", + "suggested_first_id": "REQ-prompts-001" + }, + { + "action": "review and assign one stable ID per durable requirement", + "path": "specs/watch/requirements.md", + "suggested_first_id": "REQ-watch-001" + }, + { + "action": "review and assign one stable ID per durable requirement", + "path": "specs/templates/requirements.md", + "suggested_first_id": "REQ-templates-001" + }, + { + "action": "review and assign one stable ID per durable requirement", + "path": "specs/trust/requirements.md", + "suggested_first_id": "REQ-trust-001" + }, + { + "action": "review and assign one stable ID per durable requirement", + "path": "specs/run/requirements.md", + "suggested_first_id": "REQ-run-001" + }, + { + "action": "review and assign one stable ID per durable requirement", + "path": "specs/versioning/requirements.md", + "suggested_first_id": "REQ-versioning-001" + }, + { + "action": "review and assign one stable ID per durable requirement", + "path": "specs/main/requirements.md", + "suggested_first_id": "REQ-main-001" + }, + { + "action": "review and assign one stable ID per durable requirement", + "path": "specs/remote/requirements.md", + "suggested_first_id": "REQ-remote-001" + } + ] +} diff --git a/.specsync/change.lock b/.specsync/change.lock new file mode 100644 index 00000000..e69de29b diff --git a/.specsync/changes/CHG-0001-adopt-trust-1-and-specsync-5/approvals.json b/.specsync/changes/CHG-0001-adopt-trust-1-and-specsync-5/approvals.json new file mode 100644 index 00000000..8be20908 --- /dev/null +++ b/.specsync/changes/CHG-0001-adopt-trust-1-and-specsync-5/approvals.json @@ -0,0 +1,81 @@ +{ + "approvals": [ + { + "gate": "definition", + "actor": "user:0xLeif", + "timestamp": 1783831307, + "digest": "a4efac74ec54e8951785201cf048510fd9164e1ff04edfc1b1f6e312d17ff1a6", + "note": "Authorized by the approved organization-wide SpecSync 5 / Trust 1 migration plan." + }, + { + "gate": "definition", + "actor": "0xLeif", + "timestamp": 1783904137, + "digest": "d1f8bdbac64b57504f016a4ac604863117e2afeb74cd9d3e55d6942869e60165", + "note": "Reviewed Fledge governance adoption after placeholder-free template verification, 100% strict coverage, hosted technical matrices, and required trust protection." + }, + { + "gate": "definition", + "actor": "0xLeif", + "timestamp": 1783913704, + "digest": "e501068a05e6748686f9e67c2abc8740da52e6d7df64770bbb7c6bd6e8d2c391", + "note": "Approved final strict Trust policy, SpecSync 5.0.1 scaffolding, build-manifest governance, and substantive template regression scope." + }, + { + "gate": "definition", + "actor": "0xLeif", + "timestamp": 1783917629, + "digest": "e501068a05e6748686f9e67c2abc8740da52e6d7df64770bbb7c6bd6e8d2c391", + "note": "Approved non-recursive native verification lane after hosted Trust and spec-check cancellation exposed recursive contract execution" + }, + { + "gate": "definition", + "actor": "0xLeif", + "timestamp": 1783918310, + "digest": "e501068a05e6748686f9e67c2abc8740da52e6d7df64770bbb7c6bd6e8d2c391", + "note": "Approved standard-profile progressive provenance and complete managed-marker enforcement" + }, + { + "gate": "acceptance", + "actor": "0xLeif", + "timestamp": 1783918406, + "digest": "e6dceae128713731a5202a5b7de38b8be129f7fc1eb2f82cb1742725962c0177", + "note": null + }, + { + "gate": "acceptance", + "actor": "0xLeif", + "timestamp": 1783922639, + "digest": "29aef45929401f47b9d945bf73a850032af3efbaf9d7fd35bfb55f3ee748aca1", + "note": "Accepted after renewing verification for the non-recursive governance test lane." + }, + { + "gate": "acceptance", + "actor": "0xLeif", + "timestamp": 1783923481, + "digest": "1b71dcb19cf474784ccc9aa4e4bfe4aee685f20941b368bb96fd7bf3d451dc38", + "note": "Accepted after addressing final policy and semantic requirement review findings." + }, + { + "gate": "acceptance", + "actor": "0xLeif", + "timestamp": 1783924404, + "digest": "90d9f68e49630a9a86bb3eba03f1a74f7ba4aa199252c650e57a8a712a4d0e8c", + "note": "Accepted after strict Trust workflow and final generated-policy review fixes." + }, + { + "gate": "acceptance", + "actor": "0xLeif", + "timestamp": 1783924837, + "digest": "b672b2c889ec39d1cbf4f4dfe1afee382fe5a2ff47c29df81c43e111be5d5ec0", + "note": null + }, + { + "gate": "acceptance", + "actor": "0xLeif", + "timestamp": 1783925618, + "digest": "9abb81e538873dfec876e7f5ee2c41b3af11ef3215db9fb94501209640a0bde9", + "note": null + } + ] +} diff --git a/.specsync/changes/CHG-0001-adopt-trust-1-and-specsync-5/change.md b/.specsync/changes/CHG-0001-adopt-trust-1-and-specsync-5/change.md new file mode 100644 index 00000000..9a39cead --- /dev/null +++ b/.specsync/changes/CHG-0001-adopt-trust-1-and-specsync-5/change.md @@ -0,0 +1,24 @@ +--- +id: CHG-0001-adopt-trust-1-and-specsync-5 +state: accepted +type: migration +base_commit: 02550b3fac7e9a5ca12f5aecc1773f89972820f0 +--- + +# Adopt Trust 1 and SpecSync 5 + +## Intent + +Adopt Trust 1 and SpecSync 5 + +## Affected Canonical Specs + +- None + +## Acceptance Criteria + +- Trust 1 runs the native verify lane; SpecSync 5.0.1 strict validation passes; all four agent integrations are installed; existing requirement semantics remain unchanged + +## No-spec Rationale + +Governance tooling and stable requirement identifiers do not change existing runtime semantics. diff --git a/.specsync/changes/CHG-0001-adopt-trust-1-and-specsync-5/context.md b/.specsync/changes/CHG-0001-adopt-trust-1-and-specsync-5/context.md new file mode 100644 index 00000000..5a9e6fab --- /dev/null +++ b/.specsync/changes/CHG-0001-adopt-trust-1-and-specsync-5/context.md @@ -0,0 +1,8 @@ +--- +change: CHG-0001-adopt-trust-1-and-specsync-5 +artifact: context +--- + +# Context + +fledge is part of the organization-wide migration to SpecSync 5.0.1 and Trust 1.0.0. Existing build, test, release, signing, and publication workflows remain authoritative. diff --git a/.specsync/changes/CHG-0001-adopt-trust-1-and-specsync-5/design.md b/.specsync/changes/CHG-0001-adopt-trust-1-and-specsync-5/design.md new file mode 100644 index 00000000..fd0779b9 --- /dev/null +++ b/.specsync/changes/CHG-0001-adopt-trust-1-and-specsync-5/design.md @@ -0,0 +1,8 @@ +--- +change: CHG-0001-adopt-trust-1-and-specsync-5 +artifact: design +--- + +# Design + +A single immutable Trust action composes lifecycle, contract, risk, and progressive provenance checks. Specialized CI and standalone Atlas or signing workflows remain independent. diff --git a/.specsync/changes/CHG-0001-adopt-trust-1-and-specsync-5/docs.md b/.specsync/changes/CHG-0001-adopt-trust-1-and-specsync-5/docs.md new file mode 100644 index 00000000..370ed501 --- /dev/null +++ b/.specsync/changes/CHG-0001-adopt-trust-1-and-specsync-5/docs.md @@ -0,0 +1,8 @@ +--- +change: CHG-0001-adopt-trust-1-and-specsync-5 +artifact: docs +--- + +# Docs + +Contributor guidance and generated agent instructions describe the SpecSync 5 change lifecycle and unified Trust 1 gate. diff --git a/.specsync/changes/CHG-0001-adopt-trust-1-and-specsync-5/plan.md b/.specsync/changes/CHG-0001-adopt-trust-1-and-specsync-5/plan.md new file mode 100644 index 00000000..a008f3e1 --- /dev/null +++ b/.specsync/changes/CHG-0001-adopt-trust-1-and-specsync-5/plan.md @@ -0,0 +1,11 @@ +--- +change: CHG-0001-adopt-trust-1-and-specsync-5 +artifact: plan +--- + +# Plan + +1. Adopt the verified SDD lifecycle and stable requirement IDs. +2. Install all four agent integrations. +3. Run the native Fledge verify lane through Trust 1. +4. Preserve specialized workflows and validate hosted checks. diff --git a/.specsync/changes/CHG-0001-adopt-trust-1-and-specsync-5/research.md b/.specsync/changes/CHG-0001-adopt-trust-1-and-specsync-5/research.md new file mode 100644 index 00000000..7efbc678 --- /dev/null +++ b/.specsync/changes/CHG-0001-adopt-trust-1-and-specsync-5/research.md @@ -0,0 +1,8 @@ +--- +change: CHG-0001-adopt-trust-1-and-specsync-5 +artifact: research +--- + +# Research + +The repository's native tasks, workflow runners, contract coverage, requirement companions, and provenance policy were audited before adoption. diff --git a/.specsync/changes/CHG-0001-adopt-trust-1-and-specsync-5/state.json b/.specsync/changes/CHG-0001-adopt-trust-1-and-specsync-5/state.json new file mode 100644 index 00000000..512a66aa --- /dev/null +++ b/.specsync/changes/CHG-0001-adopt-trust-1-and-specsync-5/state.json @@ -0,0 +1,48 @@ +{ + "schema_version": 1, + "id": "CHG-0001-adopt-trust-1-and-specsync-5", + "slug": "adopt-trust-1-and-specsync-5", + "title": "Adopt Trust 1 and SpecSync 5", + "description": "Adopt Trust 1 and SpecSync 5", + "kind": "migration", + "state": "accepted", + "base_commit": "02550b3fac7e9a5ca12f5aecc1773f89972820f0", + "created_at": 1783831307, + "updated_at": 1783925618, + "affected_specs": [], + "affected_paths": [ + ".github/workflows/", + ".specsync/", + ".trust.toml", + ".augur.toml", + ".attest.json", + "AGENTS.md", + ".claude/", + ".cursor/", + ".codex/", + ".gemini/", + "fledge.toml", + "src/spec/commands.rs", + "src/templates.rs", + "specs/" + ], + "no_spec_change": true, + "no_spec_change_rationale": "Governance tooling and stable requirement identifiers do not change existing runtime semantics.", + "acceptance_criteria": [ + "Trust 1 runs the native verify lane; SpecSync 5.0.1 strict validation passes; all four agent integrations are installed; existing requirement semantics remain unchanged" + ], + "selected_artifacts": [ + "context", + "research", + "design", + "plan", + "tasks", + "testing", + "docs" + ], + "dependencies": [], + "answers": { + "architecture_risk": "yes", + "public_contract": "no" + } +} diff --git a/.specsync/changes/CHG-0001-adopt-trust-1-and-specsync-5/tasks.md b/.specsync/changes/CHG-0001-adopt-trust-1-and-specsync-5/tasks.md new file mode 100644 index 00000000..df7ab39c --- /dev/null +++ b/.specsync/changes/CHG-0001-adopt-trust-1-and-specsync-5/tasks.md @@ -0,0 +1,12 @@ +--- +change: CHG-0001-adopt-trust-1-and-specsync-5 +artifact: tasks +--- + +# Tasks + +- [x] Adopt SpecSync 5.0.1 and install agent integrations. +- [x] Configure Trust 1 with immutable action pins. +- [x] Preserve native validation and specialized workflows. +- [x] Pass hosted native, integration, lint, audit, template-validation, and CodeQL checks. +- [x] Require the green trust check on the protected branch. diff --git a/.specsync/changes/CHG-0001-adopt-trust-1-and-specsync-5/testing.md b/.specsync/changes/CHG-0001-adopt-trust-1-and-specsync-5/testing.md new file mode 100644 index 00000000..6c370a6b --- /dev/null +++ b/.specsync/changes/CHG-0001-adopt-trust-1-and-specsync-5/testing.md @@ -0,0 +1,12 @@ +--- +change: CHG-0001-adopt-trust-1-and-specsync-5 +artifact: testing +--- + +# Testing + +- Run the native Fledge verify lane. +- Run SpecSync strict validation at the committed threshold. +- Confirm all four agent integrations. +- Run Trust doctor and verification. +- Confirm hosted native and Trust checks pass. diff --git a/.specsync/changes/CHG-0001-adopt-trust-1-and-specsync-5/verification.json b/.specsync/changes/CHG-0001-adopt-trust-1-and-specsync-5/verification.json new file mode 100644 index 00000000..28c27dba --- /dev/null +++ b/.specsync/changes/CHG-0001-adopt-trust-1-and-specsync-5/verification.json @@ -0,0 +1,16 @@ +{ + "timestamp": 1783925618, + "commit": "abd4240b1699cf1f2fb79417641f0a82054b5972", + "contract_digest": "e501068a05e6748686f9e67c2abc8740da52e6d7df64770bbb7c6bd6e8d2c391", + "workspace_digest": "9a889f5a1f62f02e872ecbd4e3d055cff2603e7072ab66024d85816bc2c2bd25", + "acceptance_input_digest": "f562234962df8c999eae83354a041b963c0d89203f8c6bc235a5fa8b6b64cd94", + "passed": true, + "commands": [ + { + "command": "fledge lanes run verify-native", + "success": true, + "exit_code": 0 + } + ], + "requirement_ids": [] +} diff --git a/.specsync/changes/CHG-0002-update-corvid-stack-template-for-trust-1/approvals.json b/.specsync/changes/CHG-0002-update-corvid-stack-template-for-trust-1/approvals.json new file mode 100644 index 00000000..82563579 --- /dev/null +++ b/.specsync/changes/CHG-0002-update-corvid-stack-template-for-trust-1/approvals.json @@ -0,0 +1,81 @@ +{ + "approvals": [ + { + "gate": "definition", + "actor": "user:0xLeif", + "timestamp": 1783831331, + "digest": "3bef6eeeec488d6fb44252b8e3e755b94555f91d677f7d4731d69f9b8daf7421", + "note": "Authorized by the approved organization-wide SpecSync 5 / Trust 1 migration plan." + }, + { + "gate": "definition", + "actor": "user:0xLeif", + "timestamp": 1783831395, + "digest": "62b4cdc0055b7d9c77ee517b7549cd4ef23f69dc596edb23ecb0bffc5a332c68", + "note": "Authorized by the approved organization-wide SpecSync 5 / Trust 1 migration plan." + }, + { + "gate": "definition", + "actor": "0xLeif", + "timestamp": 1783904120, + "digest": "eba5b5589df084078203786c6f051df9378749313f2ffa761fddcff0e9d49c57", + "note": "Reviewed placeholder-free Corvid stack defaults and successful generated-project governance lane." + }, + { + "gate": "definition", + "actor": "0xLeif", + "timestamp": 1783917636, + "digest": "eba5b5589df084078203786c6f051df9378749313f2ffa761fddcff0e9d49c57", + "note": "Reapproved template migration for final workspace verification with the non-recursive native Fledge lane" + }, + { + "gate": "definition", + "actor": "0xLeif", + "timestamp": 1783918310, + "digest": "eba5b5589df084078203786c6f051df9378749313f2ffa761fddcff0e9d49c57", + "note": "Approved cross-platform git-based starter governance checks for generated Corvid stack projects" + }, + { + "gate": "acceptance", + "actor": "0xLeif", + "timestamp": 1783918406, + "digest": "49d121ae0fbf2b8f27c2317fc50b236ed4ef02011b00e9f1ab62ac88a6eeeebb", + "note": null + }, + { + "gate": "acceptance", + "actor": "0xLeif", + "timestamp": 1783922642, + "digest": "dd0475dd7f22aea80ecdb40a9ce20062d20bfa4ae6db6006b2b6915f0a35b44a", + "note": "Accepted after renewing verification against the final non-recursive governance lane." + }, + { + "gate": "acceptance", + "actor": "0xLeif", + "timestamp": 1783923481, + "digest": "d395258a462cf9cba7cf47abe6be4233715895293010ea39c78641c33a2b1957", + "note": "Accepted after final generated-template policy and local-gate review fixes." + }, + { + "gate": "acceptance", + "actor": "0xLeif", + "timestamp": 1783924408, + "digest": "b0fd1f2ce8e999ca1cbbfa1f2139a7e6610f32bf974e09922a7108b506066aff", + "note": "Accepted after committed-tree, complete-governance, and alternate-source-layout template validation." + }, + { + "gate": "acceptance", + "actor": "0xLeif", + "timestamp": 1783924858, + "digest": "170d5e1b7deb38150927144f92f7705d632a769b104e688e2562da1b19138f96", + "note": null + }, + { + "gate": "acceptance", + "actor": "0xLeif", + "timestamp": 1783925640, + "digest": "f585f05d994b3aca1007087c612db8ae8184227e6199c88f2484ffba2aa60ba9", + "note": null + } + ] +} diff --git a/.specsync/changes/CHG-0002-update-corvid-stack-template-for-trust-1/change.md b/.specsync/changes/CHG-0002-update-corvid-stack-template-for-trust-1/change.md new file mode 100644 index 00000000..3ec0544d --- /dev/null +++ b/.specsync/changes/CHG-0002-update-corvid-stack-template-for-trust-1/change.md @@ -0,0 +1,24 @@ +--- +id: CHG-0002-update-corvid-stack-template-for-trust-1 +state: accepted +type: migration +base_commit: 02550b3fac7e9a5ca12f5aecc1773f89972820f0 +--- + +# Update Corvid stack template for Trust 1 + +## Intent + +Update Corvid stack template for Trust 1 + +## Affected Canonical Specs + +- None + +## Acceptance Criteria + +- The Corvid stack template emits SpecSync 5.0.1 SDD and the immutable Trust 1 workflow + +## No-spec Rationale + +Template governance defaults do not change Fledge runtime behavior. diff --git a/.specsync/changes/CHG-0002-update-corvid-stack-template-for-trust-1/context.md b/.specsync/changes/CHG-0002-update-corvid-stack-template-for-trust-1/context.md new file mode 100644 index 00000000..e76c83e9 --- /dev/null +++ b/.specsync/changes/CHG-0002-update-corvid-stack-template-for-trust-1/context.md @@ -0,0 +1,9 @@ +--- +change: CHG-0002-update-corvid-stack-template-for-trust-1 +artifact: context +--- + +# Context + +The Corvid stack template previously emitted independently orchestrated governance actions and +SpecSync 4 defaults. New projects need the organization-standard SpecSync 5 and Trust 1 contract. diff --git a/.specsync/changes/CHG-0002-update-corvid-stack-template-for-trust-1/design.md b/.specsync/changes/CHG-0002-update-corvid-stack-template-for-trust-1/design.md new file mode 100644 index 00000000..f141eeee --- /dev/null +++ b/.specsync/changes/CHG-0002-update-corvid-stack-template-for-trust-1/design.md @@ -0,0 +1,9 @@ +--- +change: CHG-0002-update-corvid-stack-template-for-trust-1 +artifact: design +--- + +# Design + +Generate one immutable Trust action, a standard policy, and the SpecSync 5 SDD lifecycle while +leaving project-specific native verification in the Fledge verify lane. diff --git a/.specsync/changes/CHG-0002-update-corvid-stack-template-for-trust-1/docs.md b/.specsync/changes/CHG-0002-update-corvid-stack-template-for-trust-1/docs.md new file mode 100644 index 00000000..04285d15 --- /dev/null +++ b/.specsync/changes/CHG-0002-update-corvid-stack-template-for-trust-1/docs.md @@ -0,0 +1,8 @@ +--- +change: CHG-0002-update-corvid-stack-template-for-trust-1 +artifact: docs +--- + +# Docs + +The template itself is the supported documentation and scaffold for new CorvidLabs projects. diff --git a/.specsync/changes/CHG-0002-update-corvid-stack-template-for-trust-1/plan.md b/.specsync/changes/CHG-0002-update-corvid-stack-template-for-trust-1/plan.md new file mode 100644 index 00000000..719c3516 --- /dev/null +++ b/.specsync/changes/CHG-0002-update-corvid-stack-template-for-trust-1/plan.md @@ -0,0 +1,10 @@ +--- +change: CHG-0002-update-corvid-stack-template-for-trust-1 +artifact: plan +--- + +# Plan + +1. Replace the legacy template workflow with the immutable Trust 1 gate. +2. Add the SpecSync 5 lifecycle, version stamp, and standard Trust policy. +3. Validate the template and Fledge repository gates. diff --git a/.specsync/changes/CHG-0002-update-corvid-stack-template-for-trust-1/research.md b/.specsync/changes/CHG-0002-update-corvid-stack-template-for-trust-1/research.md new file mode 100644 index 00000000..08df1d15 --- /dev/null +++ b/.specsync/changes/CHG-0002-update-corvid-stack-template-for-trust-1/research.md @@ -0,0 +1,9 @@ +--- +change: CHG-0002-update-corvid-stack-template-for-trust-1 +artifact: research +--- + +# Research + +Template validation confirms the generated project structure and required governance files without +executing a consumer release. diff --git a/.specsync/changes/CHG-0002-update-corvid-stack-template-for-trust-1/state.json b/.specsync/changes/CHG-0002-update-corvid-stack-template-for-trust-1/state.json new file mode 100644 index 00000000..cc586dff --- /dev/null +++ b/.specsync/changes/CHG-0002-update-corvid-stack-template-for-trust-1/state.json @@ -0,0 +1,35 @@ +{ + "schema_version": 1, + "id": "CHG-0002-update-corvid-stack-template-for-trust-1", + "slug": "update-corvid-stack-template-for-trust-1", + "title": "Update Corvid stack template for Trust 1", + "description": "Update Corvid stack template for Trust 1", + "kind": "migration", + "state": "accepted", + "base_commit": "02550b3fac7e9a5ca12f5aecc1773f89972820f0", + "created_at": 1783831323, + "updated_at": 1783925640, + "affected_specs": [], + "affected_paths": [ + "templates/corvid-stack/" + ], + "no_spec_change": true, + "no_spec_change_rationale": "Template governance defaults do not change Fledge runtime behavior.", + "acceptance_criteria": [ + "The Corvid stack template emits SpecSync 5.0.1 SDD and the immutable Trust 1 workflow" + ], + "selected_artifacts": [ + "context", + "research", + "design", + "plan", + "tasks", + "testing", + "docs" + ], + "dependencies": [], + "answers": { + "architecture_risk": "no", + "public_contract": "no" + } +} diff --git a/.specsync/changes/CHG-0002-update-corvid-stack-template-for-trust-1/tasks.md b/.specsync/changes/CHG-0002-update-corvid-stack-template-for-trust-1/tasks.md new file mode 100644 index 00000000..53b74108 --- /dev/null +++ b/.specsync/changes/CHG-0002-update-corvid-stack-template-for-trust-1/tasks.md @@ -0,0 +1,11 @@ +--- +change: CHG-0002-update-corvid-stack-template-for-trust-1 +artifact: tasks +--- + +# Tasks + +- [x] Generate the Trust 1 and SpecSync 5 template files. +- [x] Run strict template validation. +- [x] Replace placeholder tasks with deterministic starter governance checks. +- [x] Pass hosted branch-built Corvid stack template validation. diff --git a/.specsync/changes/CHG-0002-update-corvid-stack-template-for-trust-1/testing.md b/.specsync/changes/CHG-0002-update-corvid-stack-template-for-trust-1/testing.md new file mode 100644 index 00000000..086085d7 --- /dev/null +++ b/.specsync/changes/CHG-0002-update-corvid-stack-template-for-trust-1/testing.md @@ -0,0 +1,8 @@ +--- +change: CHG-0002-update-corvid-stack-template-for-trust-1 +artifact: testing +--- + +# Testing + +Run strict template validation, SpecSync strict validation, and the unified Trust gate. diff --git a/.specsync/changes/CHG-0002-update-corvid-stack-template-for-trust-1/verification.json b/.specsync/changes/CHG-0002-update-corvid-stack-template-for-trust-1/verification.json new file mode 100644 index 00000000..10a0a281 --- /dev/null +++ b/.specsync/changes/CHG-0002-update-corvid-stack-template-for-trust-1/verification.json @@ -0,0 +1,16 @@ +{ + "timestamp": 1783925640, + "commit": "abd4240b1699cf1f2fb79417641f0a82054b5972", + "contract_digest": "eba5b5589df084078203786c6f051df9378749313f2ffa761fddcff0e9d49c57", + "workspace_digest": "9a889f5a1f62f02e872ecbd4e3d055cff2603e7072ab66024d85816bc2c2bd25", + "acceptance_input_digest": "a1a598a7e9aad2554fe6cf08d11fbd78bba93f84235dc9747695bec2bdc94a80", + "passed": true, + "commands": [ + { + "command": "fledge lanes run verify-native", + "success": true, + "exit_code": 0 + } + ], + "requirement_ids": [] +} diff --git a/.specsync/config.toml b/.specsync/config.toml index c210a4ff..f935eed6 100644 --- a/.specsync/config.toml +++ b/.specsync/config.toml @@ -1,4 +1,4 @@ -# spec-sync v4 configuration +# spec-sync v5 configuration # Docs: https://github.com/CorvidLabs/spec-sync specs_dir = "specs" @@ -10,8 +10,5 @@ exclude_dirs = [] exclude_patterns = ["src/test_support.rs", "**/.github/**"] required_sections = ["Purpose", "Public API", "Invariants", "Behavioral Examples", "Error Cases", "Dependencies", "Change Log"] enforcement = "strict" -ai_command = "claude -p --output-format text" -ai_timeout = 300 - [lifecycle] track_history = false diff --git a/.specsync/sdd.json b/.specsync/sdd.json new file mode 100644 index 00000000..7a1a98d2 --- /dev/null +++ b/.specsync/sdd.json @@ -0,0 +1,52 @@ +{ + "version": 1, + "enabled": true, + "require_change_for_meaningful_files": true, + "meaningful_paths": [ + "src/", + "tests/", + "specs/", + "site/", + ".github/", + ".claude/", + ".codex/", + ".cursor/", + ".gemini/", + "Cargo.toml", + "Cargo.lock", + "build.rs", + "flake.nix", + "action.yml", + "package.json", + "bun.lock", + "package-lock.json", + "pnpm-lock.yaml", + "yarn.lock", + "Package.swift", + "Package.resolved", + "go.mod", + "go.sum", + "pyproject.toml", + "uv.lock", + "requirements.txt", + ".specsync/sdd.json", + ".specsync/config.toml", + ".specsync/config.json", + ".specsync/registry.toml", + ".specsync/version", + "templates/", + "fledge.toml", + "install.sh", + "install.ps1", + ".trust.toml", + ".augur.toml", + ".attest.json", + "AGENTS.md" + ], + "ignored_paths": [], + "verification_commands": [ + "fledge lanes run verify-native" + ], + "custom_artifacts": {}, + "principles_file": null +} diff --git a/.specsync/version b/.specsync/version index f77856a6..6b244dcd 100644 --- a/.specsync/version +++ b/.specsync/version @@ -1 +1 @@ -4.3.1 +5.0.1 diff --git a/.trust.toml b/.trust.toml new file mode 100644 index 00000000..4dede35b --- /dev/null +++ b/.trust.toml @@ -0,0 +1,22 @@ +schema_version = 1 +profile = "standard" + +[lifecycle] +command = ["fledge", "lanes", "run", "verify-native"] + +[contract] +enabled = true +require_coverage = 100 +skip_reason = "" + +[risk] +threshold = "block" + +[provenance] +mode = "soft" +policy = ".attest.json" +skip_reason = "" + +[atlas] +enabled = false +skip_reason = "Atlas publication was not enabled during adoption" diff --git a/AGENTS.md b/AGENTS.md index 8aea8c0a..e117651c 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -366,3 +366,17 @@ If a command you want doesn't expose `--json`, or a workflow isn't automatable, 3. Implement, run `fledge lanes run pre-commit`, open the PR The project explicitly welcomes agent-surface improvements. + + +## CorvidLabs trust toolchain + +This repository uses one trust gate. Every session must use it and must not bypass or weaken it. + +- Install the `corvid-trust` bundle so `fledge trust` is available, then run + `fledge trust verify` before calling a change complete. +- Keep module specs synchronized with implementation changes. +- Treat an Augur block verdict as a hard stop that must be surfaced and de-risked. +- Record and verify provenance with Attest after the repository's verification lane passes. +- Keep generated trust configuration and this managed block in place. + + diff --git a/CHANGELOG.md b/CHANGELOG.md index 11910ec1..35798a22 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +- Update SpecSync validation to 5.0.1 and remove obsolete embedded-AI configuration. +- Generate new Corvid stack projects with the unified Trust 1.0 gate and SpecSync SDD policy. + ### Fixes - scope Atlas coverage to shipped product code by excluding build/test-only support files (#495) diff --git a/fledge.toml b/fledge.toml index 21f96610..1534e2a4 100644 --- a/fledge.toml +++ b/fledge.toml @@ -4,6 +4,7 @@ [tasks] build = "cargo build" test = "cargo test" +test-governance = "cargo test -- --skip cli_spec_check_succeeds_in_project --skip cli_spec_check_json_valid --skip cli_spec_check_json_spec_shape" lint = "cargo clippy --all-targets -- -D warnings" fmt = "cargo fmt --check" fmt-fix = "cargo fmt" @@ -19,6 +20,14 @@ description = "Validate all built-in templates" description = "Full CI pipeline" steps = ["fmt", "lint", "test", "build", "spec-check", "validate-templates"] +[lanes.verify] +description = "Required Trust gate for the Fledge repository" +steps = ["fmt", "lint", "test", "build", "spec-check", "validate-templates"] + +[lanes.verify-native] +description = "Native verification used by Trust and SpecSync without recursive self-check tests" +steps = ["fmt", "lint", "test-governance", "build", "validate-templates"] + [lanes.check] description = "Quick quality check" steps = [ diff --git a/specs/ai/requirements.md b/specs/ai/requirements.md index e4c2acfb..b3652066 100644 --- a/specs/ai/requirements.md +++ b/specs/ai/requirements.md @@ -11,12 +11,29 @@ spec: ai.spec.md ## Acceptance Criteria -- `fledge ai status` matches the provider/model/host that `llm::build_provider` would resolve; regression between the two is a tracked bug -- `fledge ai models --provider ollama --json` parses cleanly with `jq` and includes at least `name` per model -- `fledge ai use ` writes `ai.provider` + per-provider `model` to `~/.config/fledge/config.toml` atomically -- `fledge ai use` in `--non-interactive` without a provider arg errors via `utils::require_interactive` -- `fledge ai use ollama` interactively, with a running daemon, offers a Select with the live model list -- Unknown providers on any `--provider` flag reject at clap parse time (not at runtime) +### REQ-ai-001 + +The implementation SHALL meet this contract: `fledge ai status` matches the provider/model/host that `llm::build_provider` would resolve; regression between the two is a tracked bug + +### REQ-ai-002 + +The implementation SHALL meet this contract: `fledge ai models --provider ollama --json` parses cleanly with `jq` and includes at least `name` per model + +### REQ-ai-003 + +The implementation SHALL meet this contract: `fledge ai use ` writes `ai.provider` + per-provider `model` to `~/.config/fledge/config.toml` atomically + +### REQ-ai-004 + +The implementation SHALL meet this contract: `fledge ai use` in `--non-interactive` without a provider arg errors via `utils::require_interactive` + +### REQ-ai-005 + +The implementation SHALL meet this contract: `fledge ai use ollama` interactively, with a running daemon, offers a Select with the live model list + +### REQ-ai-006 + +The implementation SHALL meet this contract: Unknown providers on any `--provider` flag reject at clap parse time (not at runtime) ## Constraints diff --git a/specs/ask/requirements.md b/specs/ask/requirements.md index 33657126..e6b31ecb 100644 --- a/specs/ask/requirements.md +++ b/specs/ask/requirements.md @@ -9,11 +9,25 @@ spec: ask.spec.md ## Acceptance Criteria -- `fledge ask ` joins all trailing arguments into a single question -- The question is sent to Claude CLI running in the current project directory -- The response is streamed to stdout -- Missing Claude CLI produces install instructions -- No question provided produces a usage hint +### REQ-ask-001 + +The implementation SHALL meet this contract: `fledge ask ` joins all trailing arguments into a single question + +### REQ-ask-002 + +The implementation SHALL meet this contract: The question is sent to Claude CLI running in the current project directory + +### REQ-ask-003 + +The implementation SHALL meet this contract: The response is streamed to stdout + +### REQ-ask-004 + +The implementation SHALL meet this contract: Missing Claude CLI produces install instructions + +### REQ-ask-005 + +The implementation SHALL meet this contract: No question provided produces a usage hint ## Constraints diff --git a/specs/changelog/requirements.md b/specs/changelog/requirements.md index 65f1f00e..a8973a14 100644 --- a/specs/changelog/requirements.md +++ b/specs/changelog/requirements.md @@ -14,11 +14,34 @@ type: requirements ## Acceptance Criteria -- `fledge changelog` shows all tagged releases with commits grouped by conventional commit type -- `fledge changelog --limit 3` shows only the 3 most recent releases -- `fledge changelog --tag v0.5.0` shows only that release -- `fledge changelog --unreleased` shows commits since the latest tag -- `fledge changelog --json` outputs structured JSON -- Merge commits are excluded -- Scoped commits (e.g., `fix(parser): msg`) are correctly parsed -- Non-conventional commits appear under "Other" +### REQ-changelog-001 + +The implementation SHALL meet this contract: `fledge changelog` shows all tagged releases with commits grouped by conventional commit type + +### REQ-changelog-002 + +The implementation SHALL meet this contract: `fledge changelog --limit 3` shows only the 3 most recent releases + +### REQ-changelog-003 + +The implementation SHALL meet this contract: `fledge changelog --tag v0.5.0` shows only that release + +### REQ-changelog-004 + +The implementation SHALL meet this contract: `fledge changelog --unreleased` shows commits since the latest tag + +### REQ-changelog-005 + +The implementation SHALL meet this contract: `fledge changelog --json` outputs structured JSON + +### REQ-changelog-006 + +The implementation SHALL meet this contract: Merge commits are excluded + +### REQ-changelog-007 + +The implementation SHALL meet this contract: Scoped commits (e.g., `fix(parser): msg`) are correctly parsed + +### REQ-changelog-008 + +The implementation SHALL meet this contract: Non-conventional commits appear under "Other" diff --git a/specs/config/requirements.md b/specs/config/requirements.md index 2d1f2e7c..ed00b3a1 100644 --- a/specs/config/requirements.md +++ b/specs/config/requirements.md @@ -11,15 +11,41 @@ spec: config.spec.md ## Acceptance Criteria -- `fledge config list` displays all configured values and empty list sections -- `fledge config get ` prints the value for any valid key (scalar or list) -- `fledge config set ` persists scalar values to `config.toml` -- `fledge config unset ` removes values (clears lists for list keys) -- `fledge config add ` appends to list keys with deduplication -- `fledge config remove ` removes from list keys and reports whether found -- Using `set` on a list key (or `add`/`remove` on a scalar key) produces a clear error with guidance -- Config file is created on first write if it doesn't exist -- Missing config file returns sensible defaults (MIT license, no author, empty lists) +### REQ-config-001 + +The implementation SHALL meet this contract: `fledge config list` displays all configured values and empty list sections + +### REQ-config-002 + +The implementation SHALL meet this contract: `fledge config get ` prints the value for any valid key (scalar or list) + +### REQ-config-003 + +The implementation SHALL meet this contract: `fledge config set ` persists scalar values to `config.toml` + +### REQ-config-004 + +The implementation SHALL meet this contract: `fledge config unset ` removes values (clears lists for list keys) + +### REQ-config-005 + +The implementation SHALL meet this contract: `fledge config add ` appends to list keys with deduplication + +### REQ-config-006 + +The implementation SHALL meet this contract: `fledge config remove ` removes from list keys and reports whether found + +### REQ-config-007 + +The implementation SHALL meet this contract: Using `set` on a list key (or `add`/`remove` on a scalar key) produces a clear error with guidance + +### REQ-config-008 + +The implementation SHALL meet this contract: Config file is created on first write if it doesn't exist + +### REQ-config-009 + +The implementation SHALL meet this contract: Missing config file returns sensible defaults (MIT license, no author, empty lists) ## Constraints diff --git a/specs/create_template/requirements.md b/specs/create_template/requirements.md index e618f440..02074596 100644 --- a/specs/create_template/requirements.md +++ b/specs/create_template/requirements.md @@ -10,13 +10,33 @@ spec: create_template.spec.md ## Acceptance Criteria -- `fledge create-template my-template` creates a new directory with a valid template scaffold -- Generated `template.toml` is valid TOML parseable as `TemplateManifest` -- Interactive prompts ask for name, description, render globs, hooks, and custom prompts -- All prompts have sensible defaults that can be accepted with Enter -- Includes example `.tera` file demonstrating variable substitution -- Includes author-facing README with instructions for testing locally -- Fails with a clear error if the target directory already exists +### REQ-create-template-001 + +The implementation SHALL meet this contract: `fledge create-template my-template` creates a new directory with a valid template scaffold + +### REQ-create-template-002 + +The implementation SHALL meet this contract: Generated `template.toml` is valid TOML parseable as `TemplateManifest` + +### REQ-create-template-003 + +The implementation SHALL meet this contract: Interactive prompts ask for name, description, render globs, hooks, and custom prompts + +### REQ-create-template-004 + +The implementation SHALL meet this contract: All prompts have sensible defaults that can be accepted with Enter + +### REQ-create-template-005 + +The implementation SHALL meet this contract: Includes example `.tera` file demonstrating variable substitution + +### REQ-create-template-006 + +The implementation SHALL meet this contract: Includes author-facing README with instructions for testing locally + +### REQ-create-template-007 + +The implementation SHALL meet this contract: Fails with a clear error if the target directory already exists ## Constraints diff --git a/specs/doctor/requirements.md b/specs/doctor/requirements.md index f935ece2..9cb64376 100644 --- a/specs/doctor/requirements.md +++ b/specs/doctor/requirements.md @@ -10,12 +10,29 @@ spec: doctor.spec.md ## Acceptance Criteria -- `fledge doctor` reports four sections: `fledge`, `Git`, `AI`, `Toolchains` -- Each failing check in a non-informational section shows an actionable fix command -- The `Toolchains` section is informational — missing entries render dimmed and don't pollute the pass/fail totals -- `--json` outputs a structured `DoctorReport` with all check results, including `informational: bool` per Section -- Exit summary shows count of passed checks and issues found, computed only over non-informational sections -- Toolchains probed: rustc, cargo, node, npm, pnpm, bun, yarn, python3, uv, poetry, go, ruby, swift, java, gradle, mvn +### REQ-doctor-001 + +The implementation SHALL meet this contract: `fledge doctor` reports four sections: `fledge`, `Git`, `AI`, `Toolchains` + +### REQ-doctor-002 + +The implementation SHALL meet this contract: Each failing check in a non-informational section shows an actionable fix command + +### REQ-doctor-003 + +The implementation SHALL meet this contract: The `Toolchains` section is informational — missing entries render dimmed and don't pollute the pass/fail totals + +### REQ-doctor-004 + +The implementation SHALL meet this contract: `--json` outputs a structured `DoctorReport` with all check results, including `informational: bool` per Section + +### REQ-doctor-005 + +The implementation SHALL meet this contract: Exit summary shows count of passed checks and issues found, computed only over non-informational sections + +### REQ-doctor-006 + +The implementation SHALL meet this contract: Toolchains probed: rustc, cargo, node, npm, pnpm, bun, yarn, python3, uv, poetry, go, ruby, swift, java, gradle, mvn ## Constraints diff --git a/specs/envelope/requirements.md b/specs/envelope/requirements.md index 80681735..f56c899a 100644 --- a/specs/envelope/requirements.md +++ b/specs/envelope/requirements.md @@ -10,13 +10,33 @@ spec: envelope.spec.md ## Acceptance Criteria -- `resource(schema_version, key, items)` builds `{schema_version, : items}` with no `action` key -- `action(schema_version, action, fields)` builds `{schema_version, action, ...fields}`, inserting the fixed keys first then merging an object `fields` -- `versioned(schema_version, fields)` builds `{schema_version, ...fields}` with no `action` key -- Every envelope carries a `schema_version` from the caller-supplied `u32` -- Output is byte-for-byte identical to the equivalent hand-rolled `serde_json::json!` -- A non-object `fields` value contributes no extra keys; the envelope still carries its fixed keys -- Non-serializable `resource` items store `Value::Null` under the key instead of panicking +### REQ-envelope-001 + +The implementation SHALL meet this contract: `resource(schema_version, key, items)` builds `{schema_version, : items}` with no `action` key + +### REQ-envelope-002 + +The implementation SHALL meet this contract: `action(schema_version, action, fields)` builds `{schema_version, action, ...fields}`, inserting the fixed keys first then merging an object `fields` + +### REQ-envelope-003 + +The implementation SHALL meet this contract: `versioned(schema_version, fields)` builds `{schema_version, ...fields}` with no `action` key + +### REQ-envelope-004 + +The implementation SHALL meet this contract: Every envelope carries a `schema_version` from the caller-supplied `u32` + +### REQ-envelope-005 + +The implementation SHALL meet this contract: Output is byte-for-byte identical to the equivalent hand-rolled `serde_json::json!` + +### REQ-envelope-006 + +The implementation SHALL meet this contract: A non-object `fields` value contributes no extra keys; the envelope still carries its fixed keys + +### REQ-envelope-007 + +The implementation SHALL meet this contract: Non-serializable `resource` items store `Value::Null` under the key instead of panicking ## Constraints diff --git a/specs/github/requirements.md b/specs/github/requirements.md index c8ef759c..e4dd90d6 100644 --- a/specs/github/requirements.md +++ b/specs/github/requirements.md @@ -10,16 +10,45 @@ spec: github.spec.md ## Acceptance Criteria -- `detect_repo` parses HTTPS remote URLs (`https://github.com/owner/repo.git`) -- `detect_repo` parses SSH remote URLs (`git@github.com:owner/repo.git`) -- `detect_repo` handles token-authenticated HTTPS URLs -- `detect_repo` strips trailing `.git` suffix -- `github_api_get` reads token from `FLEDGE_GITHUB_TOKEN`, `GITHUB_TOKEN`, or config -- `github_api_get` returns parsed JSON on success -- 403 responses produce a message about setting a token -- 404 responses produce a "Not found" error -- `format_relative_time` converts ISO 8601 timestamps to human-readable relative times -- `format_relative_time` falls back to the raw string for unparseable input +### REQ-github-001 + +The implementation SHALL meet this contract: `detect_repo` parses HTTPS remote URLs (`https://github.com/owner/repo.git`) + +### REQ-github-002 + +The implementation SHALL meet this contract: `detect_repo` parses SSH remote URLs (`git@github.com:owner/repo.git`) + +### REQ-github-003 + +The implementation SHALL meet this contract: `detect_repo` handles token-authenticated HTTPS URLs + +### REQ-github-004 + +The implementation SHALL meet this contract: `detect_repo` strips trailing `.git` suffix + +### REQ-github-005 + +The implementation SHALL meet this contract: `github_api_get` reads token from `FLEDGE_GITHUB_TOKEN`, `GITHUB_TOKEN`, or config + +### REQ-github-006 + +The implementation SHALL meet this contract: `github_api_get` returns parsed JSON on success + +### REQ-github-007 + +The implementation SHALL meet this contract: 403 responses produce a message about setting a token + +### REQ-github-008 + +The implementation SHALL meet this contract: 404 responses produce a "Not found" error + +### REQ-github-009 + +The implementation SHALL meet this contract: `format_relative_time` converts ISO 8601 timestamps to human-readable relative times + +### REQ-github-010 + +The implementation SHALL meet this contract: `format_relative_time` falls back to the raw string for unparseable input ## Constraints diff --git a/specs/init/requirements.md b/specs/init/requirements.md index 78bdef42..11fb8aa2 100644 --- a/specs/init/requirements.md +++ b/specs/init/requirements.md @@ -13,17 +13,49 @@ spec: init.spec.md ## Acceptance Criteria -- `fledge init ` creates a directory with rendered template files -- `fledge init --template ` uses the specified template -- `fledge init --template owner/repo` fetches and uses a remote template -- Without `--template`, an interactive selector is shown -- `--dry-run` prints file list, hooks, and git status without writing -- `--no-git` skips git init and initial commit -- `--no-install` skips post-create hooks -- `--yes` auto-confirms remote hook prompts -- `--refresh` clears cached remote repos before fetching -- If the target directory already exists, the command errors immediately -- Git init includes an initial commit with all scaffolded files +### REQ-init-001 + +The implementation SHALL meet this contract: `fledge init ` creates a directory with rendered template files + +### REQ-init-002 + +The implementation SHALL meet this contract: `fledge init --template ` uses the specified template + +### REQ-init-003 + +The implementation SHALL meet this contract: `fledge init --template owner/repo` fetches and uses a remote template + +### REQ-init-004 + +The implementation SHALL meet this contract: Without `--template`, an interactive selector is shown + +### REQ-init-005 + +The implementation SHALL meet this contract: `--dry-run` prints file list, hooks, and git status without writing + +### REQ-init-006 + +The implementation SHALL meet this contract: `--no-git` skips git init and initial commit + +### REQ-init-007 + +The implementation SHALL meet this contract: `--no-install` skips post-create hooks + +### REQ-init-008 + +The implementation SHALL meet this contract: `--yes` auto-confirms remote hook prompts + +### REQ-init-009 + +The implementation SHALL meet this contract: `--refresh` clears cached remote repos before fetching + +### REQ-init-010 + +The implementation SHALL meet this contract: If the target directory already exists, the command errors immediately + +### REQ-init-011 + +The implementation SHALL meet this contract: Git init includes an initial commit with all scaffolded files ## Constraints diff --git a/specs/introspect/requirements.md b/specs/introspect/requirements.md index 7224ba2c..51092dd6 100644 --- a/specs/introspect/requirements.md +++ b/specs/introspect/requirements.md @@ -10,11 +10,25 @@ spec: introspect.spec.md ## Acceptance Criteria -- `fledge introspect --json` produces a single JSON object parseable by `serde_json::from_str` and `jq` -- `fledge introspect` without `--json` produces a human-readable indented tree -- The output includes every user-facing subcommand and arg — no silent gaps -- clap's auto-generated `--help` and `--version` and `help` subcommand are excluded as noise -- Subcommand aliases and global args are explicitly labeled in the output so agents can reason about them +### REQ-introspect-001 + +The implementation SHALL meet this contract: `fledge introspect --json` produces a single JSON object parseable by `serde_json::from_str` and `jq` + +### REQ-introspect-002 + +The implementation SHALL meet this contract: `fledge introspect` without `--json` produces a human-readable indented tree + +### REQ-introspect-003 + +The implementation SHALL meet this contract: The output includes every user-facing subcommand and arg — no silent gaps + +### REQ-introspect-004 + +The implementation SHALL meet this contract: clap's auto-generated `--help` and `--version` and `help` subcommand are excluded as noise + +### REQ-introspect-005 + +The implementation SHALL meet this contract: Subcommand aliases and global args are explicitly labeled in the output so agents can reason about them ## Constraints diff --git a/specs/lanes/requirements.md b/specs/lanes/requirements.md index 5e9a5690..54a357de 100644 --- a/specs/lanes/requirements.md +++ b/specs/lanes/requirements.md @@ -1,5 +1,11 @@ # Lanes — Requirements +### REQ-lanes-001 + +The implementation SHALL satisfy the behavior described by this companion. + +Acceptance Criteria + ## Functional Requirements 1. Define named workflow pipelines in `fledge.toml` under `[lanes]` diff --git a/specs/llm/requirements.md b/specs/llm/requirements.md index 5fb74e11..90b93137 100644 --- a/specs/llm/requirements.md +++ b/specs/llm/requirements.md @@ -11,13 +11,33 @@ spec: llm.spec.md ## Acceptance Criteria -- Default behavior (no config, no env, no flag) is identical to the pre-v0.13 Claude-CLI-only behavior -- Setting `ai.provider = "ollama"` in config OR `FLEDGE_AI_PROVIDER=ollama` in env routes all AI commands through Ollama -- Per-invocation `--provider ollama` overrides both env and config -- Model selection follows the same override > env > config > default precedence -- Ollama's HTTP request shape matches the `/api/generate` endpoint's published schema -- `fledge doctor` reports both providers and which is active -- No regression: `fledge ask --json` and `fledge review --json` outputs remain parseable; payloads gain a `provider` and `model` field +### REQ-llm-001 + +The implementation SHALL meet this contract: Default behavior (no config, no env, no flag) is identical to the pre-v0.13 Claude-CLI-only behavior + +### REQ-llm-002 + +The implementation SHALL meet this contract: Setting `ai.provider = "ollama"` in config OR `FLEDGE_AI_PROVIDER=ollama` in env routes all AI commands through Ollama + +### REQ-llm-003 + +The implementation SHALL meet this contract: Per-invocation `--provider ollama` overrides both env and config + +### REQ-llm-004 + +The implementation SHALL meet this contract: Model selection follows the same override > env > config > default precedence + +### REQ-llm-005 + +The implementation SHALL meet this contract: Ollama's HTTP request shape matches the `/api/generate` endpoint's published schema + +### REQ-llm-006 + +The implementation SHALL meet this contract: `fledge doctor` reports both providers and which is active + +### REQ-llm-007 + +The implementation SHALL meet this contract: No regression: `fledge ask --json` and `fledge review --json` outputs remain parseable; payloads gain a `provider` and `model` field ## Constraints diff --git a/specs/main/requirements.md b/specs/main/requirements.md index 348c3a5b..2a1cff47 100644 --- a/specs/main/requirements.md +++ b/specs/main/requirements.md @@ -1,4 +1,15 @@ -- Parse CLI arguments via clap derive -- Dispatch each subcommand to its module's entry function -- Forward unknown commands to installed plugins -- Generate shell completions on demand +### REQ-main-001 + +The implementation SHALL meet this contract: Parse CLI arguments via clap derive + +### REQ-main-002 + +The implementation SHALL meet this contract: Dispatch each subcommand to its module's entry function + +### REQ-main-003 + +The implementation SHALL meet this contract: Forward unknown commands to installed plugins + +### REQ-main-004 + +The implementation SHALL meet this contract: Generate shell completions on demand diff --git a/specs/meta/requirements.md b/specs/meta/requirements.md index 4185b4e7..3ce349b8 100644 --- a/specs/meta/requirements.md +++ b/specs/meta/requirements.md @@ -11,12 +11,29 @@ spec: meta.spec.md ## Acceptance Criteria -- `write_project_meta` writes `.fledge/meta.toml` with `SourceInfo` provenance, string template variables, and a hash for each existing created file -- `compute_file_hash` returns a 64-character lowercase hex SHA-256 digest and is deterministic -- The `.fledge` directory is created if missing -- A `.fledge/.gitignore` is created if one does not already exist, and an existing one is never overwritten -- Created files that no longer exist on disk are silently skipped, not errored -- `fledge_version` is captured from `CARGO_PKG_VERSION` at compile time and `created` is the local date as `YYYY-MM-DD` +### REQ-meta-001 + +The implementation SHALL meet this contract: `write_project_meta` writes `.fledge/meta.toml` with `SourceInfo` provenance, string template variables, and a hash for each existing created file + +### REQ-meta-002 + +The implementation SHALL meet this contract: `compute_file_hash` returns a 64-character lowercase hex SHA-256 digest and is deterministic + +### REQ-meta-003 + +The implementation SHALL meet this contract: The `.fledge` directory is created if missing + +### REQ-meta-004 + +The implementation SHALL meet this contract: A `.fledge/.gitignore` is created if one does not already exist, and an existing one is never overwritten + +### REQ-meta-005 + +The implementation SHALL meet this contract: Created files that no longer exist on disk are silently skipped, not errored + +### REQ-meta-006 + +The implementation SHALL meet this contract: `fledge_version` is captured from `CARGO_PKG_VERSION` at compile time and `created` is the local date as `YYYY-MM-DD` ## Constraints diff --git a/specs/plugin/plugin-protocol.spec.md b/specs/plugin/plugin-protocol.spec.md index b7d18224..a1550604 100644 --- a/specs/plugin/plugin-protocol.spec.md +++ b/specs/plugin/plugin-protocol.spec.md @@ -1,6 +1,6 @@ --- module: plugin-protocol -version: 7 +version: 8 status: active files: - src/protocol/mod.rs @@ -62,6 +62,7 @@ Public API — `run_protocol_plugin`, `OutboundMessage`, and `PluginContext` are | `detect_project_context` | Detect project name, root path, language, and git context from current environment | | `sanitize_remote_url` | Strip credentials from HTTPS/HTTP git URLs | | `detect_git_context` | Extract git branch, dirty status, remote name, and sanitized remote URL | +| `Read` | Crate-internal I/O trait re-export used by protocol stream readers | ### Structs & Enums @@ -604,6 +605,7 @@ These are not part of v1 but are designed to be additive under the policy above: | Version | Date | Changes | |---------|------|---------| +| 8 | 2026-07-11 | Document the crate-internal `Read` re-export detected by SpecSync 5 multi-file scanning | | 7 | 2026-05-02 | Remove misleading "sandboxed" language from exec security notes; clarify that cwd is validated but command string is unfiltered. Change future file_operations wording from "sandboxed" to "path-validated" | | 6 | 2026-05-02 | Clarify public vs internal exports in single table (spec-sync requires all exports in one `Exported Functions` table). Add platform-correct storage paths using `` notation | | 5 | 2026-04-29 | Fix spec-sync: consolidate all exports into standard `Exported Functions` table (custom subsection headers were not parsed by spec-sync) | diff --git a/specs/plugin/requirements.md b/specs/plugin/requirements.md index 0f8a2133..4b7ec498 100644 --- a/specs/plugin/requirements.md +++ b/specs/plugin/requirements.md @@ -1,5 +1,11 @@ # Plugin — Requirements +### REQ-plugin-001 + +The implementation SHALL satisfy the behavior described by this companion. + +Acceptance Criteria + ## Functional Requirements 1. Install plugins from GitHub shorthand, generic git URLs, and local paths via `fledge plugins install ` diff --git a/specs/prompts/requirements.md b/specs/prompts/requirements.md index 19382dfd..df3a8d9e 100644 --- a/specs/prompts/requirements.md +++ b/specs/prompts/requirements.md @@ -11,13 +11,33 @@ spec: prompts.spec.md ## Acceptance Criteria -- `select_template()` presents an interactive list with name and description columns -- `prompt_variables()` collects all core variables (project_name, author, github_org, license, year, date) and template-specific prompts -- Author falls back: config → `git config user.name` → interactive prompt -- GitHub org falls back: config → interactive prompt with "CorvidLabs" default -- License is always pulled from config (defaults to MIT) -- Template-specific prompt defaults support Tera variable interpolation -- Case conversion produces correct snake_case and PascalCase variants +### REQ-prompts-001 + +The implementation SHALL meet this contract: `select_template()` presents an interactive list with name and description columns + +### REQ-prompts-002 + +The implementation SHALL meet this contract: `prompt_variables()` collects all core variables (project_name, author, github_org, license, year, date) and template-specific prompts + +### REQ-prompts-003 + +The implementation SHALL meet this contract: Author falls back: config → `git config user.name` → interactive prompt + +### REQ-prompts-004 + +The implementation SHALL meet this contract: GitHub org falls back: config → interactive prompt with "CorvidLabs" default + +### REQ-prompts-005 + +The implementation SHALL meet this contract: License is always pulled from config (defaults to MIT) + +### REQ-prompts-006 + +The implementation SHALL meet this contract: Template-specific prompt defaults support Tera variable interpolation + +### REQ-prompts-007 + +The implementation SHALL meet this contract: Case conversion produces correct snake_case and PascalCase variants ## Constraints diff --git a/specs/publish/requirements.md b/specs/publish/requirements.md index a0e4d15e..7046149e 100644 --- a/specs/publish/requirements.md +++ b/specs/publish/requirements.md @@ -1,5 +1,11 @@ # Publish — Requirements +### REQ-publish-001 + +The implementation SHALL satisfy the behavior described by this companion. + +Acceptance Criteria + This module is a library — its requirements describe the helpers it exposes. The user-facing publish commands (`templates publish`, `lanes publish`, `plugins publish`) define their own validation and prompting in their respective specs. ## Functional Requirements diff --git a/specs/release/requirements.md b/specs/release/requirements.md index 9e13cdc2..bef3dfb8 100644 --- a/specs/release/requirements.md +++ b/specs/release/requirements.md @@ -1,5 +1,11 @@ # Release — Requirements +### REQ-release-001 + +The implementation SHALL satisfy the behavior described by this companion. + +Acceptance Criteria + 1. Bump version in language-specific files (Cargo.toml, package.json, pyproject.toml, etc.) 2. Support semver bump levels: major, minor, patch, or explicit version 3. Auto-detect project language to find version files diff --git a/specs/remote/requirements.md b/specs/remote/requirements.md index d653d62b..2483262d 100644 --- a/specs/remote/requirements.md +++ b/specs/remote/requirements.md @@ -2,13 +2,32 @@ ## Functional -- Clone GitHub repos to local cache for template discovery -- Support authenticated access via GitHub token -- Support `owner/repo` and `owner/repo/subpath` reference formats -- Update cached repos on subsequent access -- Shallow clones (`--depth 1`) to minimize bandwidth +### REQ-remote-001 + +The implementation SHALL meet this contract: Clone GitHub repos to local cache for template discovery + +### REQ-remote-002 + +The implementation SHALL meet this contract: Support authenticated access via GitHub token + +### REQ-remote-003 + +The implementation SHALL meet this contract: Support `owner/repo` and `owner/repo/subpath` reference formats + +### REQ-remote-004 + +The implementation SHALL meet this contract: Update cached repos on subsequent access + +### REQ-remote-005 + +The implementation SHALL meet this contract: Shallow clones (`--depth 1`) to minimize bandwidth ## Non-Functional -- Cache location follows platform conventions (XDG on Linux, Library/Caches on macOS) -- Git operations should not leak tokens in stdout/stderr output +### REQ-remote-006 + +The implementation SHALL meet this contract: Cache location follows platform conventions (XDG on Linux, Library/Caches on macOS) + +### REQ-remote-007 + +The implementation SHALL meet this contract: Git operations should not leak tokens in stdout/stderr output diff --git a/specs/review/requirements.md b/specs/review/requirements.md index 37ae866d..a844e4bb 100644 --- a/specs/review/requirements.md +++ b/specs/review/requirements.md @@ -10,12 +10,29 @@ spec: review.spec.md ## Acceptance Criteria -- `fledge review` diffs the current branch against the default base (main/master) and sends it to Claude CLI -- `fledge review --base develop` uses a custom base branch -- `fledge review --file src/foo.rs` restricts the review to one file -- Diff stats are displayed before the AI output -- Empty diffs bail with a clear message -- Missing Claude CLI produces install instructions +### REQ-review-001 + +The implementation SHALL meet this contract: `fledge review` diffs the current branch against the default base (main/master) and sends it to Claude CLI + +### REQ-review-002 + +The implementation SHALL meet this contract: `fledge review --base develop` uses a custom base branch + +### REQ-review-003 + +The implementation SHALL meet this contract: `fledge review --file src/foo.rs` restricts the review to one file + +### REQ-review-004 + +The implementation SHALL meet this contract: Diff stats are displayed before the AI output + +### REQ-review-005 + +The implementation SHALL meet this contract: Empty diffs bail with a clear message + +### REQ-review-006 + +The implementation SHALL meet this contract: Missing Claude CLI produces install instructions ## Constraints diff --git a/specs/run/requirements.md b/specs/run/requirements.md index ae743420..6bad0634 100644 --- a/specs/run/requirements.md +++ b/specs/run/requirements.md @@ -11,13 +11,33 @@ spec: run.spec.md ## Acceptance Criteria -- `fledge run ` executes the named task from `fledge.toml` -- Task dependencies run in topological order before the requested task -- Circular dependencies produce an error listing the cycle -- `fledge run --list` shows task names and descriptions -- `fledge run --init` generates `fledge.toml` with defaults for the detected project type -- Unknown task names produce an error listing available tasks -- Tasks support environment variables and working directory overrides +### REQ-run-001 + +The implementation SHALL meet this contract: `fledge run ` executes the named task from `fledge.toml` + +### REQ-run-002 + +The implementation SHALL meet this contract: Task dependencies run in topological order before the requested task + +### REQ-run-003 + +The implementation SHALL meet this contract: Circular dependencies produce an error listing the cycle + +### REQ-run-004 + +The implementation SHALL meet this contract: `fledge run --list` shows task names and descriptions + +### REQ-run-005 + +The implementation SHALL meet this contract: `fledge run --init` generates `fledge.toml` with defaults for the detected project type + +### REQ-run-006 + +The implementation SHALL meet this contract: Unknown task names produce an error listing available tasks + +### REQ-run-007 + +The implementation SHALL meet this contract: Tasks support environment variables and working directory overrides ## Constraints diff --git a/specs/search/requirements.md b/specs/search/requirements.md index d5e7db43..2ac22d5e 100644 --- a/specs/search/requirements.md +++ b/specs/search/requirements.md @@ -1,5 +1,11 @@ # Search — Requirements +### REQ-search-001 + +The implementation SHALL satisfy the behavior described by this companion. + +Acceptance Criteria + This module is a library — its requirements are about the helpers it exposes. The user-facing search commands (`templates search`, `lanes search`, `plugins search`) define their own requirements in their respective specs. ## Functional Requirements diff --git a/specs/spec/requirements.md b/specs/spec/requirements.md index 4478f8be..e97cd21c 100644 --- a/specs/spec/requirements.md +++ b/specs/spec/requirements.md @@ -11,14 +11,37 @@ spec: spec.spec.md ## Acceptance Criteria -- `fledge spec check` validates all specs in the configured specs directory -- `fledge spec check --strict` treats warnings as errors -- `fledge spec init` creates `.specsync/` with config.toml, registry.toml, .gitignore, and version -- `fledge spec init` creates `specs/` directory if it doesn't exist -- `fledge spec new ` creates `specs//` with spec.md and companion files -- Validation checks: frontmatter fields, required sections, source file existence -- Exit code 1 on errors (or warnings in strict mode), 0 otherwise -- Colored output with checkmarks/crosses for each spec +### REQ-spec-001 + +The implementation SHALL meet this contract: `fledge spec check` validates all specs in the configured specs directory + +### REQ-spec-002 + +The implementation SHALL meet this contract: `fledge spec check --strict` treats warnings as errors + +### REQ-spec-003 + +The implementation SHALL meet this contract: `fledge spec init` creates `.specsync/` with config.toml, registry.toml, .gitignore, and version + +### REQ-spec-004 + +The implementation SHALL meet this contract: `fledge spec init` creates `specs/` directory if it doesn't exist + +### REQ-spec-005 + +The implementation SHALL meet this contract: `fledge spec new ` creates `specs//` with spec.md and companion files + +### REQ-spec-006 + +The implementation SHALL meet this contract: Validation checks: frontmatter fields, required sections, source file existence + +### REQ-spec-007 + +The implementation SHALL meet this contract: Exit code 1 on errors (or warnings in strict mode), 0 otherwise + +### REQ-spec-008 + +The implementation SHALL meet this contract: Colored output with checkmarks/crosses for each spec ## Constraints diff --git a/specs/spinner/requirements.md b/specs/spinner/requirements.md index 0afe5efe..8fbac9a7 100644 --- a/specs/spinner/requirements.md +++ b/specs/spinner/requirements.md @@ -9,10 +9,21 @@ spec: spinner.spec.md ## Acceptance Criteria -- `Spinner::start(msg)` displays an animated spinner with the given message -- `Spinner::finish()` clears the spinner line completely -- A random theme is chosen each time a spinner starts -- All themes animate smoothly without visual glitches +### REQ-spinner-001 + +The implementation SHALL meet this contract: `Spinner::start(msg)` displays an animated spinner with the given message + +### REQ-spinner-002 + +The implementation SHALL meet this contract: `Spinner::finish()` clears the spinner line completely + +### REQ-spinner-003 + +The implementation SHALL meet this contract: A random theme is chosen each time a spinner starts + +### REQ-spinner-004 + +The implementation SHALL meet this contract: All themes animate smoothly without visual glitches ## Constraints diff --git a/specs/templates/requirements.md b/specs/templates/requirements.md index c4b1dc99..963c5b53 100644 --- a/specs/templates/requirements.md +++ b/specs/templates/requirements.md @@ -13,18 +13,53 @@ spec: templates.spec.md ## Acceptance Criteria -- `discover_templates()` finds all built-in templates (8 language starters: `go-cli`, `kotlin-kmp`, `kotlin-ktor-api`, `python-cli`, `rust-cli`, `static-site`, `ts-bun`, `ts-node`; plus setup-only `fledge-plugin` and `corvid-stack`) -- Extra paths from config are searched for template directories -- Remote repos from config are fetched and searched for templates -- Templates are returned sorted alphabetically by name -- Directories without `template.toml` are silently skipped -- Non-existent extra paths are silently skipped -- `render_template()` renders `.tera` files and strips the extension -- `render_template()` renders files matching `files.render` globs -- `render_template()` copies non-matching files as-is -- `render_template()` skips files matching `files.ignore` globs -- `render_template()` renders Tera variables in file/directory paths -- Created files list is returned sorted alphabetically +### REQ-templates-001 + +The implementation SHALL meet this contract: `discover_templates()` finds all built-in templates (8 language starters: `go-cli`, `kotlin-kmp`, `kotlin-ktor-api`, `python-cli`, `rust-cli`, `static-site`, `ts-bun`, `ts-node`; plus setup-only `fledge-plugin` and `corvid-stack`) + +### REQ-templates-002 + +The implementation SHALL meet this contract: Extra paths from config are searched for template directories + +### REQ-templates-003 + +The implementation SHALL meet this contract: Remote repos from config are fetched and searched for templates + +### REQ-templates-004 + +The implementation SHALL meet this contract: Templates are returned sorted alphabetically by name + +### REQ-templates-005 + +The implementation SHALL meet this contract: Directories without `template.toml` are silently skipped + +### REQ-templates-006 + +The implementation SHALL meet this contract: Non-existent extra paths are silently skipped + +### REQ-templates-007 + +The implementation SHALL meet this contract: `render_template()` renders `.tera` files and strips the extension + +### REQ-templates-008 + +The implementation SHALL meet this contract: `render_template()` renders files matching `files.render` globs + +### REQ-templates-009 + +The implementation SHALL meet this contract: `render_template()` copies non-matching files as-is + +### REQ-templates-010 + +The implementation SHALL meet this contract: `render_template()` skips files matching `files.ignore` globs + +### REQ-templates-011 + +The implementation SHALL meet this contract: `render_template()` renders Tera variables in file/directory paths + +### REQ-templates-012 + +The implementation SHALL meet this contract: Created files list is returned sorted alphabetically ## Constraints diff --git a/specs/trust/requirements.md b/specs/trust/requirements.md index 5bd2f85c..b1863638 100644 --- a/specs/trust/requirements.md +++ b/specs/trust/requirements.md @@ -9,14 +9,37 @@ spec: trust.spec.md ## Acceptance Criteria -- `determine_trust_tier` classifies `CorvidLabs/*` sources as Official -- `determine_trust_tier` classifies filesystem path sources as Local -- `determine_trust_tier` classifies sources owned by a human member of the CorvidLabs org (e.g. `0xLeif/*`) as Team -- `determine_trust_tier` classifies all other sources as Unverified -- Supports local paths, HTTPS URLs, SSH URLs, and `owner/repo` shorthand -- `parse_source_ref` splits `source@ref` without false-splitting on credential `@` signs -- `label` returns lowercase string representation -- `styled_label` returns colored console output (magenta=local, green=official, cyan=team, yellow=unverified) +### REQ-trust-001 + +The implementation SHALL meet this contract: `determine_trust_tier` classifies `CorvidLabs/*` sources as Official + +### REQ-trust-002 + +The implementation SHALL meet this contract: `determine_trust_tier` classifies filesystem path sources as Local + +### REQ-trust-003 + +The implementation SHALL meet this contract: `determine_trust_tier` classifies sources owned by a human member of the CorvidLabs org (e.g. `0xLeif/*`) as Team + +### REQ-trust-004 + +The implementation SHALL meet this contract: `determine_trust_tier` classifies all other sources as Unverified + +### REQ-trust-005 + +The implementation SHALL meet this contract: Supports local paths, HTTPS URLs, SSH URLs, and `owner/repo` shorthand + +### REQ-trust-006 + +The implementation SHALL meet this contract: `parse_source_ref` splits `source@ref` without false-splitting on credential `@` signs + +### REQ-trust-007 + +The implementation SHALL meet this contract: `label` returns lowercase string representation + +### REQ-trust-008 + +The implementation SHALL meet this contract: `styled_label` returns colored console output (magenta=local, green=official, cyan=team, yellow=unverified) ## Constraints diff --git a/specs/utils/requirements.md b/specs/utils/requirements.md index 96e70659..0a3fe1af 100644 --- a/specs/utils/requirements.md +++ b/specs/utils/requirements.md @@ -12,15 +12,41 @@ spec: utils.spec.md ## Acceptance Criteria -- `set_non_interactive` / `is_non_interactive` are the only accessors to the global flag -- `init_non_interactive_from_env` flips the flag when `FLEDGE_NON_INTERACTIVE` is a truthy value (`1`/`true`/`yes`/`y`/`on`, case-insensitive, trimmed) -- `is_interactive` returns true only when stdin is a TTY and the non-interactive flag is unset -- `require_interactive` / `require_interactive_hint` return `Ok(())` only when `is_interactive`, otherwise bail with a flag- or hint-named error -- Case conversions are pure and total — any input (including empty) returns a `String` without panicking -- `validate_project_name` rejects empty strings, `/`, `\`, `..`, null bytes, and Windows-reserved device names -- `validate_github_org` rejects empty and slash-containing names but permits spaces -- `validate_commit_scope` requires non-empty, ≤64 chars, ASCII alphanumerics plus `-`/`_` -- `redact_secrets` scrubs Authorization / x-access-token headers, URL credentials, and Bearer tokens; clean input passes through byte-identical +### REQ-utils-001 + +The implementation SHALL meet this contract: `set_non_interactive` / `is_non_interactive` are the only accessors to the global flag + +### REQ-utils-002 + +The implementation SHALL meet this contract: `init_non_interactive_from_env` flips the flag when `FLEDGE_NON_INTERACTIVE` is a truthy value (`1`/`true`/`yes`/`y`/`on`, case-insensitive, trimmed) + +### REQ-utils-003 + +The implementation SHALL meet this contract: `is_interactive` returns true only when stdin is a TTY and the non-interactive flag is unset + +### REQ-utils-004 + +The implementation SHALL meet this contract: `require_interactive` / `require_interactive_hint` return `Ok(())` only when `is_interactive`, otherwise bail with a flag- or hint-named error + +### REQ-utils-005 + +The implementation SHALL meet this contract: Case conversions are pure and total — any input (including empty) returns a `String` without panicking + +### REQ-utils-006 + +The implementation SHALL meet this contract: `validate_project_name` rejects empty strings, `/`, `\`, `..`, null bytes, and Windows-reserved device names + +### REQ-utils-007 + +The implementation SHALL meet this contract: `validate_github_org` rejects empty and slash-containing names but permits spaces + +### REQ-utils-008 + +The implementation SHALL meet this contract: `validate_commit_scope` requires non-empty, ≤64 chars, ASCII alphanumerics plus `-`/`_` + +### REQ-utils-009 + +The implementation SHALL meet this contract: `redact_secrets` scrubs Authorization / x-access-token headers, URL credentials, and Bearer tokens; clean input passes through byte-identical ## Constraints diff --git a/specs/validate/requirements.md b/specs/validate/requirements.md index 05b735c3..48c35f3c 100644 --- a/specs/validate/requirements.md +++ b/specs/validate/requirements.md @@ -10,11 +10,25 @@ spec: validate.spec.md ## Acceptance Criteria -- Single template validation checks manifest, Tera syntax, variable definitions, and render globs -- Batch validation validates all templates in a directory independently -- Strict mode exits non-zero on warnings -- JSON mode outputs structured ValidationReport array -- GitHub Actions `${{ }}` expressions are not flagged as Tera variables +### REQ-validate-001 + +The implementation SHALL meet this contract: Single template validation checks manifest, Tera syntax, variable definitions, and render globs + +### REQ-validate-002 + +The implementation SHALL meet this contract: Batch validation validates all templates in a directory independently + +### REQ-validate-003 + +The implementation SHALL meet this contract: Strict mode exits non-zero on warnings + +### REQ-validate-004 + +The implementation SHALL meet this contract: JSON mode outputs structured ValidationReport array + +### REQ-validate-005 + +The implementation SHALL meet this contract: GitHub Actions `${{ }}` expressions are not flagged as Tera variables ## Constraints diff --git a/specs/versioning/requirements.md b/specs/versioning/requirements.md index b5900ca5..7e679952 100644 --- a/specs/versioning/requirements.md +++ b/specs/versioning/requirements.md @@ -1,5 +1,11 @@ # Versioning — Requirements +### REQ-versioning-001 + +The implementation SHALL satisfy the behavior described by this companion. + +Acceptance Criteria + 1. Parse semver strings (MAJOR.MINOR.PATCH) 2. Compare versions correctly (0.2.1 > 0.2.0, 1.0.0 > 0.99.99) 3. Check `min_fledge_version` against compile-time fledge version diff --git a/specs/watch/requirements.md b/specs/watch/requirements.md index 54ed66d0..0a744958 100644 --- a/specs/watch/requirements.md +++ b/specs/watch/requirements.md @@ -4,11 +4,34 @@ spec: watch.spec.md ## Requirements -- Watch a directory recursively for filesystem changes -- Re-run a specified task or lane when relevant files change -- Filter events by file extension (optional) -- Ignore common non-source directories (.git, target, node_modules, .fledge, __pycache__) -- Configurable debounce interval with deadline extension on new events -- Perform an initial run before entering the watch loop -- Optional terminal clear before each re-run -- Graceful error handling — target failures don't stop the watcher +### REQ-watch-001 + +The implementation SHALL meet this contract: Watch a directory recursively for filesystem changes + +### REQ-watch-002 + +The implementation SHALL meet this contract: Re-run a specified task or lane when relevant files change + +### REQ-watch-003 + +The implementation SHALL meet this contract: Filter events by file extension (optional) + +### REQ-watch-004 + +The implementation SHALL meet this contract: Ignore common non-source directories (.git, target, node_modules, .fledge, __pycache__) + +### REQ-watch-005 + +The implementation SHALL meet this contract: Configurable debounce interval with deadline extension on new events + +### REQ-watch-006 + +The implementation SHALL meet this contract: Perform an initial run before entering the watch loop + +### REQ-watch-007 + +The implementation SHALL meet this contract: Optional terminal clear before each re-run + +### REQ-watch-008 + +The implementation SHALL meet this contract: Graceful error handling — target failures don't stop the watcher diff --git a/specs/work/requirements.md b/specs/work/requirements.md index 80615d9a..2a0f03bb 100644 --- a/specs/work/requirements.md +++ b/specs/work/requirements.md @@ -16,25 +16,81 @@ spec: work.spec.md ## Acceptance Criteria -- `fledge work start ` creates a branch using the configured format (default: `{author}/{type}/{name}`) -- `fledge work start --branch-type fix` creates a fix-type branch -- `fledge work start --issue 42` includes issue number in branch name -- `fledge work start --prefix user/leif` creates `user/leif/` branch -- `fledge work start` refuses if working tree is dirty -- `fledge work start` rejects invalid branch types (not in feat, feature, fix, bug, chore, task, docs, hotfix, refactor) -- `fledge work commit` stages all changes and creates a commit (prompts for type + message interactively) -- `fledge work commit -m "message"` uses the given message with default type -- `fledge work commit --type fix -m "null pointer"` creates `fix: null pointer` commit -- `fledge work commit --ai` generates the commit message from staged diff using the configured AI provider -- `fledge work commit` refuses if there are no changes to commit -- `fledge work push` pushes the current branch to origin with `-u` tracking -- `fledge work push` refuses if on the default branch -- `fledge work push` refuses if there are no commits ahead of the remote -- `fledge work status` shows branch name, commits ahead/behind, and uncommitted file count -- `fledge work status` does NOT call `gh` or any GitHub API — pure git only -- Branch names are sanitized (lowercase, hyphens only) -- `[work]` section in `fledge.toml` can override `branch_format` and `default_type` -- All subcommands support `--json` for agent consumption +### REQ-work-001 + +The implementation SHALL meet this contract: `fledge work start ` creates a branch using the configured format (default: `{author}/{type}/{name}`) + +### REQ-work-002 + +The implementation SHALL meet this contract: `fledge work start --branch-type fix` creates a fix-type branch + +### REQ-work-003 + +The implementation SHALL meet this contract: `fledge work start --issue 42` includes issue number in branch name + +### REQ-work-004 + +The implementation SHALL meet this contract: `fledge work start --prefix user/leif` creates `user/leif/` branch + +### REQ-work-005 + +The implementation SHALL meet this contract: `fledge work start` refuses if working tree is dirty + +### REQ-work-006 + +The implementation SHALL meet this contract: `fledge work start` rejects invalid branch types (not in feat, feature, fix, bug, chore, task, docs, hotfix, refactor) + +### REQ-work-007 + +The implementation SHALL meet this contract: `fledge work commit` stages all changes and creates a commit (prompts for type + message interactively) + +### REQ-work-008 + +The implementation SHALL meet this contract: `fledge work commit -m "message"` uses the given message with default type + +### REQ-work-009 + +The implementation SHALL meet this contract: `fledge work commit --type fix -m "null pointer"` creates `fix: null pointer` commit + +### REQ-work-010 + +The implementation SHALL meet this contract: `fledge work commit --ai` generates the commit message from staged diff using the configured AI provider + +### REQ-work-011 + +The implementation SHALL meet this contract: `fledge work commit` refuses if there are no changes to commit + +### REQ-work-012 + +The implementation SHALL meet this contract: `fledge work push` pushes the current branch to origin with `-u` tracking + +### REQ-work-013 + +The implementation SHALL meet this contract: `fledge work push` refuses if on the default branch + +### REQ-work-014 + +The implementation SHALL meet this contract: `fledge work push` refuses if there are no commits ahead of the remote + +### REQ-work-015 + +The implementation SHALL meet this contract: `fledge work status` shows branch name, commits ahead/behind, and uncommitted file count + +### REQ-work-016 + +The implementation SHALL meet this contract: `fledge work status` does NOT call `gh` or any GitHub API — pure git only + +### REQ-work-017 + +The implementation SHALL meet this contract: Branch names are sanitized (lowercase, hyphens only) + +### REQ-work-018 + +The implementation SHALL meet this contract: `[work]` section in `fledge.toml` can override `branch_format` and `default_type` + +### REQ-work-019 + +The implementation SHALL meet this contract: All subcommands support `--json` for agent consumption ## Constraints diff --git a/src/spec/commands.rs b/src/spec/commands.rs index 6f1628fd..bcca0462 100644 --- a/src/spec/commands.rs +++ b/src/spec/commands.rs @@ -584,7 +584,7 @@ hashes.json style("✅").green().bold() ); - fs::write(specsync_dir.join("version"), "4.3.1\n")?; + fs::write(specsync_dir.join("version"), "5.0.1\n")?; println!("{} Created .specsync/version", style("✅").green().bold()); if !specs_dir.exists() { diff --git a/src/templates.rs b/src/templates.rs index f3d49dca..c841777a 100644 --- a/src/templates.rs +++ b/src/templates.rs @@ -1031,6 +1031,57 @@ ignore = ["template.toml"] assert_eq!(names.len(), 10, "expected exactly 10 built-in templates"); } + #[test] + fn corvid_stack_bootstrap_lane_is_substantive_and_placeholder_free() { + let template_path = + Path::new(env!("CARGO_MANIFEST_DIR")).join("templates/corvid-stack/fledge.toml"); + let contents = fs::read_to_string(template_path).unwrap(); + + for forbidden in ["TODO", "placeholder", "echo '", "echo \""] { + assert!( + !contents.contains(forbidden), + "corvid-stack bootstrap must not contain {forbidden}" + ); + } + + for required in [ + "git diff-tree --check --root -r -m --no-commit-id HEAD", + "fledge introspect", + ".specsync/config.toml .specsync/registry.toml .specsync/version AGENTS.md CLAUDE.md", + "workflow-check", + "steps = [\"format-check\", \"config-check\", \"governance-check\", \"workflow-check\"]", + ] { + assert!( + contents.contains(required), + "corvid-stack bootstrap is missing substantive check: {required}" + ); + } + + let policy_path = + Path::new(env!("CARGO_MANIFEST_DIR")).join("templates/corvid-stack/.specsync/sdd.json"); + let policy: serde_json::Value = + serde_json::from_str(&fs::read_to_string(policy_path).unwrap()).unwrap(); + assert!( + policy["meaningful_paths"] + .as_array() + .is_some_and(|paths| paths.iter().any(|path| path.as_str() == Some("."))), + "corvid-stack SDD policy must cover root-level and alternate source layouts" + ); + + let trust_workflow_path = Path::new(env!("CARGO_MANIFEST_DIR")) + .join("templates/corvid-stack/.github/workflows/trust.yml"); + let trust_workflow = fs::read_to_string(trust_workflow_path).unwrap(); + for required in [ + "specsync lifecycle enforce --all", + "specsync change check --strict", + ] { + assert!( + trust_workflow.contains(required), + "corvid-stack Trust workflow is missing SDD enforcement: {required}" + ); + } + } + #[test] fn render_template_creates_parent_dirs() { let tmp = TempDir::new().unwrap(); diff --git a/templates/corvid-stack/.augur.toml b/templates/corvid-stack/.augur.toml new file mode 100644 index 00000000..031b4599 --- /dev/null +++ b/templates/corvid-stack/.augur.toml @@ -0,0 +1,3 @@ +[thresholds] +review = 35 +block = 65 diff --git a/templates/corvid-stack/.github/workflows/trust.yml b/templates/corvid-stack/.github/workflows/trust.yml index 564f333c..9cd18167 100644 --- a/templates/corvid-stack/.github/workflows/trust.yml +++ b/templates/corvid-stack/.github/workflows/trust.yml @@ -1,14 +1,5 @@ name: Trust -# The CorvidLabs trust gate as parallel checks: fledge (quality), spec-sync -# (contract), augur (risk), attest (provenance), and the AGENTS.md rules marker. -# Each job is an independent PR check, so a failure points straight at the tool. -# Tools: https://corvidlabs.xyz/integrate/ -# -# These run in parallel because, in verify form, they are independent. If you -# later switch attest to `sign --from-augur augur.json --tests-passed`, attest -# depends on augur + tests: add `needs: [augur, fledge]` and pass augur.json -# between the jobs with upload-artifact / download-artifact. on: push: branches: [main] @@ -18,69 +9,23 @@ permissions: contents: read jobs: - # 1) fledge: the quality gate (the `verify` lane: fmt + lint + test + build). - fledge: + trust: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v4.1.6 with: fetch-depth: 0 - # fledge has no setup action; install the prebuilt binary (fast). Swap for - # `cargo install fledge --locked` or `brew install corvidlabs/tap/fledge` - # if you prefer. - - name: Install fledge - run: curl -fsSL https://raw.githubusercontent.com/CorvidLabs/fledge/main/install.sh | sh - - name: Verify (fledge lane) - run: fledge lanes run verify - # 2) spec-sync: spec-as-contract validation. - # Soft until specs land; drop continue-on-error once you have specs. - spec-sync: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - uses: CorvidLabs/spec-sync@v4 - continue-on-error: true - with: - strict: true - comment: false - - # 3) augur: deterministic diff-risk gate. Fails at/above `threshold`. - augur: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - with: - fetch-depth: 0 # range needs full git history - - uses: CorvidLabs/augur@v0 - with: - # PR: base..head. Push: the single pushed commit. Avoids the empty - # range that a hardcoded origin/main..HEAD gives on push to main. - range: ${{ github.event_name == 'pull_request' && format('origin/{0}..HEAD', github.base_ref) || format('{0}~1..{0}', github.sha) }} - threshold: block + - name: CorvidLabs Trust gate + id: trust + uses: CorvidLabs/trust@9d32b5786d2e9e4d39fc581c0091c721ee3d4226 # v1.0.0 - # 4) attest: signed provenance verification against .attest.json. - # The shipped policy is permissive; soft until you tighten it. - attest: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - name: Fetch provenance notes - run: git fetch origin "+refs/notes/*:refs/notes/*" 2>/dev/null || true - - uses: CorvidLabs/attest@v0 - continue-on-error: true - with: - range: ${{ github.event_name == 'pull_request' && format('origin/{0}..HEAD', github.base_ref) || format('{0}~1..{0}', github.sha) }} - policy: .attest.json + - name: Enforce SpecSync SDD lifecycle + run: | + specsync lifecycle enforce --all + specsync change check --strict - # 5) The managed agent-rules block must be present and intact. - rules: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - name: Check AGENTS.md trust marker + - name: Check managed agent rules run: | - grep -q "CorvidLabs trust toolchain: BEGIN" AGENTS.md \ - || { echo "::error::AGENTS.md is missing the managed CorvidLabs trust toolchain block"; exit 1; } + grep -q "CorvidLabs trust toolchain: BEGIN" AGENTS.md + grep -q "CorvidLabs trust toolchain: END" AGENTS.md diff --git a/templates/corvid-stack/.specsync/config.toml b/templates/corvid-stack/.specsync/config.toml index 8c30709c..1728dd62 100644 --- a/templates/corvid-stack/.specsync/config.toml +++ b/templates/corvid-stack/.specsync/config.toml @@ -1,4 +1,4 @@ -# spec-sync v4 configuration +# spec-sync v5 configuration # Docs: https://github.com/CorvidLabs/spec-sync specs_dir = "specs" # Set this to match your project's source layout, e.g. ["lib"], ["app"], diff --git a/templates/corvid-stack/.specsync/sdd.json b/templates/corvid-stack/.specsync/sdd.json new file mode 100644 index 00000000..ee71db1c --- /dev/null +++ b/templates/corvid-stack/.specsync/sdd.json @@ -0,0 +1,42 @@ +{ + "version": 1, + "enabled": true, + "require_change_for_meaningful_files": true, + "meaningful_paths": [ + ".", + "src/", + "tests/", + "specs/", + ".github/", + "Cargo.toml", + "Cargo.lock", + "package.json", + "bun.lock", + "package-lock.json", + "pnpm-lock.yaml", + "yarn.lock", + "Package.swift", + "Package.resolved", + "go.mod", + "go.sum", + "pyproject.toml", + "uv.lock", + "requirements.txt", + ".specsync/sdd.json", + ".specsync/config.toml", + ".specsync/registry.toml", + ".specsync/version", + "fledge.toml", + ".trust.toml", + ".augur.toml", + ".attest.json", + "AGENTS.md", + "CLAUDE.md" + ], + "ignored_paths": [], + "verification_commands": [ + "fledge lanes run verify" + ], + "custom_artifacts": {}, + "principles_file": null +} diff --git a/templates/corvid-stack/.specsync/version b/templates/corvid-stack/.specsync/version new file mode 100644 index 00000000..6b244dcd --- /dev/null +++ b/templates/corvid-stack/.specsync/version @@ -0,0 +1 @@ +5.0.1 diff --git a/templates/corvid-stack/.trust.toml b/templates/corvid-stack/.trust.toml new file mode 100644 index 00000000..dd9cad74 --- /dev/null +++ b/templates/corvid-stack/.trust.toml @@ -0,0 +1,22 @@ +schema_version = 1 +profile = "standard" + +[lifecycle] +command = ["fledge", "lanes", "run", "verify"] + +[contract] +enabled = true +require_coverage = 0 +skip_reason = "" + +[risk] +threshold = "block" + +[provenance] +mode = "soft" +policy = ".attest.json" +skip_reason = "" + +[atlas] +enabled = false +skip_reason = "Atlas publication was not enabled during project creation" diff --git a/templates/corvid-stack/README.md.tera b/templates/corvid-stack/README.md.tera index 1ff6f187..b42d6983 100644 --- a/templates/corvid-stack/README.md.tera +++ b/templates/corvid-stack/README.md.tera @@ -11,8 +11,10 @@ that gates every change through four tools. See https://corvidlabs.xyz/integrate |------|---------| | `fledge.toml` | Tasks plus the `verify` lane (the single quality gate) | | `.specsync/config.toml` | spec-sync configuration (spec-as-contract validation) | +| `.trust.toml` | unified Trust profile and component policy | +| `.augur.toml` | deterministic change-risk thresholds | | `.attest.json` | attestation policy (provenance verification) | -| `.github/workflows/trust.yml` | CI: fledge, spec-sync, augur, attest | +| `.github/workflows/trust.yml` | CI: unified Trust 1 gate | | `AGENTS.md` | Agent/human rules, incl. the managed trust-toolchain block | > Dropping this onto an existing repo? Merge the `.gitignore` and `AGENTS.md` @@ -23,14 +25,15 @@ that gates every change through four tools. See https://corvidlabs.xyz/integrate ```bash # Install the toolchain (macOS shown; see the guide for Linux/cargo) -brew install CorvidLabs/tap/fledge -cargo install specsync -# augur + attest run as GitHub Actions in trust.yml +brew install CorvidLabs/tap/corvid-trust -# Wire up your stack's tasks (auto-detects Rust, Node, Go, Python, Ruby, Java, Swift) -fledge run --init +# This source-free template starts with deterministic bootstrap checks. +# Before committing native application code, replace or extend those tasks in +# fledge.toml with the stack's format, lint, test, and build commands, and add +# every native task name to lanes.verify so Trust executes them. # Run the gate locally +fledge trust doctor fledge lanes run verify ``` @@ -38,10 +41,15 @@ Then fill in the `[tasks]` in `fledge.toml`, set `source_dirs` in `.specsync/config.toml` to match your layout, add a `*.spec.md` per module under `specs/`, and register it in `.specsync/registry.toml`. +The bootstrap lane validates real repository content and manifests; it is not a +substitute for native checks after source code is added. A generated project +must extend `lanes.verify` with its stack's checks in the same change that adds +native code. + ## The gate -Every push and PR runs `.github/workflows/trust.yml` as **five parallel checks**, -so a failure points straight at the tool: +Every push and PR runs one required `trust` job. Its component status outputs and +summary identify which layer failed: - **fledge** `lanes run verify`: fmt + lint + test + build - **spec-sync**: specs match code (soft until specs land) @@ -49,6 +57,6 @@ so a failure points straight at the tool: - **attest**: provenance verified against `.attest.json` - **rules**: the managed `AGENTS.md` trust block must be present -They run independently because, in verify form, none consumes another's output. -If you later switch attest to `sign --from-augur` (which needs augur's verdict -and the test result), make the attest job `needs: [augur, fledge]`. +The template starts with advisory contract coverage (`0`) because it contains no +source files or canonical companions. Raise `contract.require_coverage` as specs +are adopted; new specified behavior should reach 100%. diff --git a/templates/corvid-stack/fledge.toml b/templates/corvid-stack/fledge.toml index 7947242a..7de35113 100644 --- a/templates/corvid-stack/fledge.toml +++ b/templates/corvid-stack/fledge.toml @@ -1,15 +1,15 @@ # fledge.toml: tasks and lanes for the CorvidLabs trust toolchain. # Docs: https://github.com/CorvidLabs/fledge -# Fill these in for your stack. `fledge run --init` auto-detects Rust, Node, Go, -# Python, Ruby, Java, or Swift and can populate them for you. +# These deterministic starter checks work before application source exists. +# Replace or extend them with stack-native checks when application code is added. [tasks] -fmt = "echo 'TODO: format-check command (e.g. cargo fmt --check)'" -lint = "echo 'TODO: lint command (e.g. cargo clippy -- -D warnings)'" -test = "echo 'TODO: test command (e.g. cargo test)'" -build = "echo 'TODO: build command (e.g. cargo build)'" +format-check = "git diff-tree --check --root -r -m --no-commit-id HEAD" +config-check = "fledge introspect" +governance-check = "git ls-files --error-unmatch .trust.toml .augur.toml .attest.json .specsync/sdd.json .specsync/config.toml .specsync/registry.toml .specsync/version AGENTS.md CLAUDE.md" +workflow-check = "git ls-files --error-unmatch .github/workflows/trust.yml && git grep -q -F \"CorvidLabs/trust@9d32b5786d2e9e4d39fc581c0091c721ee3d4226\" -- .github/workflows/trust.yml" # The single quality gate. `.github/workflows/trust.yml` runs `fledge lanes run verify`. [lanes.verify] description = "The single quality gate" -steps = ["fmt", "lint", "test", "build"] +steps = ["format-check", "config-check", "governance-check", "workflow-check"]