Metadata-Version: 2.4
Name: fabricast
Version: 1.0.0
Summary: Composable AI role system with recipe-based generation for Cursor, Copilot, Claude, and Cline
Author: Edward Fry
License-Expression: MIT
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Software Development :: Code Generators
Requires-Python: >=3.11
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: pyyaml>=6.0
Requires-Dist: jsonschema>=4.20
Provides-Extra: dev
Requires-Dist: build>=1.0; extra == "dev"
Requires-Dist: setuptools>=77; extra == "dev"
Requires-Dist: wheel>=0.40; extra == "dev"
Requires-Dist: pytest>=8.0; extra == "dev"
Requires-Dist: pytest-cov>=4.0; extra == "dev"
Requires-Dist: pytest-xdist>=3.0; extra == "dev"
Requires-Dist: pytest-timeout>=2.0; extra == "dev"
Requires-Dist: ruff>=0.1.0; extra == "dev"
Requires-Dist: mypy>=1.0; extra == "dev"
Requires-Dist: types-PyYAML>=6.0; extra == "dev"
Requires-Dist: types-jsonschema>=4.20; extra == "dev"
Requires-Dist: black>=24.0; extra == "dev"
Requires-Dist: bandit>=1.7; extra == "dev"
Requires-Dist: pylint>=3.0; extra == "dev"
Requires-Dist: mutmut>=3.0; extra == "dev"
Requires-Dist: radon>=6.0; extra == "dev"
Requires-Dist: cognitive-complexity>=1.3; extra == "dev"
Provides-Extra: tooling
Requires-Dist: httpx>=0.27; extra == "tooling"
Requires-Dist: ruamel.yaml>=0.18; extra == "tooling"
Requires-Dist: packaging>=23.0; extra == "tooling"
Dynamic: license-file

# Fabricast

**Last Updated:** April 25, 2026

Composable YAML **roles** and **recipes** for AI coding assistants. Generates and installs tool-native rules for **Cursor**, **GitHub Copilot**, **Claude**, and **Cline**.

---

## 📚 Documentation

**New to Fabricast?** Start here:

### 🚀 Getting Started
- **[Quick Start Guide](docs/quickstart.md)** - Get up and running in 5 minutes
- **[User Guide](docs/user-guide.md)** - Complete workflows and usage patterns
- **[Global Command Setup](docs/global-command-setup.md)** - Make fabricast work from anywhere
- **[Troubleshooting](docs/troubleshooting.md)** - Common issues and solutions

### 🧠 Understanding Fabricast
- **[Core Concepts](docs/concepts.md)** - How Fabricast works (with diagrams!)
- **[Recipe Guide](docs/recipe-guide.md)** - Creating and customizing recipes
- **[Visual Diagrams](docs/diagrams.md)** - All diagrams in one place
- **[Diagram Style Guide](docs/diagram-style-guide.md)** - Visual design system

### 🔧 For Developers
- **[Developer Guide](docs/developer-guide.md)** - Setup, testing, and best practices
- **[Contributing Guide](docs/contributing.md)** - How to contribute (PR process, standards)
- **[Extending Fabricast](docs/extending.md)** - Adding new features (step-by-step)
- **[Architecture](docs/architecture.md)** - Technical design and patterns
- **[Requirements](docs/requirements.md)** - Product goals and principles

### 📖 Reference
- **[CLI Reference](docs/cli-reference.md)** - Complete command documentation
- **[Recipe Schema](docs/recipe-schema.md)** - YAML schema reference
- **[Examples & Cookbook](docs/examples.md)** - Real-world scenarios

---

## Code Quality

[![Coverage](https://img.shields.io/badge/coverage-91.18%25-brightgreen)](tests/)
[![Tests](https://img.shields.io/badge/tests-1334%20passing-brightgreen)](tests/)

**Automated Quality Guards** (enforced via `pytest`):
- ✅ Cyclomatic Complexity ≤ 10 (PRIMARY SRP guard)
- ✅ Method Count ≤ 10 per class
- ✅ File Size ≤ 400 lines per module
- ✅ Function Size ≤ 25 lines
- ✅ Import Count ≤ 10 per module
- ✅ Workspace Organization (17 convention tests)

See [docs/architecture.md#code-quality-standards](docs/architecture.md#code-quality-standards) for details.

## Requirements

- Python **3.11+**
- [PyYAML](https://pypi.org/project/PyYAML/) and [jsonschema](https://pypi.org/project/jsonschema/) (installed with the package)

## Installation

### One-Command Setup (Recommended)

**Same experience for both feed and local repo users:**

**From Azure Artifacts feed:**
```powershell
# After pip install fabricast
fabricast setup

# Or with PAT directly
fabricast setup --pat 'your-pat-here'
```

**From local repository:**
```powershell
.\scripts\Setup-Fabricast.ps1
```

Both approaches:
- ✓ Auto-detect feed vs local installation
- ✓ Handle pip configuration and package installation
- ✓ Ensure `fabricast` command works globally from any directory
- ✓ Configure PowerShell profile with helpful functions
- ✓ Are idempotent - safe to run multiple times

**Need a PAT for feed access?**
- Get one at: `https://dev.azure.com/edwardf/_usersSettings/tokens`
- Required scope: **Packaging (Read)**

**Additional options:**
```powershell
# Feed users - extract setup script without running it
fabricast setup --extract-only

# Feed users - run with specific options
fabricast setup --from-feed --skip-profile

# Local repo - run with options
.\scripts\Setup-Fabricast.ps1 -FromLocal -SkipProfile

# Local repo - test distribution by building wheel first
.\scripts\Setup-Fabricast.ps1 -FromLocal -BuildWheel
```

**Troubleshooting:** If setup fails, run the test suite for diagnostics:
```powershell
.\tests\Test-SetupScript.ps1
```

### After Setup

**Restart your terminal**, then test:

```bash
fabricast --version
fabricast verify          # confirms install health, PATH, and recipe data
fabricast list
fabricast install '*' --format cursor
```

**Alternative commands that always work:**
```bash
fab --version                          # Short alias (if profile configured)
python -m generator.cli.main --version  # Module form (always works)
```

### Manual Installation (Advanced)

If you prefer manual control:

**From Azure Artifacts feed:**
```powershell
# See scripts/Setup-Pythontools.ps1 for pip configuration details
pip install --user fabricast
```

**From local repository:**
```bash
pip install --user -e ".[dev]"
```

- **`[dev]`** — pytest and pytest-cov for tests.
- **`[tooling]`** — optional sidecar for auditing tool lists (`python -m tooling`). See [tooling/README.md](tooling/README.md).

**After manual installation, ensure global access:**
```powershell
.\scripts\Setup-Fabricast.ps1 -SkipProfile  # Just fix PATH, skip profile edits
```

## Making fabricast Globally Available

The `fabricast` command should work from **any directory** - this is handled automatically by `Setup-Fabricast.ps1`.

**If you used the recommended setup script, you're done!** Just restart your terminal.

**If you installed manually or having issues:**

```powershell
# Test if it's working
fabricast --version

# If not found, run the setup script to fix it
.\scripts\Setup-Fabricast.ps1
```

**📖 For troubleshooting and details: [Global Command Setup Guide](docs/global-command-setup.md)**

### How It Works

When you install fabricast, Python creates a `fabricast.exe` (Windows) or `fabricast` (Linux/Mac) in its Scripts directory. For the command to work globally:

1. **Package must be installed** - Not just cloned, but actually installed with pip
2. **Scripts folder must be in PATH** - So your shell can find the executable

**Setup-Fabricast.ps1 handles both automatically.**

### Three Ways to Use fabricast

After setup, you can use any of these commands:

```bash
# 1. Direct command (cleanest - requires PATH)
fabricast --version
fabricast list
fabricast install '*' --format cursor

# 2. PowerShell alias (convenient - if profile configured)
fab --version
fab list

# 3. Module form (always works - no PATH needed)
python -m generator.cli.main --version
python -m generator.cli.main list
```

### Troubleshooting

**Command not found?**
```powershell
# One command to fix everything
.\scripts\Setup-Fabricast.ps1

# Then restart your terminal
```

**Still having issues?**
See the [Global Command Setup Guide](docs/global-command-setup.md) for detailed troubleshooting.

## CLI

After install, use `fabricast …` (console script from `[project.scripts]`).

Common commands:

| Command | Purpose |
|--------|---------|
| `fabricast install '*' --format cursor` (or `copilot`, `claude`, `cline`) | Install all recipes globally (default target: user home) |
| `fabricast install '*game*' 'test-*' --format cursor` | Install recipes matching wildcard patterns |
| `fabricast remove 'game*' --format cursor` | Remove installed recipes matching wildcard patterns |
| `fabricast list '*game*' 'test-*'` | List recipes matching wildcard patterns |
| `fabricast set-active <recipe> --format cursor` (or `copilot`, `claude`, `cline`) | Switch active persona for that tool |
| `fabricast provision list` / `provision enable <name>` / `provision apply` | Apply optional, non-persona capabilities (status line, plugins, behaviors). See [docs/provisions.md](docs/provisions.md) |
| `fabricast ingest <source>` | Scan an external source and emit a report-only ingest proposal. See [docs/ingest.md](docs/ingest.md) and [docs/recipe-naming.md](docs/recipe-naming.md) |
| `fabricast discover [--source <repo>]` | Scan community indexes for candidates, flagging which already exist in Fabricast (report-only). See [docs/discovery.md](docs/discovery.md) |
| `fabricast recipe <name> --format copilot` | Print composed output for one recipe |
| `fabricast validate` | Validate roles/recipes against JSON Schema |
| `fabricast verify` | Verify install health (version, PATH, recipe data, active personas) |
| `fabricast list` | List roles and recipes |

> **v1.1.0 Breaking Change:** The `install-all` command has been replaced with `install` that accepts wildcard patterns.
> 
> **Migration:**
> - Old: `fabricast install-all --format cursor`
> - New: `fabricast install '*' --format cursor`
> 
> The new `install` command supports multiple glob patterns for more flexible recipe selection:
> - `install '*'` — install all recipes (replaces install-all)
> - `install '*game*'` — install all game-related recipes
> - `install 'test-*' '*python*'` — install test recipes and Python recipes
> 
> The `list` command also supports multiple patterns: `list '*game*' 'test-*'`

### Cursor: global install and User Rules sync

Fabricast's **global** `install` / `set-active` (default `--target global`, i.e. your user home) writes under `~/.cursor/rules/` **and** merges the same text into Cursor's **Settings > Rules for AI** storage (`aicontext.personalContext` in `%APPDATA%\Cursor\User\globalStorage\state.vscdb` on Windows, analogous paths on macOS/Linux). That way the Agent sees your personas in **every folder** without per-repo installs. After `set-active`, run **Reload Window** if Cursor was already open so the UI picks up the updated row.

If the DB is locked, quit Cursor once and re-run the command, or set `FABRICAST_SKIP_CURSOR_USER_SYNC=1` to only update files on disk.

**Note:** Sync **replaces** the entire Cursor **Rules for AI** field. If you already keep unrelated instructions there, copy them elsewhere first.

**"fabricast" in Cursor Settings:** Cursor may show a **fabricast** tab or filter under **Rules, Skills, Subagents**. Fabricast **cannot** hide that UI or mirror full state into it from this CLI (no supported API). That tab is **not** updated by `install` / `set-active`. **Source of truth** = this repo's YAML + CLI outputs (`~/.cursor/rules/`, `~/.fabricast/`, synced User rules, `~/.cursor/skills/`). Avoid adding parallel Rules or Skills there for personas—they can confuse people or conflict. The synced rules text includes a short reminder.


### Cursor skills (chat / slash)

Each successful **`install --format cursor`** (any `--target`) copies Agent skills from [`.cursor/skills/`](.cursor/skills/) into **`~/.cursor/skills/`** (Windows: `%USERPROFILE%\.cursor\skills\`) so **`/fabricast-*`** works in every workspace. No separate setup step.

| Skill | Purpose |
|--------|--------|
| `fabricast-current` | Show active recipe id (`~/.fabricast/cursor-active.json`) |
| `fabricast-list` | Run `generate.py list` (set **`FABRICAST_BASE`** to your clone when the workspace is not Fabricast) |
| `fabricast-set-active` | Run global `set-active <recipe> --format cursor` |

Set **`FABRICAST_SKIP_CURSOR_SKILLS=1`** to skip copying skills (e.g. in CI).

### GitHub Copilot (VS Code)

Global **`install '*' --format copilot`** writes always-on custom instructions under **`~/.copilot/instructions/`** (`fabricast-baseline`, `fabricast-router`, `fabricast-active` as `*.instructions.md` with `applyTo: "**"`, per [VS Code custom instructions](https://code.visualstudio.com/docs/copilot/customization/custom-instructions)). Recipe bodies are cached under **`~/.fabricast/copilot-recipes/`**. Switch persona: **`fabricast set-active <recipe> --format copilot`**.

### Claude Code

Global install writes **`~/.claude/rules/`** (`fabricast-baseline.md`, `fabricast-router.md`, `fabricast-active.md`) plus cache **`~/.fabricast/claude-recipes/`**, matching [Claude Code memory / user rules](https://code.claude.com/docs/en/memory). **`install '*' --format claude`** also publishes skills from **`.claude/skills/`** to **`~/.claude/skills/`** (skip with **`FABRICAST_SKIP_CLAUDE_SKILLS=1`**). Switch persona: **`fabricast set-active <recipe> --format claude`**.

### Cline

Global install writes **`~/Documents/Cline/Rules/`** (same three `fabricast-*.md` files) and cache **`~/.fabricast/cline-recipes/`**, consistent with Cline's global rules directory. Switch persona: **`fabricast set-active <recipe> --format cline`**.

Override where roles/recipes are read from (e.g. in tests):

```bash
set FABRICAST_BASE=C:\path\to\fabricast
fabricast validate
```

When the package is installed from PyPI without a nearby recipe tree, set `FABRICAST_BASE` to your clone or data directory.

## Working in this repository (clone)

Do **not** commit workspace-scoped rules that mirror the global install: **`.github/copilot-instructions.md`**, **`.claude/*.md`** (keep **`.claude/skills/`**), or recipe caches under **`.fabricast/*-recipes/`** and `*-active.json` in the clone. Those paths are ignored (see `.gitignore`) so Copilot, Claude Code, and Cursor pick up personas from your **global** `install` under your user profile. The small **`.fabricast/last-audit`** stamp stays versioned for tooling.

## Tests

```bash
# Full test suite (1,334 tests, ~91% coverage)
pytest

# Fast: unit tests only
pytest --ignore=tests/integration

# Faster: unit tests in parallel (~2-3x speedup)
pytest --ignore=tests/integration -n auto

# With coverage report (matches CI)
pytest --cov=src/generator --cov-report=term --cov-report=html

# Integration tests only
pytest tests/integration

# Skip audit tooling tests (optional dependency)
pytest -m "not audit_tooling"

# Run complexity guard tests
pytest tests/test_code_complexity_guards.py -v
```

**Performance Tips:**
- Use `-n auto` with pytest-xdist for parallel execution (2-4x faster on multi-core machines)
- Run unit tests alone during development: `pytest --ignore=tests/integration`
- Integration tests take ~85% of total runtime (mostly subprocess overhead)
- Coverage target: 90%+ (currently 91.18%)

**Quality Guards:** Automated tests enforce code complexity thresholds to prevent regression. See [docs/architecture.md#code-quality-standards](docs/architecture.md#code-quality-standards).

Integration-style tests live under [tests/integration/](tests/integration/).

## Package Structure

Fabricast uses a standard Python `src/` layout (PEP 517/518 compliant):

| Path | Role |
|------|------|
| `data/base/`, `data/language_specific/` | Role YAML |
| `data/recipes/` | Recipe YAML |
| `data/config/merge-config.yaml` | Merge **field_strategies** and conflict rules (used by the merger) |
| `data/schemas/` | JSON Schema for roles and recipes |
| `src/generator/` | Load, merge, validate, format, install |
| `src/generator/cli/` | CLI entry point and subcommand modules |
| `src/generator/cli/commands/` | Individual command modules (install, remove, set-active, skill, etc.) |
| `src/generator/formatters/` | Per-tool markdown/XML emitters |
| `src/generator/skills/` | Skill generation subsystem (composer, enhancer, metadata) |
| `tests/` | Test suite (1,334 tests, 91% coverage) |
| `tests/integration/` | Pipeline and install tests (shared helpers in `tests/integration/helpers.py`) |
| `src/tooling/` | Optional corpus auditor (`python -m tooling`) |
| `.cursor/skills/` | Optional Cursor Agent skills (current recipe, list, set-active) |
| `.claude/skills/` | Optional Claude Code skills (same commands, `--format claude`) |
| `docs/` | Requirements, architecture, and setup documentation |

**Key files:**
- `src/generator/copilot_layout.py`, `src/generator/claude_layout.py`, `src/generator/cline_layout.py` - Format-specific installers
- `src/generator/layout_common.py` - Shared baseline + router generation
- `src/generator/merger.py` - Recipe composition engine
- `src/generator/pipeline.py` - Generation pipeline orchestration

See [docs/architecture.md](docs/architecture.md) for detailed architecture and design decisions.

## Workspace Standards

**File Naming Conventions:**
- **Python files:** `snake_case.py` (e.g., `merge_config.py`)
- **PowerShell scripts:** `PascalCase-With-Hyphens.ps1` (e.g., `Setup-Pythontools.ps1`, `Connect-To-Pythontools-Feed.ps1`)
- **YAML/JSON config:** `kebab-case.yaml` (e.g., `merge-config.yaml`, `pyproject.toml`)
- **Documentation:** `kebab-case.md` (e.g., `architecture.md`, `requirements.md`)
- **Conventional root files:** `README.md`, `WORKSPACE_STATUS.md`, `MANIFEST.in` (allowed exceptions)
- **Bundled skills:** `SKILL.md` (required by convention)
- **Schema files:** `name.schema.json` pattern
- **Template files:** `name.extension.template` pattern

**Directory Organization:**
- **`src/`** — Python code only (no YAML, JSON, or markdown files)
- **`data/`** — Data files only (YAML, JSON, schemas, templates, no Python)
- **`tests/`** — Test files mirror `src/` structure (e.g., `tests/unit/generator/` mirrors `src/generator/`)
- **`scripts/`** — Operational PowerShell scripts (separate from `src/`)
- **`.tool-stuff/`** — Tool by-products (coverage reports, cache, quality reviews)
- **`docs/`** — Project documentation

**Enforced by:** 17 automated workspace convention tests in `tests/quality/workspace/`

Run workspace tests: `pytest tests/quality/workspace/ -v`

## License

See repository license file if present.
