Lokasi ngalangkungan proxy:   [ UP ]  
[Ngawartoskeun bug]   [Panyetelan cookie]                
Skip to content

BenGardiner123/spec-ferret

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

128 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

SpecFerret keeps your specs honest.

npm cli npm core Downloads Bun License Website

SpecFerret keeps your specs honest.

A Bun-first CLI that detects contract drift before it breaks downstream consumers.
Turns markdown contracts into a dependency graph, classifies drift, and blocks unsafe changes in local dev and CI.


πŸ“’ News

  • 2026-05-04 πŸŽ‰ Released v0.6.0 β€” ferret scan now auto-infers stable status when a contract's source resolves clean (NOOP upward drift). No manual status: active needed. See CHANGELOG.
  • 2026-05-04 πŸŽ‰ Released v0.5.0 β€” source field on defineContract() for cross-file upward drift (S63) and roadmap β†’ pending status rename with context.json v3.0 (S62). See CHANGELOG.
  • 2026-04-26 πŸ› Released v0.4.2 β€” dogfooding bug fixes: zod@4 compatibility, tree-sitter native module dedup, ContractRef type for consumes/dependsOn, and defineContract now returns schema: ZodObject<T> for safe composition. See release notes.
  • 2026-04-14 πŸŽ‰ Released v0.4.0 β€” ferret watch, ferret audit, and exported watch/audit APIs in @specferret/core. See CHANGELOG.
  • 2026-04-14 πŸŽ‰ Released v0.3.0 β€” TypeScript-native .contract.ts format with defineContract(), Zod-based schemas, ferret status command, and automatic .contract.ts discovery. See CHANGELOG.
  • 2026-04-14 πŸŽ‰ Released v0.2.0 β€” bidirectional drift enforcement (code β†’ spec), upward drift detection in ferret lint --ci, source: blocks, and guided resolution for code-origin drift. See CHANGELOG.
  • 2026-04-09 πŸŽ‰ Released v0.1.4 β€” agent mode scaffolding (--agent-targets), default tree-sitter TypeScript extraction (no annotations required), context schema versioning, diagnostics command, and perf budget hardening. See release notes.
  • 2026-04-04 πŸŽ‰ Released v0.1.3 β€” publish-safe Bun exports, smoke-fixture hardening, and npm packages refreshed. See release notes.
  • 2026-03-15 πŸš€ Released v0.1.0 β€” initial public release. ferret init, ferret scan, ferret lint, ferret review. Full BMAD and spec-kit validation runs passing.

Table of Contents


✨ Key Features

πŸ” Drift Detection β€” Parses .contract.md and .contract.ts files and detects shape changes automatically on every ferret lint.

πŸ’₯ Breaking vs Non-Breaking Classification β€” Missing required fields and removed properties are BREAKING. Optional additions are NON-BREAKING. You know exactly what needs review.

πŸ•ΈοΈ Dependency Graph β€” Contracts declare dependencies with imports (markdown) or consumes (TypeScript). SpecFerret computes the full direct and transitive impact graph so you know every consumer of a drifted contract.

⚑ Fast β€” ferret lint on a clean project completes in under 500ms. SQLite-backed, no external service.

πŸ”’ Pre-commit Enforcement β€” ferret init installs a .git/hooks/pre-commit hook that blocks commits when breaking drift is detected.

πŸ€– CI Mode β€” ferret lint --ci exits non-zero on drift, with JSON output for downstream tooling and agents.

πŸ› οΈ TypeScript Extraction β€” ferret extract infers contracts from exported TypeScript declarations by default, with // @ferret-contract: available as an override for explicit id and type.

πŸ“œ TypeScript-Native Contracts β€” Define contracts as .contract.ts files using defineContract() and Zod schemas. Full type safety, runtime invariants, and zero markdown.


πŸ—οΈ Architecture

SpecFerret is built in five strict layers. No layer reaches into another layer's domain.

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  CLI                                            β”‚
β”‚  ferret.ts Β· init Β· scan Β· lint Β· review        β”‚
β”‚  extract Β· status Β· watch Β· audit               β”‚
β”‚  Reads config, calls core, prints, exits.       β”‚
β”‚  Max 50 lines per command file.                 β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚  Reconciler                                     β”‚
β”‚  BFS traversal Β· flags dirty nodes Β· report     β”‚
β”‚  Never parses files. Never formats output.      β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚  Validator                                      β”‚
β”‚  JSON Schema subset Β· breaking / non-breaking   β”‚
β”‚  Pure function. No side effects. No I/O.        β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚  Extractor                                      β”‚
β”‚  .contract.md Β· .contract.ts Β· .ts (tree-sitter)β”‚
β”‚  Never talks to the store or the graph.         β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚  Store                                          β”‚
β”‚  SQLite (default) Β· Postgres (roadmap)          β”‚
β”‚  Parameterised SQL only. No business logic.     β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

πŸ“¦ Install

Global install (recommended)

bun install -g @specferret/cli

Verify

ferret --version

Tip

Bun 1.0 or later is required. Install it at bun.sh.

Install @specferret/core as a library

bun add @specferret/core
# or
npm install @specferret/core

Use @specferret/core directly when you want to integrate the extractor, validator, or reconciler into your own tooling or agent workflow.


πŸš€ Quick Start

1. Install

bun install -g @specferret/cli

2. Initialise your project

cd your-project
ferret init

This creates .ferret/ state, ferret.config.json, and installs a pre-commit hook.

Tip

Use ferret init --no-hook to skip the pre-commit hook.

3. Bootstrap contracts (choose one path)

Manual contract-first path:

mkdir -p contracts

Code-first TypeScript path:

ferret extract

ferret extract uses Tree-sitter to infer contracts from exported TypeScript declarations and scaffolds deterministic .contract.md files with no annotations required. @ferret-contract remains supported as a compatibility override for explicit id and type.

Example summary from inferred extraction:

ferret extract  created=7  updated=0  skipped=0  failed=0  inferred=12  annotated=2  143ms

4. Lint (default daily command)

ferret lint

ferret lint runs scan/reconcile checks and reports drift. Use ferret scan directly for advanced/manual graph refresh workflows.

Clean output:

βœ“ ferret  12 contracts  0 drift  9ms

Drift detected:

  ferret  3 contracts need review

  BREAKING  auth.jwt
  β”œβ”€β”€ contracts/search.contract.md          imports this directly
  β”œβ”€β”€ contracts/recommendations.contract.md imports this directly
  └── contracts/analytics.contract.md       imports this transitively (depth 2)

  NON-BREAKING  tables.document
  └── contracts/search.contract.md          optional field added β€” no action needed

  2 breaking  1 non-breaking

  β†’ Run ferret review to resolve

5. Resolve

ferret review

πŸ“ Your First Contract

Create a file under contracts/ with a ferret: frontmatter block:

---
ferret:
  id: api.GET/users
  type: api
  shape:
    type: array
    items:
      type: object
      properties:
        id:
          type: string
        email:
          type: string
      required: [id, email]
---

# GET /users

Returns the list of registered users.

Then run:

ferret lint

Now change required: [id, email] to required: [id] β€” removing email from required β€” and run lint again to see breaking drift detected.

Contract with imports (dependency)

Declare that one contract depends on another using imports:

---
ferret:
  id: api.POST/search
  type: api
  imports:
    - auth.jwt
  shape:
    type: object
    properties:
      query:
        type: string
      results:
        type: array
    required: [query, results]
---

# POST /search

Authenticated search endpoint. Depends on the JWT auth contract.

Now if auth.jwt shape changes, api.POST/search is flagged as an impacted consumer.

Code-first: extract contracts from TypeScript

SpecFerret extracts contracts from TypeScript by default, so no annotations are required for normal workflows. Use @ferret-contract only when you need an explicit id or type override:

// @ferret-contract: api.GET/users api
export interface GetUsersResponse {
  id: string;
  email: string;
}

Then run:

ferret extract

This scaffolds .contract.md files under contracts/ using deterministic mapping. Summary output includes created=<n>, updated=<n>, skipped=<n>, and failed=<n>. The command exits non-zero for hard extraction errors, when --perf-budget-ms is exceeded, and with exit code 2 when --perf-budget-ms is invalid.

Inferred output example:

ferret extract  created=5  updated=1  skipped=0  failed=0  inferred=5  annotated=1  87ms

Migration from annotation-first repositories:

  1. Keep existing @ferret-contract annotations in place initially.
  2. Run ferret extract and verify generated ids/types match expected contracts.
  3. Remove annotations incrementally where inferred ids/types are already correct.
  4. Retain annotations only for files that need explicit overrides.

Mixed repository mode is fully supported: inferred and annotated contracts can coexist in the same run.


πŸ’» CLI Reference

Command Purpose
ferret init Scaffold .ferret/ state, config, and pre-commit hook
ferret init --no-hook Scaffold without installing the pre-commit hook
ferret scan Parse contracts and refresh .ferret/context.json
ferret lint Detect and classify contract drift
ferret lint --ci CI mode β€” JSON output, exits non-zero on drift
ferret review Resolve blocking drift interactively
ferret review --json Emit versioned review JSON with suggested actions and dependency context
ferret extract Generate contracts from exported TypeScript (annotation override compatible)
ferret status Report current contract drift state (read-only)
ferret status --json Machine-readable status JSON (always exits 0)
ferret status --export Write STATUS.md to the project root
ferret watch Watch contract files and re-lint on change
ferret audit Full bidirectional drift report (downward + upward + integrity)
ferret diagnostics Print import graph diagnostics
Pre-commit hook behaviour

ferret init writes .git/hooks/pre-commit (when .git/hooks/ exists).

When you git commit, the hook runs ferret lint. If breaking drift is detected, the commit is blocked:

ferret  checking staged files...

  BREAKING  auth.jwt shape changed
  └── 3 downstream contracts need review

  commit blocked  β†’  run ferret review

Fix drift with ferret review, re-stage, and commit again.

ferret lint output formats

Default (human-readable)

βœ“ ferret  12 contracts  0 drift  9ms

CI mode (--ci)

Exits with code 1 when drift exists. Emits a JSON summary to stdout for downstream tools:

{
  "drift": true,
  "breaking": 2,
  "nonBreaking": 1,
  "diagnosticsSchemaVersion": "1.0.0",
  "diagnostics": [
    {
      "code": "FERRET_DRIFT_BREAKING",
      "severity": "error",
      "message": "auth.jwt impacts contracts/search/results.contract.md (direct, depth 1).",
      "location": {
        "contractId": "auth.jwt",
        "filePath": "contracts/search/results.contract.md",
        "depth": 1,
        "impact": "direct"
      },
      "remediation": "Run ferret review and resolve downstream drift before merge."
    }
  ],
  "contracts": [...]
}

Machine-readable diagnostics contract:

  • diagnosticsSchemaVersion identifies the stable diagnostics schema version for parsers
  • diagnostics[].code is a stable machine key (safe for switch/case routing)
  • diagnostics[].severity is one of error, warning, or info
  • diagnostics[].location carries file/contract/node/import context when available
  • diagnostics[].remediation is human-readable guidance for safe resolution

Parsing guidance:

  • Branch your parser by diagnosticsSchemaVersion first
  • Treat unknown code values as forward-compatible and fall back to message
  • Prefer code + location for automation and remediation for user-facing hints

Reference sample payloads:

  • docs/ci-templates/ferret-lint-ci-sample.json
  • docs/ci-templates/ferret-review-json-sample.json

End-to-end agent example (ferret review --json):

  1. Run ferret lint --ci and collect diagnostics.
  2. If drift is detected, run ferret review --json.
  3. For each reviewable[] item:
  • Use suggestedActions[] ordered by confidence to pick a default action.
  • Use dependencyContext.directDependents and dependencyContext.transitiveDependents to scope impacted files.
  1. Apply the selected action with ferret review --contract <id> --action <accept|update|reject> --json.
  2. Re-run ferret lint --ci and confirm consistent: true before merge.

οΏ½ TypeScript-Native Contracts (v0.3.0)

Instead of markdown frontmatter, define contracts directly in TypeScript with full type safety:

// contracts/auth.contract.ts
import { z } from 'zod';
import { defineContract } from '@specferret/core';

export const jwtPayload = defineContract({
  id: 'auth.jwt',
  value: 'JWT authentication payload',
  output: {
    sub: z.string(),
    email: z.string().email(),
    role: z.enum(['admin', 'user', 'viewer']),
    iat: z.number(),
  },
  invariants: [(r) => r.role !== ''],
  status: 'active',
});

Cross-file upward drift with source (v0.5.0)

Add a source field to point upward drift tracking at a named TypeScript type in your src/ directory. SpecFerret will compare the Zod output schema against the live implementation type via tree-sitter on every ferret lint:

// contracts/keywords.contract.ts
export const apiGetKeywords = defineContract({
  id: 'api.getKeywords',
  value: 'Keywords endpoint',
  output: {
    keywords: z.array(z.object({ keyword: z.string(), created_at: z.string() })),
    limit: z.number(),
    remaining: z.number(),
  },
  source: { file: 'src/routes/keywords.ts', symbol: 'KeywordsResponse' },
});
// src/routes/keywords.ts
export type KeywordsResponse = {
  keywords: Array<{ keyword: string; created_at: string }>;
  limit: number;
  remaining: number;
};

Now ferret lint detects drift between the Zod contract and the actual KeywordsResponse type β€” two representations, one enforcement check, no markdown spec needed.


**Why `.contract.ts`?**

- **`tsc` enforces your contract** β€” shape errors are compile errors, not runtime surprises
- **Zod schemas** β€” converted to JSON Schema automatically via `zod-to-json-schema`
- **Runtime invariants** β€” typed functions, not text descriptions
- **`consumes` references** β€” object references, not string IDs. Upstream shape changes break downstream contracts at compile time
- **`contract.schema`** β€” `defineContract` returns a `ZodObject<T>` on every contract. Use it for composition: `z.array(jwtPayload.schema)`, `z.object({ token: jwtPayload.schema })`. Do not compose with `contract.output` β€” that is the raw shape, not a schema.

> [!NOTE]
> v0.4.2 requires **zod@4**. If your project is on zod@3, upgrade: `bun add zod@4`.

**Using it:**

```bash
# .contract.ts files are discovered automatically β€” no config needed
ferret lint

# Disable if needed:
# ferret.config.json β†’ "contractParsers": { "typescript": false }

Both .contract.md and .contract.ts work in the same project. Mixed format is fully supported.

Contract with consumes (typed dependency)
// contracts/search.contract.ts
import { z } from 'zod';
import { defineContract } from '@specferret/core';
import { jwtPayload } from './auth.contract.js';

export const searchResults = defineContract({
  value: 'Search results endpoint',
  output: {
    query: z.string(),
    results: z.array(z.object({ id: z.string(), title: z.string() })),
  },
  consumes: [jwtPayload],
});

The consumes reference is resolved by object identity β€” no string matching. If jwtPayload changes shape, searchResults is flagged as impacted.

Check contract status
ferret status
ferret status  12 contracts

  stable        10
  needs-review   2

  NEEDS REVIEW
  auth.jwt          breaking β€” 3 dependents
  tables.document   non-breaking β€” 1 dependent

Machine-readable: ferret status --json Export to markdown: ferret status --export (writes STATUS.md)


οΏ½πŸ“ Contract Types

Type Use for
api REST endpoints, GraphQL operations, RPC methods
table Database tables, collections, document schemas
type Shared TypeScript types, interfaces, enums
event Domain events, webhooks, message queue payloads
flow User flows and multi-step process contracts
config Configuration shapes, environment schemas, flags

Each type uses the same frontmatter convention. The type field is used for grouping and reporting.

Type semantics are strict at runtime:

  • ferret.type must be exactly one of: api, table, type, event, flow, config
  • Unknown values are rejected during extraction with an error that lists allowed values
  • Custom type namespaces are not currently supported as runtime extensions

Extension model:

  • If a contract does not fit one of the six core types, use the closest core type and open an issue for model expansion

Migration note for legacy repos:

  • Replace legacy values like schema, service, or model with the closest supported core type before running ferret scan or ferret lint

πŸ—’ Changelog

See CHANGELOG.md for versioned changes and migration notes.


πŸ”„ How Drift Resolution Works

When ferret lint detects drift it classifies every violation:

Classification Trigger Action required
BREAKING Required field removed, property type changed Must resolve before merge
NON-BREAKING Optional field added, description changed only No action required

The impact report shows:

  • The drifting contract id and source file
  • Every downstream contract that imports it β€” direct and transitive
  • Depth of the transitive chain

Run ferret review to step through each breaking drift, choose an action (accept / update / reject), and write resolution notes back to the contract file.

End-to-end agent loop (`ferret review --json`)
  1. Ask your agent to run:
ferret review --json
  1. Agent reads each review item and prioritizes suggestedActions by confidence.
  2. Agent uses dependencyContext and the direct/transitive impact lists to update downstream files in blast-radius order.
  3. Agent re-runs:
ferret lint --ci
  1. If clean, agent proceeds with commit/PR. If drift remains, it repeats the review loop with the new JSON payload.

πŸ§ͺ CI Integration

Minimal GitHub Actions step (reusable action)

- name: SpecFerret CI
  uses: BenGardiner123/action@v1
  with:
    baseline-mode: committed

Full job example

jobs:
  ferret:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: SpecFerret CI
        uses: BenGardiner123/action@v1
        with:
          baseline-mode: committed
          artifact-name: ferret-lint-ci

Starter templates:

  • docs/ci-templates/ferret-action-single-package.yml
  • docs/ci-templates/ferret-action-monorepo.yml
  • docs/ci-templates/ferret-action-pr-only.yml

Tip

Commit .ferret/context.json to your repo. The default --ci-baseline committed mode reads from it, so CI passes on the first run without a rebuild step.

Baseline modes

Mode When to use
--ci-baseline committed Default. Requires committed context.json.
--ci-baseline rebuild Ephemeral runners or fresh checkouts.

🀝 BMAD & spec-kit Integration

SpecFerret is not a planning tool. It enforces contract consistency downstream of planning tools.

If you use BMAD or spec-kit:

  1. Produce PRD, architecture, and stories as usual
  2. Capture concrete shapes in .contract.md files under contracts/
  3. Run ferret lint to validate and enforce consistency across the team

Example repo layout

your-project/
  _bmad-output/
    PRD.md
    architecture.md
  contracts/
    auth/
      jwt.contract.md
    tables/
      user.contract.md
    api/
      get-users.contract.md
  .ferret/
    context.json
  ferret.config.json

Tip

Ask your AI agent to ferret lint --ci as a sub-step whenever it generates or edits code that might touch a contract boundary. This catches AI-introduced drift before it reaches review.


πŸ’‘ Use Cases

API teams preventing breaking changes

Map every REST endpoint, GraphQL operation, or RPC method to a .contract.md file. Declare which other contracts import each API surface. When a shape change breaks a required field on a consumer, ferret lint catches it in seconds β€” not days.

Multi-team monorepos

Teams working in the same repo often change shared types without realising the downstream blast radius. SpecFerret's dependency graph shows every contract that transitively depends on a changed type β€” and blocks the commit until drift is resolved or accepted.

AI-assisted development

AI code generation accelerates implementation but outpaces documentation. Add ferret lint --ci to your CI pipeline so that every AI-generated PR is checked for contract drift. Use ferret review --json to feed the impact report back to your agent for automated resolution.

Schema governance

Long-lived product surfaces β€” database tables, event payloads, config shapes β€” drift over years. SpecFerret's SQLite graph persists the contract state so you always have a before/after diff of every shape change, not just a snapshot.


πŸ“ Project Structure

specferret/
β”œβ”€β”€ packages/
β”‚   β”œβ”€β”€ core/               @specferret/core
β”‚   β”‚   └── src/
β”‚   β”‚       β”œβ”€β”€ store/      # DBStore interface Β· SQLite Β· Postgres Β· factory
β”‚   β”‚       β”œβ”€β”€ extractor/  # frontmatter.ts Β· typescript.ts Β· typescript-contract.ts Β· validator.ts Β· upward-classifier.ts Β· hash.ts
β”‚   β”‚       β”œβ”€β”€ reconciler/ # BFS engine β€” dirty node flagging
β”‚   β”‚       β”œβ”€β”€ context/    # context.json writer
β”‚   β”‚       β”œβ”€β”€ watch/      # file watcher
β”‚   β”‚       β”œβ”€β”€ audit/      # bidirectional audit report
β”‚   β”‚       β”œβ”€β”€ config.ts   # project config loader
β”‚   β”‚       └── index.ts    # public re-exports
β”‚   └── cli/                @specferret/cli
β”‚       └── bin/
β”‚           β”œβ”€β”€ commands/   # init Β· scan Β· lint Β· review Β· extract Β· status Β· watch Β· audit
β”‚           └── ferret.ts   # CLI entrypoint
β”œβ”€β”€ apps/
β”‚   └── site/               specferret.dev (Astro)
β”œβ”€β”€ spec/                   Architecture, stories, contract schema
β”œβ”€β”€ docs/                   Quickstart, demo runbook, images
└── scripts/                Build helpers

πŸ›£οΈ Roadmap

PRs welcome. The codebase is intentionally small and readable.

  • Postgres store β€” production-grade persistence without SQLite
  • ferret audit β€” bidirectional drift report across all contracts (shipped v0.4.0)
  • roadmap β†’ pending status rename β€” contract lifecycle uses pending everywhere; ferret lint shows βœ“ only when pending count is zero; context.json v3.0 (shipped v0.5.0 / S62)
  • source field on defineContract() β€” cross-file upward drift for .contract.ts projects without the three-representation trap (shipped v0.5.0 / S63)
  • Auto-infer stable from source during ferret scan β€” contracts auto-promote from pending β†’ stable when source resolves clean; no manual declaration needed (shipped v0.6.0)
  • ferret upgrade β€” SQLite β†’ Postgres migration command
  • ferret place β€” AI-powered feature placement against the graph
  • ferret benchmark β€” provider benchmarking for AI-assisted review
  • GitHub Action adoption (Sprint 6) β€” one-line CI enforcement via uses: BenGardiner123/action@v1
  • Upward code-to-spec drift (Sprint 7) β€” catch implementation drift when specs are not updated
  • TypeScript-native contracts (Sprint 8) β€” .contract.ts with defineContract(), Zod schemas, ferret status
  • Tree-sitter extraction β€” TypeScript shape extraction without annotations (shipped)
  • Multi-language support β€” Go, Python, OpenAPI (post Phase 5)
  • Hosted dashboard β€” team-wide contract health, analytics, SSO/RBAC
  • Branch-matrix dogfooding (Sprint 5) β€” scenario branches across spec-kit and BMAD validation repos

See spec/ROADMAP.MD for the full plan.


βœ… Validation Evidence

Latest validated evidence (post explicit S40/S41/S42 assertions):

Validation Link
spec-kit matrix run actions/runs/23962649755
BMAD matrix run actions/runs/23962652352

Release evidence (v0.1.3 publish window):

Validation Link
spec-kit validation run actions/runs/23962649755
BMAD validation run actions/runs/23962652352
@specferret/core@0.1.3 on npm npmjs.com/package/@specferret/core
@specferret/cli@0.1.3 on npm npmjs.com/package/@specferret/cli

Sprint 5 expands this from a single smoke path to a branch matrix. Operational details live in spec/GA-VALIDATION-REPOS.MD and spec/GA-VALIDATION-RUNBOOK.MD.


πŸ› οΈ Development

bun install
bun test
bun run build

Performance benchmark guardrails

Use explicit performance budgets when validating contributor changes:

# Lint clean-run budget (project baseline target)
ferret lint --perf-budget-ms 500

# Extract runtime budget (tune per fixture/repo size in CI)
ferret extract --perf-budget-ms 1000

If a budget is exceeded, the command exits non-zero and prints an actionable diagnostic.

Documentation safety rule

  • Never include PII or secrets in docs, contracts, runbooks, screenshots, logs, or release evidence.
  • Always use synthetic placeholders (for example user@example.test, REDACTED_TOKEN).
  • Redact sensitive values before commit.

Monorepo packages

Package Path npm
@specferret/core packages/core npm
@specferret/cli packages/cli npm
specferret.dev (Astro) apps/site β€”

Docs


⭐ Star History


MIT License Β· specferret.dev Β· "SpecFerret keeps your specs honest."