From 150ba2df55ec33581eafd1167d32fe532ae6bba2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Baudet?= Date: Thu, 6 Aug 2026 11:03:24 -0600 Subject: [PATCH 1/3] chore: prepare repository for public release Prepares vgv-ffca-plugin for going public and for registration in the Very Good Claude Marketplace. - Remove docs/ (internal spec, kickoff prompt, and implementation plan) - Add MIT LICENSE, matching the other VGV plugin repositories - Add release-please config, manifest, and workflow so the marketplace version-sync workflow has GitHub releases to read - Add CI: markdown lint, spell check, layer validator tests, and claude plugin validate - Enrich plugin.json with homepage, repository, and keywords - Add version and metadata description to the self-hosted marketplace manifest, wired into release-please extra-files - Rewrite the README install section for the public marketplace Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01SNHNDnPH7H7y2m4Pbsbmme --- .claude-plugin/marketplace.json | 5 + .claude-plugin/plugin.json | 14 +- .github/workflows/ci.yaml | 62 ++++ .github/workflows/release_please.yaml | 22 ++ .release-please-config.json | 44 +++ .release-please-manifest.json | 3 + CHANGELOG.md | 10 + LICENSE | 21 ++ README.md | 11 +- config/cspell.json | 18 ++ config/custom.markdownlint.jsonc | 8 + .../2026-06-10-feat-vgv-ffca-plugin-plan.md | 218 ------------- docs/source/vgv_ffca_kickoff_prompt.md | 97 ------ docs/source/vgv_ffca_plugin_spec.md | 287 ------------------ 14 files changed, 210 insertions(+), 610 deletions(-) create mode 100644 .github/workflows/ci.yaml create mode 100644 .github/workflows/release_please.yaml create mode 100644 .release-please-config.json create mode 100644 .release-please-manifest.json create mode 100644 CHANGELOG.md create mode 100644 LICENSE create mode 100644 config/cspell.json create mode 100644 config/custom.markdownlint.jsonc delete mode 100644 docs/plan/2026-06-10-feat-vgv-ffca-plugin-plan.md delete mode 100644 docs/source/vgv_ffca_kickoff_prompt.md delete mode 100644 docs/source/vgv_ffca_plugin_spec.md diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json index 6c9ffb3..59225f2 100644 --- a/.claude-plugin/marketplace.json +++ b/.claude-plugin/marketplace.json @@ -4,10 +4,15 @@ "name": "Very Good Ventures", "url": "https://verygood.ventures" }, + "metadata": { + "description": "Self-hosted marketplace for the VGV FFCA plugin, for local development and direct installs.", + "version": "0.1.0" + }, "plugins": [ { "name": "vgv-ffca-plugin", "source": "./", + "version": "0.1.0", "description": "Feature-First Clean Architecture (FFCA) for Flutter monorepos. Skills, validation hooks, and conventions for AI-first development, by Very Good Ventures." } ] diff --git a/.claude-plugin/plugin.json b/.claude-plugin/plugin.json index b0ceb47..91bca41 100644 --- a/.claude-plugin/plugin.json +++ b/.claude-plugin/plugin.json @@ -6,5 +6,17 @@ "name": "Very Good Ventures", "url": "https://verygood.ventures", "email": "hello@verygood.ventures" - } + }, + "homepage": "https://github.com/VeryGoodOpenSource/vgv-ffca-plugin", + "repository": "https://github.com/VeryGoodOpenSource/vgv-ffca-plugin", + "keywords": [ + "flutter", + "dart", + "clean architecture", + "feature-first", + "monorepo", + "architecture", + "layer validation", + "ai assisted engineering" + ] } diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml new file mode 100644 index 0000000..0e1da5b --- /dev/null +++ b/.github/workflows/ci.yaml @@ -0,0 +1,62 @@ +name: ci + +on: + pull_request: + branches: + - main + +jobs: + markdown: + name: ๐Ÿ“ Markdown Quality + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v7 + - name: Lint Markdown + uses: DavidAnson/markdownlint-cli2-action@v24.1.0 + with: + globs: | + **/*.md + !CHANGELOG.md + !references/ffca_architecture.md + config: 'config/custom.markdownlint.jsonc' + + spelling: + name: โœ๏ธ Spelling Check + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v7 + - name: Spell Check + uses: streetsidesoftware/cspell-action@v8 + with: + files: | + **/*.md + !CHANGELOG.md + config: 'config/cspell.json' + + validator: + name: ๐Ÿงช Layer Validator + runs-on: ubuntu-latest + defaults: + run: + working-directory: scripts + steps: + - uses: actions/checkout@v7 + - uses: dart-lang/setup-dart@v1 + - name: Install dependencies + run: dart pub get + - name: Analyze + run: dart analyze --fatal-infos + - name: Format + run: dart format --output=none --set-exit-if-changed . + - name: Test + run: dart test + + plugin-validate: + name: ๐Ÿ“ฆ Plugin Validation + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v7 + - name: Install Claude Code + run: npm install -g @anthropic-ai/claude-code + - name: Validate Plugin + run: claude plugin validate . diff --git a/.github/workflows/release_please.yaml b/.github/workflows/release_please.yaml new file mode 100644 index 0000000..0556ed1 --- /dev/null +++ b/.github/workflows/release_please.yaml @@ -0,0 +1,22 @@ +name: release_please + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +on: + workflow_dispatch: + push: + branches: + - main + +jobs: + create_release_pr: + runs-on: ubuntu-latest + + steps: + - uses: googleapis/release-please-action@v5 + with: + token: ${{ secrets.RELEASE_PLEASE_TOKEN }} + manifest-file: ".release-please-manifest.json" + config-file: ".release-please-config.json" diff --git a/.release-please-config.json b/.release-please-config.json new file mode 100644 index 0000000..cd4337d --- /dev/null +++ b/.release-please-config.json @@ -0,0 +1,44 @@ +{ + "$schema": "https://raw.githubusercontent.com/googleapis/release-please/main/schemas/config.json", + "bump-minor-pre-major": true, + "bump-patch-for-minor-pre-major": true, + "changelog-sections": [ + { "type": "feat", "section": "Features" }, + { "type": "fix", "section": "Bug Fixes" }, + { "type": "refactor", "section": "Refactors" }, + { "type": "chore", "section": "Miscellaneous Chores" }, + { "type": "docs", "section": "Docs" } + ], + "pull-request-header": ":rotating_light: There are changes ready for release :rocket:\n\nโ„น Merge this PR once the team confirms the release is ready.\n", + "pull-request-title-pattern": "chore: ${version}", + "extra-label": "no-auto-update", + "include-component-in-tag": false, + "packages": { + ".": { + "release-type": "simple", + "changelog-path": "CHANGELOG.md", + "extra-files": [ + { + "type": "json", + "path": ".claude-plugin/plugin.json", + "jsonpath": "$.version" + }, + { + "type": "json", + "path": ".claude-plugin/marketplace.json", + "jsonpath": "$.metadata.version" + }, + { + "type": "json", + "path": ".claude-plugin/marketplace.json", + "jsonpath": "$.plugins[0].version" + } + ] + } + }, + "exclude-paths": [ + ".github", + ".release-please-manifest.json", + ".release-please-config.json" + ] +} diff --git a/.release-please-manifest.json b/.release-please-manifest.json new file mode 100644 index 0000000..466df71 --- /dev/null +++ b/.release-please-manifest.json @@ -0,0 +1,3 @@ +{ + ".": "0.1.0" +} diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..339595b --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,10 @@ +# Changelog + +## 0.1.0 + +### Features + +- FFCA skills: architecture, feature, routing, cross-feature, and audit +- Blocking `pubspec.yaml` layer-dependency validation hook +- `ffca-layer-auditor` agent for whole-repo architecture audits +- Very Good CLI MCP server configuration diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..0441486 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2026 Very Good Ventures + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md index 4165a44..5d0c18c 100644 --- a/README.md +++ b/README.md @@ -37,22 +37,19 @@ The `ffca-architecture` skill defers to `layered-architecture` when it sees the ## Installation -The plugin is currently a private repository in the VeryGoodOpenSource organization. Anyone with git access (via `gh auth`) can install it as a Claude Code marketplace. - -For the platform team pilot, add the repository as a marketplace and install: +The plugin is published in the [Very Good Claude Marketplace](https://github.com/VeryGoodOpenSource/very_good_claude_marketplace). Inside Claude: ```bash -claude plugin marketplace add VeryGoodOpenSource/vgv-ffca-plugin && claude plugin install vgv-ffca-plugin +/plugin marketplace add VeryGoodOpenSource/very-good-claude-code-marketplace +/plugin install vgv-ffca-plugin ``` -For local iteration, install from a checkout path: +For local iteration, install from a checkout path instead: ```bash claude plugin marketplace add /path/to/vgv-ffca-plugin && claude plugin install vgv-ffca-plugin ``` -At v1.0 the repository goes public and registers in the `very_good_claude_marketplace` for one-line public install. - ## Skills | Skill | Description | diff --git a/config/cspell.json b/config/cspell.json new file mode 100644 index 0000000..4536f76 --- /dev/null +++ b/config/cspell.json @@ -0,0 +1,18 @@ +{ + "language": "en", + "words": [ + "dtos", + "ffca", + "mappr", + "mocktail", + "operationalizes", + "posthog", + "pubspec", + "pubspecs", + "rebuildable", + "riverpod", + "subcomponents", + "subfeature" + ], + "flagWords": [] +} diff --git a/config/custom.markdownlint.jsonc b/config/custom.markdownlint.jsonc new file mode 100644 index 0000000..d6da083 --- /dev/null +++ b/config/custom.markdownlint.jsonc @@ -0,0 +1,8 @@ +{ + "MD009": false, + "MD013": false, + "MD032": false, + "MD033": false, + "MD036": false, + "MD060": false +} diff --git a/docs/plan/2026-06-10-feat-vgv-ffca-plugin-plan.md b/docs/plan/2026-06-10-feat-vgv-ffca-plugin-plan.md deleted file mode 100644 index 974be43..0000000 --- a/docs/plan/2026-06-10-feat-vgv-ffca-plugin-plan.md +++ /dev/null @@ -1,218 +0,0 @@ ---- -title: Implement vgv-ffca-plugin -type: feat -date: 2026-06-10 ---- - -## Implement vgv-ffca-plugin - Standard - -## Overview - -Build the `vgv-ffca-plugin` Claude Code plugin exactly as specified in `vgv_ffca_plugin_spec.md`. The plugin operationalizes Feature-First Clean Architecture (FFCA) for Flutter monorepos through three asset types: - -1. **Five skills** that teach Claude FFCA workflows (`ffca-architecture`, `ffca-feature`, `ffca-routing`, `ffca-cross-feature`, `ffca-audit`). -2. **A blocking validation hook** (`PostToolUse` on `Edit|Write`) that enforces layer dependency rules on every `pubspec.yaml` edit, backed by a pure-Dart `validate_layers.dart` script. -3. **An MCP configuration** wiring the Very Good CLI server. - -The spec is the source of truth for structure, skill trigger descriptions, hook behavior, and validation rules. `ffca_architecture.md` is the conventions reference: it is copied verbatim to `references/ffca_architecture.md` and is never rewritten or summarized. Skills carry workflow guidance only; they point into the reference by section name so conventions live in exactly one place. - -## Problem Statement / Motivation - -FFCA is the approved VGV monorepo architecture, but there is no tooling to enforce its layer rules or teach its conventions to AI agents. The plugin is the delivery vehicle for the architecture, available before the FFCA SDK exists. It is the **Structure** layer of VGV's AI engineering stack, sitting between `vgv-wingspan` (workflow) and `vgv-ai-flutter-plugin` (code quality). It must coexist with `vgv-ai-flutter-plugin` without trigger conflicts: every skill self-scopes to FFCA repos via its description (detection signal: a `features/` folder containing `{feature}_domain`, `{feature}_data`, or `{feature}_presentation` packages). - -## Proposed Solution - -Build bottom-up, highest-risk-first. The validation script is the riskiest component (real logic, exit-code contract with the hook), so it is built test-first before anything else. Then the hook wraps it, then the skills and reference, then MCP config and README, then end-to-end verification. - -### Structural reference (already studied) - -The sibling plugin `vgv-ai-flutter-plugin` (in the plugin cache) establishes the conventions to mirror: - -- **`hooks/scripts/analyze.sh`** is the template for the validation hook wrapper: `set -euo pipefail`, read stdin payload, check `jq` availability and skip gracefully, extract `file_path` with `jq -r '.tool_input.file_path // empty'`, filter by file type, run the tool, capture output and `exit 2` on failure. -- **SKILL.md frontmatter** uses these keys: `name`, `description`, `when_to_use`, `allowed-tools`, `effort`. The spec's "Description (trigger)" text maps to the combined `description` + `when_to_use` fields. -- **`.mcp.json`**, **`plugin.json`**, and the **README layout** (overview, installation, skills table, hooks table with prerequisites) all follow the sibling's shape. - -Decision: the sibling's `hooks.json` references scripts at `hooks/scripts/`. The FFCA spec places `validate_layers.sh` directly at `hooks/validate_layers.sh`. **Follow the spec exactly** (`hooks/validate_layers.sh`, command `${CLAUDE_PLUGIN_ROOT}/hooks/validate_layers.sh`), not the sibling's nested layout. - -### Final plugin structure - -``` -vgv-ffca-plugin/ -โ”œโ”€โ”€ .claude-plugin/ -โ”‚ โ””โ”€โ”€ plugin.json -โ”œโ”€โ”€ references/ -โ”‚ โ”œโ”€โ”€ ffca_architecture.md # byte-identical copy of provided file -โ”‚ โ””โ”€โ”€ code_templates/ -โ”‚ โ”œโ”€โ”€ domain_templates.md -โ”‚ โ”œโ”€โ”€ data_templates.md -โ”‚ โ””โ”€โ”€ presentation_templates.md -โ”œโ”€โ”€ skills/ -โ”‚ โ”œโ”€โ”€ ffca-architecture/SKILL.md -โ”‚ โ”œโ”€โ”€ ffca-feature/SKILL.md -โ”‚ โ”œโ”€โ”€ ffca-routing/SKILL.md -โ”‚ โ”œโ”€โ”€ ffca-cross-feature/SKILL.md -โ”‚ โ””โ”€โ”€ ffca-audit/SKILL.md -โ”œโ”€โ”€ hooks/ -โ”‚ โ”œโ”€โ”€ hooks.json -โ”‚ โ””โ”€โ”€ validate_layers.sh -โ”œโ”€โ”€ scripts/ -โ”‚ โ”œโ”€โ”€ validate_layers.dart -โ”‚ โ”œโ”€โ”€ pubspec.yaml # for package:yaml + package:test -โ”‚ โ”œโ”€โ”€ sync_reference.dart # stub with TODO (out of scope to implement) -โ”‚ โ””โ”€โ”€ test/ -โ”‚ โ”œโ”€โ”€ validate_layers_test.dart -โ”‚ โ””โ”€โ”€ fixtures/ -โ”‚ โ”œโ”€โ”€ valid_workspace/ -โ”‚ โ””โ”€โ”€ invalid_workspace/ -โ”œโ”€โ”€ .mcp.json -โ””โ”€โ”€ README.md -``` - -Note: `scripts/test/` and `scripts/pubspec.yaml` are not in the spec's structure diagram, but the kickoff explicitly requires a `dart test` suite and a pubspec is acceptable for `package:yaml`. They live under `scripts/` so the validator and its tests form one self-contained Dart package. - -## Technical Considerations - -### `scripts/validate_layers.dart` (highest risk, build test-first) - -**Constraints:** pure Dart. `dart:io` + `dart:core` for filesystem and process. `package:yaml` to parse pubspecs (acceptable per kickoff; requires `scripts/pubspec.yaml`). - -**CLI surface:** -- `--file `: incremental mode (default for the hook). Validates the edited package plus its direct dependents. -- `--all`: full-graph mode. Validates every package and runs a workspace-wide topological cycle check. Used by CI and the `ffca-audit` skill. - -**Workspace discovery:** from the target pubspec, walk parent directories to find the workspace root (the dir containing `features/`, typically also the root `pubspec.yaml` with a `workspace:` key). Build a map of every package: `name โ†’ {path, layer, feature, dependencies}`. Layer/feature are inferred from the path under `features/{f}/{f}_{layer}` and the package name. - -**Rules constant (isolated at top of file):** a `const rules` block, commented with a pointer to the `Dependency Graph Rules` section of `references/ffca_architecture.md`, so a convention change maps to one code location. Implements the spec's checks table verbatim: - -| Check | Rule | -|---|---| -| Naming | A package under `features/{f}/` must be named `{f}_domain`, `{f}_data`, `{f}_data_{backend}`, or `{f}_presentation` | -| Domain deps | Path deps on other `*_domain` packages and `shared/` Dart packages only | -| Data deps | Own `{f}_domain` + `shared/`. Never any `*_presentation`, never another feature's `*_data` | -| Presentation deps | Own `{f}_domain`, other `*_domain`, other `*_presentation`, `shared/`. Never any `*_data` | -| Shared deps | External pub packages + other `shared/` packages only. Never `features/` | -| Apps | May depend on anything. Nothing depends on an app | -| Cycles | Incremental: cycles reachable from edited package. `--all`: topological sort of full graph | - -**Only path dependencies are checked** (local packages). External pub dependencies are ignored for layer rules. The "shared deps: external only" rule means a `shared/` package must have no path dependency pointing into `features/`. - -**Violation output (stderr, then `exit 2`)** matches the spec format exactly โ€” the rule AND the fix on each finding: - -``` -FFCA violation in features/cart/cart_presentation/pubspec.yaml: - โœ— cart_presentation depends on product_data (presentation must never depend on a data layer) - โ†’ Depend on product_domain instead and access data through its repository interface. -``` - -**Graceful skips (`exit 0`, no output):** -- target file is not a `pubspec.yaml` -- repo has no `features/` folder (not FFCA-shaped) -- workspace root cannot be located - -**Exit codes:** `0` pass/skip, `2` violation (blocks Claude). Reserve other non-zero codes for genuine script errors so the hook can distinguish a crash from a violation. - -### Test matrix (`scripts/test/validate_layers_test.dart`) - -Two fixture workspaces under `scripts/test/fixtures/`, pubspec.yaml files only (no Dart source). Each is a Dart workspace (root `pubspec.yaml` with `workspace:` listing members) so discovery works. - -`valid_workspace/` โ€” a minimal correct FFCA monorepo: -- `apps/mobile_app` depends on features + shared -- `features/product/{product_domain, product_data, product_presentation}` -- `features/cart/{cart_domain, cart_data, cart_presentation}` with `cart_domain โ†’ product_domain` (valid cross-feature domain dep) -- `features/auth/{auth_domain, auth_data_firebase}` (headless, backend suffix naming) -- `shared/ui_kit`, `shared/api_client` - -`invalid_workspace/` โ€” must plant **every** violation so each rule has a failing test: -1. Bad naming under `features/` (e.g., `features/orders/orders_service`) -2. Domain depending on data (`x_domain โ†’ x_data`) -3. Data depending on presentation (`x_data โ†’ x_presentation`) -4. Presentation depending on `*_data` (`cart_presentation โ†’ product_data`) โ€” the spec's canonical example -5. Shared depending on a feature (`shared/foo โ†’ some_domain`) -6. A dependency cycle (`a_domain โ†’ b_domain โ†’ a_domain`) -7. A package depending on an app (`x โ†’ mobile_app`) - -Test cases assert: -- Valid workspace passes in **both** incremental (`--file` on each package) and `--all` modes (exit 0, no violations). -- Each planted violation in the invalid workspace is caught with its specific message substring (rule text present, fix text present), exit code 2. -- Graceful-skip cases: non-pubspec path โ†’ exit 0; a workspace with no `features/` โ†’ exit 0. - -Tests invoke the script via `Process.run('dart', ['run', 'validate_layers.dart', ...])` (or call an exposed `run(args)` entrypoint directly for speed) and assert on exit code + stderr. - -### `hooks/validate_layers.sh` - -Mirror `analyze.sh`: -1. `set -euo pipefail`, read stdin payload. -2. `command -v jq` and `command -v dart`; if either missing, echo a skip note to stderr and `exit 0`. -3. `file_path=$(jq -r '.tool_input.file_path // empty')`; if empty or basename is not `pubspec.yaml`, `exit 0`. -4. FFCA-shape check: walk up from the file to find a `features/` dir; if none, `exit 0`. -5. `dart run ${CLAUDE_PLUGIN_ROOT}/scripts/validate_layers.dart --file "$file_path"`; propagate exit code (capture output, re-emit on failure, `exit 2`). - -### `hooks/hooks.json` - -Exactly the spec block: `PostToolUse` matcher `Edit|Write`, command `${CLAUDE_PLUGIN_ROOT}/hooks/validate_layers.sh`. Add a top-level `description` field (sibling convention) and a `timeout` (~30s) consistent with the sibling. - -### Skills - -Each `SKILL.md`: frontmatter (`name: vgv-ffca-`, `description`/`when_to_use` carrying the spec's exact trigger text, `allowed-tools`, `effort`), then workflow guidance only. Conventions are NEVER restated โ€” every convention reference is a pointer like: "Read `references/ffca_architecture.md`, section *Dependency Graph Rules*, before wiring pubspec dependencies." Each skill names the reference sections it depends on. - -- **ffca-architecture**: orientation skill. Points into Structure, Naming Conventions, Dependency Graph Rules, Layer Subfolder Conventions, anti-patterns. No code templates. -- **ffca-feature**: scaffold workflow (check for Swagger client โ†’ domain โ†’ data โ†’ presentation; headless variant). Points into Feature Layers sections AND `references/code_templates/` (domain, data, presentation). Delegates blocTest/mocktail detail to vgv-ai-flutter-plugin's testing skill. -- **ffca-routing**: callback injection, go_router_builder `GoRouteData`, `$extra` hydration, Actions/Intents alternative. Points into Routing & Navigation section AND `references/code_templates/presentation_templates.md`. -- **ffca-cross-feature**: cross-feature domain deps, Summary pattern, composing features, shared app-level Blocs. Points into Combining Different Features + FAQ sections. No code templates. -- **ffca-audit**: runs `dart run scripts/validate_layers.dart --all`, then the qualitative checks from the spec (classify packages, verify declared-vs-imported deps, barrel consistency, misplaced packages, high fan-in domains). Outputs a per-package verdict table + prioritized findings list. - -### `references/code_templates/` - -Extract the code examples already in `ffca_architecture.md` into ready-to-adapt template files (do not invent new code): -- `domain_templates.md`: model (manual `==`/`hashCode`/`toString`), `abstract interface class` repository (`IProductsRepository`), Summary pattern, Query/Command use cases. -- `data_templates.md`: data source + `dtos/`, extension mapper (`toDomain()`), repository implementation. -- `presentation_templates.md`: Cubit + sealed states, Module (Provider + BlocProvider wiring), `GoRouteData` route, Navigation class. - -### `.mcp.json` and `plugin.json` - -`.mcp.json`: exactly the spec's Very Good CLI server block. `plugin.json`: exactly the spec's block (name, version `0.1.0`, description, author). Optionally enrich author/keywords per sibling convention, but the spec's four fields are the floor. - -### `scripts/sync_reference.dart` - -Out of scope to implement. Stub it: a `main()` that prints a "not yet implemented" notice plus a comment block describing the Notion source page URL and the intended regeneration flow. - -## Acceptance Criteria - -- [ ] Plugin tree matches the spec's structure exactly (plus the justified `scripts/test/` + `scripts/pubspec.yaml` additions) -- [ ] `references/ffca_architecture.md` is byte-identical to the provided file (verify with `diff`) -- [ ] `validate_layers.dart` implements all seven checks with the isolated `rules` constant pointing at the reference section -- [ ] Incremental (`--file`) and `--all` modes both implemented; `--all` includes topological cycle detection -- [ ] Violation output includes both the rule and the fix, exits 2; graceful skips exit 0 -- [ ] `dart test` passes in `scripts/`; every validation rule has a failing-fixture test; valid workspace passes both modes -- [ ] `hooks/validate_layers.sh` parses payload with jq, filters to `pubspec.yaml`, skips gracefully when not FFCA-shaped or when `dart`/`jq` missing, propagates exit 2 -- [ ] `hooks/hooks.json` matches the spec block -- [ ] All five SKILL.md files use the spec's exact trigger descriptions, contain workflow guidance only, and point into the reference by section name (no restated conventions) -- [ ] `references/code_templates/` populated by extraction from the reference (domain, data, presentation) -- [ ] `.mcp.json` and `plugin.json` match the spec -- [ ] `sync_reference.dart` stubbed with TODO + Notion source comment -- [ ] README complete: overview, three-layer stack positioning table, installation (private repo), skills table, hook behavior table with prerequisites (Dart SDK, jq) -- [ ] No em dashes anywhere in authored prose (VGV style: use colons) -- [ ] End-to-end verification (step 8) performed in a live session against a scratch fixture: hook blocks the `cart_presentation โ†’ product_data` edit and Claude self-corrects; a valid edit passes silently; an FFCA question triggers the right skill; `/ffca-audit` flags planted violations -- [ ] Conventional commits; PR opened from `feat/implement-ffca-plugin` for review - -## Success Metrics - -- `dart test` green with one failing-fixture test per rule. -- In a live Claude Code session, the hook blocks an invalid pubspec edit with the exact spec violation message, and a valid edit passes with no output. -- An FFCA-shaped question triggers the correct skill, which answers from the reference rather than from restated conventions. - -## Dependencies & Risks - -- **Dart SDK + jq** required at runtime for the hook; both skip gracefully if absent. -- **Workspace-root discovery** is the trickiest logic: ambiguous when `features/` is nested or absent. Mitigation: explicit graceful-skip path + a fixture test for the no-`features/` case. -- **Incremental dependent resolution**: an edit to `x_domain` can break `x_data`/`x_presentation` that depend on it. Incremental mode must validate the edited package plus its direct dependents, not just the edited package. Covered by a dedicated test. -- **Skill trigger collisions** with `vgv-ai-flutter-plugin`: mitigated by the FFCA self-scoping language in every description (the `features/` + `{feature}_{layer}` signal). -- **Byte-identical reference**: copy with `cp`, never through an editor; verify with `diff`. -- **Out of scope (do not build):** Mason bricks/scaffolding commands, `sync_reference.dart` automation (stub only), marketplace registration, Arcana integration. - -## References & Research - -- Spec (source of truth): `vgv_ffca_plugin_spec.md` -- Conventions reference: `ffca_architecture.md` (sections: Structure, Naming Conventions, Feature Layers, Dependency Graph Rules, Layer Subfolder Conventions, Routing & Navigation, FAQ) -- Kickoff steps + Definition of Done: `vgv_ffca_kickoff_prompt.md` -- Structural reference plugin: `vgv-ai-flutter-plugin` (plugin cache) โ€” `hooks/scripts/analyze.sh` (hook wrapper pattern), `skills/layered-architecture/SKILL.md` (frontmatter format), `README.md` (layout), `.claude-plugin/plugin.json`, `.mcp.json` diff --git a/docs/source/vgv_ffca_kickoff_prompt.md b/docs/source/vgv_ffca_kickoff_prompt.md deleted file mode 100644 index 53e9e9f..0000000 --- a/docs/source/vgv_ffca_kickoff_prompt.md +++ /dev/null @@ -1,97 +0,0 @@ -# Kickoff: Implement vgv-ffca-plugin - -Paste this into Claude Code from an empty working directory, with `vgv_ffca_plugin_spec.md` and `ffca_architecture.md` placed alongside it. If Wingspan is installed, run `/plan` with this file first, then `/build` the resulting plan. - ---- - -## Goal - -Implement the **vgv-ffca-plugin** Claude Code plugin exactly as specified in `vgv_ffca_plugin_spec.md`. The plugin operationalizes Feature-First Clean Architecture (FFCA) for Flutter monorepos through five skills, a blocking pubspec validation hook, and a Very Good CLI MCP configuration. - -## Provided Files - -- `vgv_ffca_plugin_spec.md`: the full specification. It is the source of truth for structure, skill descriptions, hook behavior, and validation rules. Follow it; don't redesign it. -- `ffca_architecture.md`: the FFCA conventions reference, already generated from the canonical Notion page. Copy it verbatim to `references/ffca_architecture.md`. Do not rewrite or summarize it. - -## Steps - -### 1. Repo bootstrap - -```bash -gh repo create VGVentures/vgv-ffca-plugin --private --clone -cd vgv-ffca-plugin -``` - -### 2. Study the structural reference - -Clone the sibling plugin and mirror its conventions for plugin metadata, hook wiring, and shell wrapper style: - -```bash -git clone https://github.com/VeryGoodOpenSource/vgv-ai-flutter-plugin /tmp/reference-plugin -``` - -Specifically copy the patterns from: `.claude-plugin/plugin.json`, `hooks/hooks.json`, the analyze hook's shell script (jq payload parsing, graceful skip when prerequisites are missing, exit code propagation), and the SKILL.md frontmatter format. - -### 3. Scaffold the plugin structure - -Create the tree exactly as in the spec's Plugin Structure section: `.claude-plugin/`, `references/` (drop in the provided `ffca_architecture.md`), `references/code_templates/`, `skills/` (five skill folders), `hooks/`, `scripts/`, `.mcp.json`. - -### 4. Implement validate_layers.dart (test-first) - -This is the highest-risk component; build it before the skills. - -- Pure Dart, `dart:io` and `dart:core` only if possible; `package:yaml` is acceptable if a pubspec is added for the script. -- Two modes per the spec: incremental (default, edited package + direct dependents) and `--all` (full graph + workspace topological cycle check). -- Implement the checks table from the spec verbatim. Keep the rules in an isolated `rules` constant at the top of the file, with a comment naming the "Dependency Graph Rules" section of `references/ffca_architecture.md`. -- Violation output format per the spec: the rule AND the fix, exit 2. -- Graceful skips (exit 0): file is not a pubspec.yaml, repo has no `features/` folder, workspace root not found. - -**Fixture workspace for tests:** build `test/fixtures/valid_workspace/` and `test/fixtures/invalid_workspace/` containing minimal FFCA monorepos (pubspec.yaml files only, no Dart source needed). The invalid fixture must cover every rule: bad naming under `features/`, domain depending on data, data depending on presentation, presentation depending on `*_data`, shared depending on a feature, a dependency cycle, and a package depending on an app. Write `dart test` cases asserting each violation is caught with the right message and that the valid workspace passes both modes. - -### 5. Implement the hook - -- `hooks/hooks.json` per the spec. -- `hooks/validate_layers.sh`: jq payload parsing, pubspec.yaml filter, FFCA-shape check, graceful skip when `dart` or `jq` is missing, then `dart run` the script and propagate exit 2. - -### 6. Author the five skills - -Per the spec's Skills section: `ffca-architecture`, `ffca-feature`, `ffca-routing`, `ffca-cross-feature`, `ffca-audit`. Rules: - -- Use the exact trigger descriptions from the spec in each SKILL.md frontmatter. -- Skills contain workflow guidance only. Conventions are NEVER restated; point into `references/ffca_architecture.md` by section name (e.g., "Read references/ffca_architecture.md, section Dependency Graph Rules, before wiring pubspec dependencies"). -- Populate `references/code_templates/` (domain, data, presentation templates) by extracting the code examples from `ffca_architecture.md` into ready-to-adapt template files. Only `ffca-feature` and `ffca-routing` point to these. -- `ffca-audit` instructs running `dart run scripts/validate_layers.dart --all` plus the qualitative checks listed in the spec, producing the per-package verdict table. - -### 7. MCP config and README - -- `.mcp.json` per the spec (Very Good CLI server). -- README: overview, the three-layer stack positioning table, installation (private repo instructions for now), skills table, hook behavior table with prerequisites (Dart SDK, jq), modeled on the vgv-ai-flutter-plugin README. - -### 8. End-to-end verification (required, not optional) - -1. Install the plugin into a Claude Code session from the local path. -2. In a scratch FFCA fixture workspace, ask Claude to add `product_data` as a dependency of `cart_presentation`'s pubspec. **Verify the hook blocks with the expected violation message and Claude self-corrects.** -3. Make a valid pubspec edit and verify the hook passes silently. -4. Ask an FFCA-shaped question ("where should a CartBadge widget live?") and verify the right skill triggers and answers from the reference. -5. Run `/ffca-audit` (or trigger it by asking for an architecture health check) against the invalid fixture and verify the verdict table flags the planted violations. - -### 9. Ship - -Conventional commits, push to the private repo, open a PR from a feature branch for review. - -## Definition of Done - -- [ ] Repo exists at VGVentures/vgv-ffca-plugin (private) with the spec's exact structure -- [ ] `dart test` passes; every validation rule has a failing-fixture test -- [ ] Hook blocks invalid pubspec edits in a live Claude Code session (verified manually, step 8) -- [ ] All five skills trigger correctly and point into the reference rather than restating it -- [ ] `references/ffca_architecture.md` is byte-identical to the provided file -- [ ] README complete -- [ ] No em dashes anywhere in authored prose (VGV style: use colons) - -## Out of Scope (do not build) - -- Mason bricks or scaffolding commands (v2 brings SDK MCP tools instead) -- `scripts/sync_reference.dart` automation (stub it with a TODO and a comment describing the Notion source page; the provided reference file is current as of today) -- Marketplace registration (happens at v1.0 after transfer to VeryGoodOpenSource) -- Arcana integration diff --git a/docs/source/vgv_ffca_plugin_spec.md b/docs/source/vgv_ffca_plugin_spec.md deleted file mode 100644 index 8541df2..0000000 --- a/docs/source/vgv_ffca_plugin_spec.md +++ /dev/null @@ -1,287 +0,0 @@ -# vgv-ffca-plugin: Specification - -**Status:** Draft -**Author:** Rรฉmy (VGV) -**Distribution:** very_good_claude_marketplace - ---- - -## Overview - -A Claude Code plugin that operationalizes Feature-First Clean Architecture (FFCA) for Flutter monorepos. It is the third layer of VGV's AI-assisted engineering stack: - -| Layer | Plugin | Role | -|---|---|---| -| Workflow | vgv-wingspan | brainstorm โ†’ plan โ†’ build โ†’ review | -| **Structure** | **vgv-ffca-plugin** | Monorepo structure, layer rules, FFCA conventions | -| Code quality | vgv-ai-flutter-plugin | Bloc, testing, a11y, theming, analyze/format hooks | - -The plugin ships three asset types: **skills** that teach Claude the FFCA conventions, a **blocking validation hook** that enforces layer rules on every pubspec edit, and an **MCP configuration** that wires the Very Good CLI server. - -The plugin is the delivery vehicle for the approved architecture, available before the FFCA SDK exists. When the SDK ships, its MCP tools slot into the same plugin (v2). - ---- - -## Plugin Structure - -``` -vgv-ffca-plugin/ -โ”œโ”€โ”€ .claude-plugin/ -โ”‚ โ””โ”€โ”€ plugin.json -โ”œโ”€โ”€ references/ -โ”‚ โ”œโ”€โ”€ ffca_architecture.md # THE reference: full conventions, synced from the Notion page -โ”‚ โ””โ”€โ”€ code_templates/ -โ”‚ โ”œโ”€โ”€ domain_templates.md -โ”‚ โ”œโ”€โ”€ data_templates.md -โ”‚ โ””โ”€โ”€ presentation_templates.md -โ”œโ”€โ”€ skills/ -โ”‚ โ”œโ”€โ”€ ffca-architecture/ -โ”‚ โ”‚ โ””โ”€โ”€ SKILL.md -โ”‚ โ”œโ”€โ”€ ffca-feature/ -โ”‚ โ”‚ โ””โ”€โ”€ SKILL.md -โ”‚ โ”œโ”€โ”€ ffca-routing/ -โ”‚ โ”‚ โ””โ”€โ”€ SKILL.md -โ”‚ โ”œโ”€โ”€ ffca-cross-feature/ -โ”‚ โ”‚ โ””โ”€โ”€ SKILL.md -โ”‚ โ””โ”€โ”€ ffca-audit/ -โ”‚ โ””โ”€โ”€ SKILL.md -โ”œโ”€โ”€ hooks/ -โ”‚ โ”œโ”€โ”€ hooks.json -โ”‚ โ””โ”€โ”€ validate_layers.sh -โ”œโ”€โ”€ scripts/ -โ”‚ โ”œโ”€โ”€ validate_layers.dart -โ”‚ โ””โ”€โ”€ sync_reference.dart # regenerates references/ from the Notion page export -โ””โ”€โ”€ .mcp.json -``` - ---- - -## plugin.json - -```json -{ - "name": "vgv-ffca-plugin", - "version": "0.1.0", - "description": "Feature-First Clean Architecture (FFCA) for Flutter monorepos. Skills, validation hooks, and conventions for AI-first development, by Very Good Ventures.", - "author": "Very Good Ventures" -} -``` - ---- - -## Shared Reference - -`references/ffca_architecture.md` is the single FFCA reference inside the plugin: the full conventions document, generated from the [FFCA architecture Notion page](https://www.notion.so/verygoodventures/Feature-First-Clean-Architecture-2fb45eb3279580568023d1cf9bc00c24). All four skills point into it instead of carrying their own copy of the conventions. - -This follows the progressive-disclosure model that skills are built on, and the same depth-to-load-frequency principle as the CLAUDE.md hybrid approach: - -- **SKILL.md files stay lean:** trigger description, the workflow for that task, the non-negotiable rules for that context, and pointers into the reference ("Read `references/ffca_architecture.md`, section *Dependency Graph Rules*, before wiring pubspec dependencies"). -- **The reference carries the depth:** full naming tables, layer rules, folder conventions, decision trees, and rationale. Claude reads the relevant section on demand when a skill directs it there. -- **One sync target:** when the Notion page changes, only `references/ffca_architecture.md` regenerates (via `scripts/sync_reference.dart` from a Notion export). The skill files only change when a *workflow* changes, not when conventions are reworded. - -`references/code_templates/` holds the canonical code examples per layer (model, repository, mapper, Cubit, Module, GoRouteData). Only `ffca-feature` and `ffca-routing` point to these. - ---- - -## Skills - -Each skill self-scopes to FFCA repos through its description, so the plugin coexists with vgv-ai-flutter-plugin without triggering conflicts. The detection signal: a `features/` folder containing `{feature}_domain`, `{feature}_data`, or `{feature}_presentation` packages. - -Skills contain workflow guidance only; conventions live in the shared reference. Each SKILL.md names the reference sections it depends on, so drift is traceable when the architecture evolves. - -### Skill 1: ffca-architecture - -**Description (trigger):** "Use when working in an FFCA monorepo (a features/ folder containing {feature}_domain, {feature}_data, or {feature}_presentation packages), or when the user asks about Feature-First Clean Architecture, monorepo structure, where code should live, layer dependencies, or package organization." - -**Content:** -- The three top-level folders: apps/, features/, shared/ -- Feature types: full feature, headless feature, shared package -- The decision rule: business capability โ†’ features/, pub-publishable generic โ†’ shared/ -- Naming conventions table (enforced) -- Dependency graph rules (the six rules from the architecture page) -- Layer subfolder conventions (models/, repositories/, use_cases/, data_sources/, dtos/, mappers/, bloc/, views/) -- Anti-patterns: presentation importing data, shared depending on features, business logic in shared/ - -### Skill 2: ffca-feature - -**Description (trigger):** "Use when creating a new feature, headless feature, screen, or adding a layer to an existing feature in an FFCA monorepo. Covers the three-package scaffold, domain models, repositories, use cases, DTOs, mappers, Cubits, and Modules." - -**Content:** -- Workflow: check for a pre-generated API client (Swagger) first, then domain โ†’ data โ†’ presentation -- Domain: model with manual `==`/`hashCode`/`toString`, `abstract interface class` repositories, CQS use cases (Query/Command) only when combining repositories -- Data: data sources with dtos/ subfolders, extension mappers, repository implementations -- Presentation: Cubit + sealed states (Initial/Loading/Loaded/Error), screen with switch-on-state, Module wiring Providers and callbacks -- Headless feature: domain + data only, how to grow into a full feature -- Pubspec templates per layer with correct path dependencies -- Barrel files: primary + subfeature barrels -- Test scaffolding per layer (delegates to vgv-ai-flutter-plugin's testing skill for blocTest/mocktail details) - -### Skill 3: ffca-routing - -**Description (trigger):** "Use when adding screens, routes, navigation, deep links, or navigation callbacks in an FFCA monorepo." - -**Content:** -- Callback injection: Module exposes typed callbacks, app layer wires them -- go_router_builder: `@TypedGoRoute` + `GoRouteData` classes in the app layer -- The `$extra` hydration pattern: screens rebuild from URL params alone, `$extra` is an optional optimization -- The Actions/Intent alternative for deep widget trees -- Constraints: no string-based paths, features never import the app router or another feature's routes - -### Skill 4: ffca-cross-feature - -**Description (trigger):** "Use when one feature needs data or functionality from another feature, when sharing models across features, or when deciding between a use case and a new composing feature." - -**Content:** -- Cross-feature domain dependencies: cart_domain โ†’ product_domain -- The Summary pattern: loose coupling through IDs -- Use cases in the consuming feature's domain -- Composing features for complex multi-domain logic (checkout depends on cart + product) -- Shared Blocs at app level; features communicate by dispatching events, never by knowing each other -- Reusable widgets with their own Cubit live in the owning feature's presentation package - -### Skill 5: ffca-audit - -**Description (trigger):** "Use when auditing an FFCA monorepo for architecture compliance, reviewing the full dependency graph, assessing FFCA adoption in an existing project, or when the user asks for an architecture health check." - -**Content:** -- Runs `dart run scripts/validate_layers.dart --all` for the full-graph mechanical checks (naming, layer rules, cycles) -- Goes beyond the script with qualitative review against `references/ffca_architecture.md`: - - Enumerate all packages and classify each by folder, naming, and inferred type (feature, headless feature, shared) - - Classify every presentation package's path dependencies by layer and confirm actual usage via import analysis (a declared dependency that's never imported is also a finding) - - Check barrel file consistency: primary barrels exist, subfeature barrels where expected, no missing exports - - Flag misplaced packages (business logic in shared/, generic utilities in features/) - - Flag high fan-in domains that may be doing too much -- Output: a per-package verdict table plus a prioritized findings list, suitable for a `CODE_ASSESSMENT`-style report - -The hook keeps individual edits compliant; the audit skill answers "is this whole repo healthy", on demand and in CI-adjacent reviews. - ---- - -## Hooks - -### hooks.json - -```json -{ - "hooks": { - "PostToolUse": [ - { - "matcher": "Edit|Write", - "hooks": [ - { - "type": "command", - "command": "${CLAUDE_PLUGIN_ROOT}/hooks/validate_layers.sh" - } - ] - } - ] - } -} -``` - -### validate_layers.sh - -Thin shell wrapper, mirroring the analyze hook in vgv-ai-flutter-plugin: - -1. Parse the hook payload from stdin with `jq`, extract `file_path` -2. Exit 0 silently unless the file is a `pubspec.yaml` -3. Exit 0 silently if the repo is not FFCA-shaped (no `features/` folder) or if `dart`/`jq` is unavailable (graceful skip) -4. Run `dart run ${CLAUDE_PLUGIN_ROOT}/scripts/validate_layers.dart --file ` -5. Propagate the exit code: 0 passes, 2 blocks Claude until the violation is fixed - -### validate_layers.dart - -Two modes: - -- **Incremental (hook, default):** validates the edited package plus its direct dependents. Fast on any workspace size; an edit can only break its own rules or the packages that depend on it. -- **Full graph (`--all`):** validates every package and runs the workspace-wide cycle check. Used by CI and the `ffca-audit` skill. - -Checks per package: - -| Check | Rule | -|---|---| -| Naming | A package under `features/{f}/` must be named `{f}_domain`, `{f}_data`, `{f}_data_{backend}`, or `{f}_presentation` | -| Domain deps | Path dependencies on other `*_domain` packages and `shared/` Dart packages only | -| Data deps | Own `{f}_domain`, `shared/` packages. Never any `*_presentation`, never another feature's `*_data` | -| Presentation deps | Own `{f}_domain`, other `*_domain` packages, other `*_presentation` packages, `shared/`. Never any `*_data` | -| Shared deps | External pub packages and other `shared/` packages only. Never `features/` | -| Apps | May depend on anything. Nothing depends on an app | -| Cycles | Incremental mode: cycles reachable from the edited package. `--all` mode: topological sort of the full workspace graph | - -Output on failure (exit 2, stderr): - -``` -FFCA violation in features/cart/cart_presentation/pubspec.yaml: - โœ— cart_presentation depends on product_data (presentation must never depend on a data layer) - โ†’ Depend on product_domain instead and access data through its repository interface. -``` - -Each violation includes the rule and the fix, so Claude self-corrects in the same turn. - -Rules live in a `rules` constant at the top of the script, isolated so the pending architecture decisions (cross-feature dependency scope) change one block, not the whole script. The same script runs in CI: `dart run scripts/validate_layers.dart --all`. - ---- - -## MCP Configuration - -`.mcp.json` reuses the Very Good CLI MCP server, identical to vgv-ai-flutter-plugin: - -```json -{ - "mcpServers": { - "very_good_cli": { - "command": "very_good", - "args": ["mcp"] - } - } -} -``` - -This gives Claude `create`, `tests`, `packages_get`, and `packages_check_licenses` today. FFCA SDK tools (`create_feature`, `validate_graph`, `add_model`, and the rest of the catalog) are added here in v2 once the SDK ships. - ---- - -## Distribution - -Two stages, gated on the architecture's approval status: - -**Stage 1 (now): private repo in VGVentures.** - -```bash -gh repo create VGVentures/vgv-ffca-plugin --private -``` - -The plugin's `references/ffca_architecture.md` is the full architecture doc, which isn't approved or published on VGE yet, so the repo starts private. Claude Code marketplaces work with private repos for anyone with git access via `gh auth`, which covers the platform team pilot. For the very first local iteration, no repo is needed at all: build the plugin in a folder and install it from a local marketplace path to test the hook. - -**Stage 2 (at v1.0): transfer to VeryGoodOpenSource and register in the marketplace.** - -Once the open discussions are resolved and the architecture is public-ready, transfer the repo and open one PR to `very_good_claude_marketplace` adding the plugin entry. From then on: - -```bash -claude plugin install vgv-ffca-plugin@very_good_claude_marketplace -``` - -Standalone install, no Arcana dependency. Arcana integration (auto-enable via its settings.json template) can come later as a one-line change on the Arcana side. - ---- - -## Versioning Roadmap - -| Version | Contents | Gate | -|---|---|---| -| 0.1.0 | Skills (including audit) + validation hook + Very Good CLI MCP | None: ship now, iterate as the architecture evolves | -| 0.x | Iterate on skill content and hook rules from pilot project feedback | Pilot project | -| 1.0.0 | Stable conventions, resolved open discussions (Component+Builder, widget-tree composition) baked into skills and rules | Open discussions resolved with Brian | -| 2.0.0 | FFCA SDK MCP tools replace skill-guided generation with deterministic tool calls | SDK Phase 1 ships | - -Generation stays skill-guided until v2: a Mason command layer in between would be throwaway work once the SDK's deterministic tools arrive. - ---- - -## Drift Prevention - -The architecture Notion page is the single source of truth; `references/ffca_architecture.md` is its in-plugin mirror. Three mechanisms keep the plugin honest: - -1. `scripts/sync_reference.dart` regenerates `references/ffca_architecture.md` from the Notion page export. A CI check (or scheduled workflow) flags when the plugin's copy is stale. -2. Skills never restate conventions; they point into the reference by section name. A reworded convention requires zero skill edits. -3. The validation rules constant in `validate_layers.dart` names the "Dependency Graph Rules" section it implements, so a rule change on the page maps to one code location. From c501463b3e710c5241704c0fa66e189150a7e65a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Baudet?= Date: Sat, 19 Sep 2026 21:19:19 -0600 Subject: [PATCH 2/3] docs: use current marketplace repo slug in README link The install command already pointed at very-good-claude-code-marketplace while the link above it used the pre-rename very_good_claude_marketplace. The old name redirects, so both resolved, but they disagreed in the same paragraph. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01PRHkiEhvrUnK2P69o42vpX --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 5d0c18c..817e777 100644 --- a/README.md +++ b/README.md @@ -37,7 +37,7 @@ The `ffca-architecture` skill defers to `layered-architecture` when it sees the ## Installation -The plugin is published in the [Very Good Claude Marketplace](https://github.com/VeryGoodOpenSource/very_good_claude_marketplace). Inside Claude: +The plugin is published in the [Very Good Claude Marketplace](https://github.com/VeryGoodOpenSource/very-good-claude-code-marketplace). Inside Claude: ```bash /plugin marketplace add VeryGoodOpenSource/very-good-claude-code-marketplace From a1938f6e3392d50f8a1dc434303a5bdd8dd7fee8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Baudet?= Date: Tue, 22 Sep 2026 11:50:19 -0500 Subject: [PATCH 3/3] chore: address review feedback on public release prep Remove .claude-plugin/marketplace.json. Neither vgv-wingspan nor vgv-ai-flutter-plugin ships one, and the plugin is registered in the shared marketplace. Drops its two release-please extra-files entries and the README local-checkout install block, which needed the file. Add the skills-lint job from very_good_workflows, matching both sibling plugins. All five SKILL.md descriptions contained an unquoted colon and so were invalid YAML, which the stricter linter rejects even though `claude plugin validate` accepts them. Quote all five. Use tools@verygood.ventures and bump markdownlint-cli2-action to v24.2.0 and cspell-action to v9, all to match the sibling plugins. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01PRHkiEhvrUnK2P69o42vpX --- .claude-plugin/marketplace.json | 19 ------------------- .claude-plugin/plugin.json | 2 +- .github/workflows/ci.yaml | 10 ++++++++-- .release-please-config.json | 10 ---------- README.md | 6 ------ skills/ffca-architecture/SKILL.md | 2 +- skills/ffca-audit/SKILL.md | 2 +- skills/ffca-cross-feature/SKILL.md | 2 +- skills/ffca-feature/SKILL.md | 2 +- skills/ffca-routing/SKILL.md | 2 +- 10 files changed, 14 insertions(+), 43 deletions(-) delete mode 100644 .claude-plugin/marketplace.json diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json deleted file mode 100644 index 59225f2..0000000 --- a/.claude-plugin/marketplace.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "name": "vgv-ffca-plugin", - "owner": { - "name": "Very Good Ventures", - "url": "https://verygood.ventures" - }, - "metadata": { - "description": "Self-hosted marketplace for the VGV FFCA plugin, for local development and direct installs.", - "version": "0.1.0" - }, - "plugins": [ - { - "name": "vgv-ffca-plugin", - "source": "./", - "version": "0.1.0", - "description": "Feature-First Clean Architecture (FFCA) for Flutter monorepos. Skills, validation hooks, and conventions for AI-first development, by Very Good Ventures." - } - ] -} diff --git a/.claude-plugin/plugin.json b/.claude-plugin/plugin.json index 91bca41..000da1a 100644 --- a/.claude-plugin/plugin.json +++ b/.claude-plugin/plugin.json @@ -5,7 +5,7 @@ "author": { "name": "Very Good Ventures", "url": "https://verygood.ventures", - "email": "hello@verygood.ventures" + "email": "tools@verygood.ventures" }, "homepage": "https://github.com/VeryGoodOpenSource/vgv-ffca-plugin", "repository": "https://github.com/VeryGoodOpenSource/vgv-ffca-plugin", diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 0e1da5b..7d6fa3b 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -12,7 +12,7 @@ jobs: steps: - uses: actions/checkout@v7 - name: Lint Markdown - uses: DavidAnson/markdownlint-cli2-action@v24.1.0 + uses: DavidAnson/markdownlint-cli2-action@v24.2.0 with: globs: | **/*.md @@ -26,7 +26,7 @@ jobs: steps: - uses: actions/checkout@v7 - name: Spell Check - uses: streetsidesoftware/cspell-action@v8 + uses: streetsidesoftware/cspell-action@v9 with: files: | **/*.md @@ -51,6 +51,12 @@ jobs: - name: Test run: dart test + skills-lint: + name: ๐Ÿ” Skills Lint + uses: VeryGoodOpenSource/very_good_workflows/.github/workflows/skills_lint.yml@v1.21.1 + with: + skills_directories: 'skills' + plugin-validate: name: ๐Ÿ“ฆ Plugin Validation runs-on: ubuntu-latest diff --git a/.release-please-config.json b/.release-please-config.json index cd4337d..c585d59 100644 --- a/.release-please-config.json +++ b/.release-please-config.json @@ -22,16 +22,6 @@ "type": "json", "path": ".claude-plugin/plugin.json", "jsonpath": "$.version" - }, - { - "type": "json", - "path": ".claude-plugin/marketplace.json", - "jsonpath": "$.metadata.version" - }, - { - "type": "json", - "path": ".claude-plugin/marketplace.json", - "jsonpath": "$.plugins[0].version" } ] } diff --git a/README.md b/README.md index 817e777..1e33db8 100644 --- a/README.md +++ b/README.md @@ -44,12 +44,6 @@ The plugin is published in the [Very Good Claude Marketplace](https://github.com /plugin install vgv-ffca-plugin ``` -For local iteration, install from a checkout path instead: - -```bash -claude plugin marketplace add /path/to/vgv-ffca-plugin && claude plugin install vgv-ffca-plugin -``` - ## Skills | Skill | Description | diff --git a/skills/ffca-architecture/SKILL.md b/skills/ffca-architecture/SKILL.md index ce673b9..fe1e4d9 100644 --- a/skills/ffca-architecture/SKILL.md +++ b/skills/ffca-architecture/SKILL.md @@ -1,6 +1,6 @@ --- name: ffca-architecture -description: Feature-First Clean Architecture orientation for Flutter monorepos: where code lives, layer boundaries, naming, and package organization. +description: "Feature-First Clean Architecture orientation for Flutter monorepos: where code lives, layer boundaries, naming, and package organization." when_to_use: Use when working in an FFCA monorepo (a features/ folder containing {feature}_domain, {feature}_data, or {feature}_presentation packages), or when the user asks about Feature-First Clean Architecture, monorepo structure, where code should live, layer dependencies, or package organization. allowed-tools: Read Glob Grep effort: high diff --git a/skills/ffca-audit/SKILL.md b/skills/ffca-audit/SKILL.md index 6a87ed2..145647d 100644 --- a/skills/ffca-audit/SKILL.md +++ b/skills/ffca-audit/SKILL.md @@ -1,6 +1,6 @@ --- name: ffca-audit -description: Audit an FFCA monorepo for architecture compliance: the mechanical layer/naming/cycle checks plus a qualitative review, producing a per-package verdict table. +description: "Audit an FFCA monorepo for architecture compliance: the mechanical layer/naming/cycle checks plus a qualitative review, producing a per-package verdict table." when_to_use: Use when auditing an FFCA monorepo for architecture compliance, reviewing the full dependency graph, assessing FFCA adoption in an existing project, or when the user asks for an architecture health check. allowed-tools: Task Read Glob Grep Bash effort: high diff --git a/skills/ffca-cross-feature/SKILL.md b/skills/ffca-cross-feature/SKILL.md index 560eeb0..454d19c 100644 --- a/skills/ffca-cross-feature/SKILL.md +++ b/skills/ffca-cross-feature/SKILL.md @@ -1,6 +1,6 @@ --- name: ffca-cross-feature -description: Cross-feature dependencies in FFCA: the Summary pattern, use cases that combine repositories, composing features, and feature-to-feature communication. +description: "Cross-feature dependencies in FFCA: the Summary pattern, use cases that combine repositories, composing features, and feature-to-feature communication." when_to_use: Use when one feature needs data or functionality from another feature, when sharing models across features, or when deciding between a use case and a new composing feature. allowed-tools: Read Glob Grep effort: high diff --git a/skills/ffca-feature/SKILL.md b/skills/ffca-feature/SKILL.md index 8bd0037..b1ab24b 100644 --- a/skills/ffca-feature/SKILL.md +++ b/skills/ffca-feature/SKILL.md @@ -1,6 +1,6 @@ --- name: ffca-feature -description: Scaffold and extend FFCA features: the three-package domain/data/presentation structure, models, repositories, use cases, DTOs, mappers, Cubits, and Modules. +description: "Scaffold and extend FFCA features: the three-package domain/data/presentation structure, models, repositories, use cases, DTOs, mappers, Cubits, and Modules." when_to_use: Use when creating a new feature, headless feature, screen, or adding a layer to an existing feature in an FFCA monorepo. Covers the three-package scaffold, domain models, repositories, use cases, DTOs, mappers, Cubits, and Modules. allowed-tools: Read Glob Grep Write Edit mcp__very_good_cli__create mcp__very_good_cli__packages_get effort: high diff --git a/skills/ffca-routing/SKILL.md b/skills/ffca-routing/SKILL.md index 12d022f..97e6a90 100644 --- a/skills/ffca-routing/SKILL.md +++ b/skills/ffca-routing/SKILL.md @@ -1,6 +1,6 @@ --- name: ffca-routing -description: Routing and navigation for FFCA monorepos: callback injection, go_router_builder typed routes, the $extra hydration pattern, and feature isolation. +description: "Routing and navigation for FFCA monorepos: callback injection, go_router_builder typed routes, the $extra hydration pattern, and feature isolation." when_to_use: Use when adding screens, routes, navigation, deep links, or navigation callbacks in an FFCA monorepo. allowed-tools: Read Glob Grep Write Edit effort: high