From 2788e26242e0d27c55a4c3c9777402c52323a030 Mon Sep 17 00:00:00 2001 From: Dominik Simonik Date: Wed, 21 Oct 2026 14:01:51 +0200 Subject: [PATCH 1/6] chore: adopt Very Good CLI release and repo conventions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit release-please now owns versions and changelogs for both packages, and the release workflow regenerates the build_version output on the release branch so verify-version does not fail on the release PR. Also adds CODEOWNERS and a lychee link check, fixes the LICENSE copyright holder in both packages, gives each a repository and issue tracker, and renames ".github/ISSUE_TEMPLATE/ config.yml" — the leading space meant GitHub never read it, so blank_issues_enabled had no effect. --- .github/CODEOWNERS | 3 + .../{ config.yml => config.yml} | 0 .github/cspell.json | 1 + .github/workflows/check_links.yaml | 30 +++++++++ .github/workflows/release_please.yaml | 61 +++++++++++++++++++ .gitignore | 4 ++ .lycheeignore | 22 +++++++ .release-please-config.json | 36 +++++++++++ .release-please-manifest.json | 4 ++ packages/plugin_source/LICENSE | 2 +- packages/plugin_source/pubspec.yaml | 2 + packages/vgv_ai_cli/LICENSE | 2 +- packages/vgv_ai_cli/example/README.md | 3 + packages/vgv_ai_cli/pubspec.yaml | 3 + 14 files changed, 171 insertions(+), 2 deletions(-) create mode 100644 .github/CODEOWNERS rename .github/ISSUE_TEMPLATE/{ config.yml => config.yml} (100%) create mode 100644 .github/workflows/check_links.yaml create mode 100644 .github/workflows/release_please.yaml create mode 100644 .lycheeignore create mode 100644 .release-please-config.json create mode 100644 .release-please-manifest.json create mode 100644 packages/vgv_ai_cli/example/README.md diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 00000000..e9909896 --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1,3 @@ +# Every request must be reviewed and accepted by: + +* @VeryGoodOpenSource/codeowners diff --git a/.github/ISSUE_TEMPLATE/ config.yml b/.github/ISSUE_TEMPLATE/config.yml similarity index 100% rename from .github/ISSUE_TEMPLATE/ config.yml rename to .github/ISSUE_TEMPLATE/config.yml diff --git a/.github/cspell.json b/.github/cspell.json index 507a9e06..fc3dbc52 100644 --- a/.github/cspell.json +++ b/.github/cspell.json @@ -25,6 +25,7 @@ "frontmatter", "gemini", "kevmoo", + "lycheeignore", "mcp", "opencode", "prereqs", diff --git a/.github/workflows/check_links.yaml b/.github/workflows/check_links.yaml new file mode 100644 index 00000000..90ce4ab6 --- /dev/null +++ b/.github/workflows/check_links.yaml @@ -0,0 +1,30 @@ +name: check_links + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +on: + push: + branches: + - main + pull_request: + branches: + - main + schedule: + # Runs every Monday at 08:00 UTC + - cron: "0 8 * * 1" + +jobs: + check_links: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v7 + + - name: šŸ”— Link Checker + uses: lycheeverse/lychee-action@v2 + with: + # The repository is private, so GitHub links need a token to resolve. + token: ${{ secrets.GITHUB_TOKEN }} + args: ./**/*.md ./**/*.dart + fail: true diff --git a/.github/workflows/release_please.yaml b/.github/workflows/release_please.yaml new file mode 100644 index 00000000..a7e22117 --- /dev/null +++ b/.github/workflows/release_please.yaml @@ -0,0 +1,61 @@ +name: release_please + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +on: + workflow_dispatch: + push: + branches: + - main + +jobs: + release_please: + runs-on: ubuntu-latest + + steps: + - name: šŸš€ Release Please + id: release + uses: googleapis/release-please-action@v5 + with: + token: ${{ secrets.RELEASE_PLEASE_TOKEN }} + manifest-file: ".release-please-manifest.json" + config-file: ".release-please-config.json" + + # `packages/vgv_ai_cli/lib/src/version.dart` is generated from the + # package version by `build_version`, so the bump release-please writes + # leaves it stale and `verify-version` fails on the release PR. + # Regenerate it on the release branch. + - name: šŸ“š Git Checkout + if: steps.release.outputs.prs_created == 'true' + uses: actions/checkout@v7 + with: + ref: ${{ fromJSON(steps.release.outputs.pr).headBranchName }} + token: ${{ secrets.RELEASE_PLEASE_TOKEN }} + + - name: šŸŽÆ Setup Dart + if: steps.release.outputs.prs_created == 'true' + uses: dart-lang/setup-dart@v1.8.1 + with: + sdk: "3.13.0" + + - name: šŸ”„ Regenerate version file + if: steps.release.outputs.prs_created == 'true' + working-directory: packages/vgv_ai_cli + run: | + dart pub get + dart run build_runner build + + - name: šŸ“¤ Push version file + if: steps.release.outputs.prs_created == 'true' + run: | + if [ -z "$(git status --porcelain packages/vgv_ai_cli/lib/src/version.dart)" ]; then + echo "version.dart is already in sync" + exit 0 + fi + git config user.name "github-actions[bot]" + git config user.email "41898282+github-actions[bot]@users.noreply.github.com" + git add packages/vgv_ai_cli/lib/src/version.dart + git commit -m "chore: regenerate version file" + git push diff --git a/.gitignore b/.gitignore index 120d6c29..df2bf651 100644 --- a/.gitignore +++ b/.gitignore @@ -28,3 +28,7 @@ coverage/ docs/ tasks/ + +# Mason +.mason/ +mason-lock.json diff --git a/.lycheeignore b/.lycheeignore new file mode 100644 index 00000000..c0b742f1 --- /dev/null +++ b/.lycheeignore @@ -0,0 +1,22 @@ +# Lychee ignore patterns +# See https://github.com/lycheeverse/lychee for documentation + +# Dart string interpolation in source, picked up as literal link text. +# Lychee matches these patterns against the percent-encoded URL, so `${` arrives as `$%7B`. +\$%7B + +# Placeholder hosts used in tests and doc examples +^https://docs/$ +^https://docs\.example +^https://example\.com +^https://open\.example +^https://x/$ +^https://x\.example +^https://mcp\.example\.com +^https://github\.com/acme/ + +# Private sibling repositories the workflow token cannot read +^https://github\.com/VeryGoodOpenSource/vgv-wingspan + +# MCP endpoints answer 405 to the GET lychee sends +^https://mcp\.context7\.com diff --git a/.release-please-config.json b/.release-please-config.json new file mode 100644 index 00000000..ccb45c86 --- /dev/null +++ b/.release-please-config.json @@ -0,0 +1,36 @@ +{ + "$schema": "https://raw.githubusercontent.com/googleapis/release-please/main/schemas/config.json", + "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", + "group-pull-request-title-pattern": "chore: release ${branch}", + "include-component-in-tag": true, + "packages": { + "packages/vgv_ai_cli": { + "release-type": "dart", + "component": "vgv_ai_cli", + "changelog-path": "CHANGELOG.md", + "version-file": "pubspec.yaml" + }, + "packages/plugin_source": { + "release-type": "dart", + "component": "plugin_source", + "changelog-path": "CHANGELOG.md", + "version-file": "pubspec.yaml" + } + }, + "exclude-paths": [ + ".github", + ".release-please-config.json", + ".release-please-manifest.json", + "AGENTS.md", + "CONTRIBUTING.md", + "README.md", + "tool" + ] +} diff --git a/.release-please-manifest.json b/.release-please-manifest.json new file mode 100644 index 00000000..a768163b --- /dev/null +++ b/.release-please-manifest.json @@ -0,0 +1,4 @@ +{ + "packages/vgv_ai_cli": "0.1.0", + "packages/plugin_source": "0.1.0" +} diff --git a/packages/plugin_source/LICENSE b/packages/plugin_source/LICENSE index 2c1c5f17..650d32a0 100644 --- a/packages/plugin_source/LICENSE +++ b/packages/plugin_source/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2026 +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 diff --git a/packages/plugin_source/pubspec.yaml b/packages/plugin_source/pubspec.yaml index 78428b37..beaacb55 100644 --- a/packages/plugin_source/pubspec.yaml +++ b/packages/plugin_source/pubspec.yaml @@ -3,6 +3,8 @@ description: >- Resolves VGV Claude Code plugins to a directory on disk and parses them into a harness-neutral asset model. version: 0.1.0 +repository: https://github.com/VeryGoodOpenSource/vgv_ai_cli +issue_tracker: https://github.com/VeryGoodOpenSource/vgv_ai_cli/issues publish_to: none resolution: workspace environment: diff --git a/packages/vgv_ai_cli/LICENSE b/packages/vgv_ai_cli/LICENSE index 2c1c5f17..650d32a0 100644 --- a/packages/vgv_ai_cli/LICENSE +++ b/packages/vgv_ai_cli/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2026 +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 diff --git a/packages/vgv_ai_cli/example/README.md b/packages/vgv_ai_cli/example/README.md new file mode 100644 index 00000000..10207b8d --- /dev/null +++ b/packages/vgv_ai_cli/example/README.md @@ -0,0 +1,3 @@ +# Example + +`vgv_ai` is used from the terminal. See [../README.md](../README.md) for usage. diff --git a/packages/vgv_ai_cli/pubspec.yaml b/packages/vgv_ai_cli/pubspec.yaml index c60d0720..e1109fc9 100644 --- a/packages/vgv_ai_cli/pubspec.yaml +++ b/packages/vgv_ai_cli/pubspec.yaml @@ -1,6 +1,9 @@ name: vgv_ai_cli description: A CLI that configures Very Good AI coding agents and tooling version: 0.1.0 +repository: https://github.com/VeryGoodOpenSource/vgv_ai_cli +issue_tracker: https://github.com/VeryGoodOpenSource/vgv_ai_cli/issues +topics: [cli, ai, agents, tooling] # Not published. `plugin_source`, which this depends on, is `publish_to: none`, # and the CLI is installed from source rather than pub.dev. publish_to: none From 7e5a172cbd1a0441edff636dc95d60e6c9611c24 Mon Sep 17 00:00:00 2001 From: Dominik Simonik Date: Wed, 21 Oct 2026 15:54:27 +0200 Subject: [PATCH 2/6] chore: correct the release-please setup from review - `bootstrap-sha` pins where changelog collection starts. The repo has no tags, so without it the first release PR would replay every commit the hand-written 0.1.0 entries already describe. - `linked-versions` groups the two packages, so a fix in plugin_source bumps the CLI the user actually runs instead of only itself. - The root `exclude-paths` filtered nothing: release-please only attributes commits that touch a package path, and every entry was outside both. - `permissions: contents: read`, since the PAT does all the writing. - The link check reads markdown only. Scanning Dart needed ten ignore patterns for test fixtures; two remain, and a new fixture URL can no longer break the weekly run. - Dropped `topics` and `example/README.md`, which only affect pub.dev. --- .github/workflows/check_links.yaml | 2 +- .github/workflows/release_please.yaml | 3 +++ .lycheeignore | 18 ++---------------- .release-please-config.json | 15 +++++++-------- packages/vgv_ai_cli/example/README.md | 3 --- packages/vgv_ai_cli/pubspec.yaml | 1 - 6 files changed, 13 insertions(+), 29 deletions(-) delete mode 100644 packages/vgv_ai_cli/example/README.md diff --git a/.github/workflows/check_links.yaml b/.github/workflows/check_links.yaml index 90ce4ab6..9e0b956b 100644 --- a/.github/workflows/check_links.yaml +++ b/.github/workflows/check_links.yaml @@ -26,5 +26,5 @@ jobs: with: # The repository is private, so GitHub links need a token to resolve. token: ${{ secrets.GITHUB_TOKEN }} - args: ./**/*.md ./**/*.dart + args: ./**/*.md fail: true diff --git a/.github/workflows/release_please.yaml b/.github/workflows/release_please.yaml index a7e22117..bdea5f2c 100644 --- a/.github/workflows/release_please.yaml +++ b/.github/workflows/release_please.yaml @@ -10,6 +10,9 @@ on: branches: - main +permissions: + contents: read + jobs: release_please: runs-on: ubuntu-latest diff --git a/.lycheeignore b/.lycheeignore index c0b742f1..36eb3f2b 100644 --- a/.lycheeignore +++ b/.lycheeignore @@ -1,22 +1,8 @@ # Lychee ignore patterns # See https://github.com/lycheeverse/lychee for documentation -# Dart string interpolation in source, picked up as literal link text. -# Lychee matches these patterns against the percent-encoded URL, so `${` arrives as `$%7B`. -\$%7B - -# Placeholder hosts used in tests and doc examples -^https://docs/$ -^https://docs\.example -^https://example\.com -^https://open\.example -^https://x/$ -^https://x\.example -^https://mcp\.example\.com -^https://github\.com/acme/ +# Dart string interpolation quoted in docs, picked up as literal link text +\$\{ # Private sibling repositories the workflow token cannot read ^https://github\.com/VeryGoodOpenSource/vgv-wingspan - -# MCP endpoints answer 405 to the GET lychee sends -^https://mcp\.context7\.com diff --git a/.release-please-config.json b/.release-please-config.json index ccb45c86..d4870d74 100644 --- a/.release-please-config.json +++ b/.release-please-config.json @@ -10,6 +10,7 @@ "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", "group-pull-request-title-pattern": "chore: release ${branch}", "include-component-in-tag": true, + "bootstrap-sha": "875842bc783d6bd1592f6e5204d9735709df3a93", "packages": { "packages/vgv_ai_cli": { "release-type": "dart", @@ -24,13 +25,11 @@ "version-file": "pubspec.yaml" } }, - "exclude-paths": [ - ".github", - ".release-please-config.json", - ".release-please-manifest.json", - "AGENTS.md", - "CONTRIBUTING.md", - "README.md", - "tool" + "plugins": [ + { + "type": "linked-versions", + "groupName": "vgv_ai", + "components": ["vgv_ai_cli", "plugin_source"] + } ] } diff --git a/packages/vgv_ai_cli/example/README.md b/packages/vgv_ai_cli/example/README.md deleted file mode 100644 index 10207b8d..00000000 --- a/packages/vgv_ai_cli/example/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# Example - -`vgv_ai` is used from the terminal. See [../README.md](../README.md) for usage. diff --git a/packages/vgv_ai_cli/pubspec.yaml b/packages/vgv_ai_cli/pubspec.yaml index e1109fc9..4c3a7c7d 100644 --- a/packages/vgv_ai_cli/pubspec.yaml +++ b/packages/vgv_ai_cli/pubspec.yaml @@ -3,7 +3,6 @@ description: A CLI that configures Very Good AI coding agents and tooling version: 0.1.0 repository: https://github.com/VeryGoodOpenSource/vgv_ai_cli issue_tracker: https://github.com/VeryGoodOpenSource/vgv_ai_cli/issues -topics: [cli, ai, agents, tooling] # Not published. `plugin_source`, which this depends on, is `publish_to: none`, # and the CLI is installed from source rather than pub.dev. publish_to: none From a89c64ecb86fea16725fba2afe8fe1c8d4c343c9 Mon Sep 17 00:00:00 2001 From: Dominik Simonik Date: Mon, 26 Oct 2026 13:53:51 +0100 Subject: [PATCH 3/6] chore: drop bootstrap-sha, the 0.1.0 tags mark the baseline --- .release-please-config.json | 1 - 1 file changed, 1 deletion(-) diff --git a/.release-please-config.json b/.release-please-config.json index d4870d74..9ea2549d 100644 --- a/.release-please-config.json +++ b/.release-please-config.json @@ -10,7 +10,6 @@ "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", "group-pull-request-title-pattern": "chore: release ${branch}", "include-component-in-tag": true, - "bootstrap-sha": "875842bc783d6bd1592f6e5204d9735709df3a93", "packages": { "packages/vgv_ai_cli": { "release-type": "dart", From 4fc3abe2d89bd43d0d9211202b1472e6d78c4cb3 Mon Sep 17 00:00:00 2001 From: Dominik Simonik Date: Mon, 26 Oct 2026 13:58:27 +0100 Subject: [PATCH 4/6] chore: release the repository as one unit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The two package entries meant a fix in plugin_source bumped only plugin_source, so the weekly pin bump — how users get new skills and agents — never reached the CLI. A single release unit at "." releases on any change in the repository, and tags it `vX.Y.Z` instead of one tag per component. The root pubspec.yaml now carries that version, and release-please writes it into the CLI's pubspec.yaml and lib/src/version.dart through the x-release-please-version markers on their version lines. That is how Very Good CLI does it, and it replaces build_version: gone with it are three dev dependencies, ensure_build_test.dart, the version-verify tag, the verify-version job, and the four workflow steps that regenerated the file on the release branch. --- .github/workflows/release_please.yaml | 38 ------- .github/workflows/vgv_ai_cli.yaml | 20 ---- .release-please-config.json | 27 ++--- .release-please-manifest.json | 3 +- AGENTS.md | 12 +- packages/vgv_ai_cli/dart_test.yaml | 2 - packages/vgv_ai_cli/lib/src/version.dart | 4 +- packages/vgv_ai_cli/pubspec.yaml | 5 +- .../vgv_ai_cli/test/ensure_build_test.dart | 12 -- pubspec.lock | 104 ------------------ pubspec.yaml | 4 + 11 files changed, 19 insertions(+), 212 deletions(-) delete mode 100644 packages/vgv_ai_cli/test/ensure_build_test.dart diff --git a/.github/workflows/release_please.yaml b/.github/workflows/release_please.yaml index bdea5f2c..dfca753d 100644 --- a/.github/workflows/release_please.yaml +++ b/.github/workflows/release_please.yaml @@ -19,46 +19,8 @@ jobs: steps: - name: šŸš€ Release Please - id: release uses: googleapis/release-please-action@v5 with: token: ${{ secrets.RELEASE_PLEASE_TOKEN }} manifest-file: ".release-please-manifest.json" config-file: ".release-please-config.json" - - # `packages/vgv_ai_cli/lib/src/version.dart` is generated from the - # package version by `build_version`, so the bump release-please writes - # leaves it stale and `verify-version` fails on the release PR. - # Regenerate it on the release branch. - - name: šŸ“š Git Checkout - if: steps.release.outputs.prs_created == 'true' - uses: actions/checkout@v7 - with: - ref: ${{ fromJSON(steps.release.outputs.pr).headBranchName }} - token: ${{ secrets.RELEASE_PLEASE_TOKEN }} - - - name: šŸŽÆ Setup Dart - if: steps.release.outputs.prs_created == 'true' - uses: dart-lang/setup-dart@v1.8.1 - with: - sdk: "3.13.0" - - - name: šŸ”„ Regenerate version file - if: steps.release.outputs.prs_created == 'true' - working-directory: packages/vgv_ai_cli - run: | - dart pub get - dart run build_runner build - - - name: šŸ“¤ Push version file - if: steps.release.outputs.prs_created == 'true' - run: | - if [ -z "$(git status --porcelain packages/vgv_ai_cli/lib/src/version.dart)" ]; then - echo "version.dart is already in sync" - exit 0 - fi - git config user.name "github-actions[bot]" - git config user.email "41898282+github-actions[bot]@users.noreply.github.com" - git add packages/vgv_ai_cli/lib/src/version.dart - git commit -m "chore: regenerate version file" - git push diff --git a/.github/workflows/vgv_ai_cli.yaml b/.github/workflows/vgv_ai_cli.yaml index 47cc2b5a..5f474cf7 100644 --- a/.github/workflows/vgv_ai_cli.yaml +++ b/.github/workflows/vgv_ai_cli.yaml @@ -80,26 +80,6 @@ jobs: exit 1 fi - verify-version: - runs-on: ubuntu-latest - steps: - - name: šŸ“š Git Checkout - uses: actions/checkout@v7 - - - name: šŸŽÆ Setup Dart - uses: dart-lang/setup-dart@v1.8.1 - with: - sdk: "3.13.0" - - - name: šŸ“¦ Install Dependencies - working-directory: packages/vgv_ai_cli - run: | - dart pub get - - - name: šŸ”Ž Verify version - working-directory: packages/vgv_ai_cli - run: dart run test --run-skipped -t version-verify - verify-pins: runs-on: ubuntu-latest steps: diff --git a/.release-please-config.json b/.release-please-config.json index 9ea2549d..780a2d9b 100644 --- a/.release-please-config.json +++ b/.release-please-config.json @@ -9,26 +9,15 @@ ], "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", "group-pull-request-title-pattern": "chore: release ${branch}", - "include-component-in-tag": true, + "include-component-in-tag": false, "packages": { - "packages/vgv_ai_cli": { + ".": { "release-type": "dart", - "component": "vgv_ai_cli", - "changelog-path": "CHANGELOG.md", - "version-file": "pubspec.yaml" - }, - "packages/plugin_source": { - "release-type": "dart", - "component": "plugin_source", - "changelog-path": "CHANGELOG.md", - "version-file": "pubspec.yaml" - } - }, - "plugins": [ - { - "type": "linked-versions", - "groupName": "vgv_ai", - "components": ["vgv_ai_cli", "plugin_source"] + "changelog-path": "packages/vgv_ai_cli/CHANGELOG.md", + "extra-files": [ + "packages/vgv_ai_cli/pubspec.yaml", + "packages/vgv_ai_cli/lib/src/version.dart" + ] } - ] + } } diff --git a/.release-please-manifest.json b/.release-please-manifest.json index a768163b..466df71c 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,4 +1,3 @@ { - "packages/vgv_ai_cli": "0.1.0", - "packages/plugin_source": "0.1.0" + ".": "0.1.0" } diff --git a/AGENTS.md b/AGENTS.md index d346f256..37006ef5 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -51,17 +51,11 @@ dart run test test/src/commands/update_command_test.dart # 'handles pub update errors' and 'handles pub update process errors') dart run test --plain-name 'handles pub update' -# Verify the generated version file is in sync (tagged, skipped by default) -dart run test --run-skipped -t version-verify - -# Regenerate lib/src/version.dart after bumping the package version -dart run build_runner build - # Run the CLI from source dart run bin/vgv_ai.dart --help ``` -**Full test run with coverage** is the one exception. With the VGV AI Flutter Plugin active, a hook denies `dart test`, `flutter test`, `very_good test`, `dart create`, `flutter create`, `very_good create`, and `very_good packages` when they are the first two tokens of a Bash command (note `very_good packages get` is blocked while `dart pub get` is not), so run it through the `very_good_cli` MCP `test` tool instead. That tool takes no file path and no name filter, which is why the single-test commands above use `dart run test` — a form the hook does not catch, and the one CI itself uses for `verify-version`. The CI step, from the reusable `dart_package.yml` workflow, is equivalent to: +**Full test run with coverage** is the one exception. With the VGV AI Flutter Plugin active, a hook denies `dart test`, `flutter test`, `very_good test`, `dart create`, `flutter create`, `very_good create`, and `very_good packages` when they are the first two tokens of a Bash command (note `very_good packages get` is blocked while `dart pub get` is not), so run it through the `very_good_cli` MCP `test` tool instead. That tool takes no file path and no name filter, which is why the single-test commands above use `dart run test` — a form the hook does not catch,. The CI step, from the reusable `dart_package.yml` workflow, is equivalent to: ```bash very_good dart test -j 4 --coverage --min-coverage 100 --optimization @@ -116,7 +110,7 @@ A result with one status enum, such as `EntryHealth` or `ReversedEntry`, is buil ### Generated version file -`lib/src/version.dart` is generated by `build_version` from the `version:` field in `pubspec.yaml`. **Never edit it by hand** — regenerate with `build_runner` after bumping the version. `test/ensure_build_test.dart` verifies it is in sync; it is tagged `version-verify` and skipped by default (see `dart_test.yaml`). +`lib/src/version.dart` carries the version release-please writes. **Never edit it by hand**, and never bump a version by hand either — the repository releases as one unit from the root `pubspec.yaml`, and release-please carries that version into this file and the CLI's `pubspec.yaml` through the `x-release-please-version` markers on their version lines. ## Code Conventions @@ -147,7 +141,7 @@ This is a pure Dart CLI with no widgets, so the rule is: any skill gated on Flut Each workflow under `.github/workflows/` is path-filtered, and every reusable workflow comes from very_good_workflows through the floating `@v2` tag. -- `vgv_ai_cli.yaml` runs on changes to itself, `.github/cspell.json`, `packages/vgv_ai_cli/lib/**`, `packages/vgv_ai_cli/test/**`, `packages/vgv_ai_cli/pubspec.yaml`, `packages/plugin_source/lib/**`, `packages/plugin_source/pubspec.yaml`, `bricks/**` and `tool/**`. Its jobs are `semantic-pull-request`, `build` (the reusable `dart_package.yml` in `packages/vgv_ai_cli`), `spell-check`, `verify-bundle`, `verify-version` and `verify-pins`. +- `vgv_ai_cli.yaml` runs on changes to itself, `.github/cspell.json`, `packages/vgv_ai_cli/lib/**`, `packages/vgv_ai_cli/test/**`, `packages/vgv_ai_cli/pubspec.yaml`, `packages/plugin_source/lib/**`, `packages/plugin_source/pubspec.yaml`, `bricks/**` and `tool/**`. Its jobs are `semantic-pull-request`, `build` (the reusable `dart_package.yml` in `packages/vgv_ai_cli`), `spell-check`, `verify-bundle` and `verify-pins`. - `plugin_source.yaml` runs on changes to itself and `packages/plugin_source/**`. Its jobs are `semantic-pull-request` and `build` (the reusable `dart_package.yml` in `packages/plugin_source`). - Both `build` jobs also run the cognitive complexity check on their package's `lib`, which fails when any function scores above 15. Split a function that crosses it into smaller ones rather than raising the threshold. Run it locally with the `cognitive_complexity` scanner from [kevmoo/analytica.dart](https://github.com/kevmoo/analytica.dart/tree/main/packages/cognitive_complexity). - `license_check.yaml` runs on changes to itself and either package's `pubspec.yaml`. Dependency licenses are restricted to `MIT`, `BSD-3-Clause`, `BSD-2-Clause`, `Apache-2.0`. diff --git a/packages/vgv_ai_cli/dart_test.yaml b/packages/vgv_ai_cli/dart_test.yaml index 4b64be76..b73075a3 100644 --- a/packages/vgv_ai_cli/dart_test.yaml +++ b/packages/vgv_ai_cli/dart_test.yaml @@ -1,5 +1,3 @@ tags: - version-verify: - skip: "Should only be run during pull request. Verifies if version file is updated." pinned-plugins: skip: "Clones the real pinned plugins over the network. Run in CI by verify-pins." diff --git a/packages/vgv_ai_cli/lib/src/version.dart b/packages/vgv_ai_cli/lib/src/version.dart index 5b6bfb4d..39ea6999 100644 --- a/packages/vgv_ai_cli/lib/src/version.dart +++ b/packages/vgv_ai_cli/lib/src/version.dart @@ -1,2 +1,2 @@ -// Generated code. Do not modify. -const packageVersion = '0.1.0'; +// Managed by release-please. Do not edit by hand. +const packageVersion = '0.1.0'; // x-release-please-version diff --git a/packages/vgv_ai_cli/pubspec.yaml b/packages/vgv_ai_cli/pubspec.yaml index 4c3a7c7d..94a2b156 100644 --- a/packages/vgv_ai_cli/pubspec.yaml +++ b/packages/vgv_ai_cli/pubspec.yaml @@ -1,6 +1,6 @@ name: vgv_ai_cli description: A CLI that configures Very Good AI coding agents and tooling -version: 0.1.0 +version: 0.1.0 # x-release-please-version repository: https://github.com/VeryGoodOpenSource/vgv_ai_cli issue_tracker: https://github.com/VeryGoodOpenSource/vgv_ai_cli/issues # Not published. `plugin_source`, which this depends on, is `publish_to: none`, @@ -26,9 +26,6 @@ dependencies: toml: ^0.18.0 dev_dependencies: - build_runner: ^2.16.2 - build_verify: ^3.1.1 - build_version: ^2.1.3 mocktail: ^1.0.5 test: ^1.33.0 very_good_analysis: ^11.0.0 diff --git a/packages/vgv_ai_cli/test/ensure_build_test.dart b/packages/vgv_ai_cli/test/ensure_build_test.dart deleted file mode 100644 index 510db214..00000000 --- a/packages/vgv_ai_cli/test/ensure_build_test.dart +++ /dev/null @@ -1,12 +0,0 @@ -@Tags(['version-verify', 'skip_very_good_optimization']) -library; - -import 'package:build_verify/build_verify.dart'; -import 'package:test/test.dart'; - -void main() { - test( - 'ensure_build', - () => expectBuildClean(packageRelativeDirectory: 'packages/vgv_ai_cli'), - ); -} diff --git a/pubspec.lock b/pubspec.lock index 12a0bb19..e9835ab2 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -57,70 +57,6 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.2" - build: - dependency: transitive - description: - name: build - sha256: "8a5c5761af8e31748bba3c82f68925ace40f3225c3eea25be9beb57eca7cd7a8" - url: "https://pub.dev" - source: hosted - version: "4.0.11" - build_config: - dependency: transitive - description: - name: build_config - sha256: d466ed2dc9c6cd1d169948879b84ee061eb5e22c64a7c6089879c6296d272a8d - url: "https://pub.dev" - source: hosted - version: "1.3.3" - build_daemon: - dependency: transitive - description: - name: build_daemon - sha256: "39ab65f7c60c19af64b9ef96e6a5d3ab48355f7dddfd98a9079d55a8cb6628fc" - url: "https://pub.dev" - source: hosted - version: "4.1.7" - build_runner: - dependency: transitive - description: - name: build_runner - sha256: "6feadd32d90a68253c1f7b4fcff76adb4b41ad32a53f8bad835dc65f01ac9dc5" - url: "https://pub.dev" - source: hosted - version: "2.16.2" - build_verify: - dependency: transitive - description: - name: build_verify - sha256: "3b17b59b6d66f9d3e6014996f089902d56cec5760e051c353cc387b9da577652" - url: "https://pub.dev" - source: hosted - version: "3.1.1" - build_version: - dependency: transitive - description: - name: build_version - sha256: "1063066ec338c18f0629d01077c9315f92fae3e7e0e06d0dc10e8aa3145d44f5" - url: "https://pub.dev" - source: hosted - version: "2.1.3" - built_collection: - dependency: transitive - description: - name: built_collection - sha256: "44922ecebd8e3d0cef743dadd3b54df4e87e2a4c52a29465a1872aa9e192caa8" - url: "https://pub.dev" - source: hosted - version: "5.1.2" - built_value: - dependency: transitive - description: - name: built_value - sha256: f87ea98192116f7093cb214551ce1929caae0681fdba282b3d8b4462adee7bb7 - url: "https://pub.dev" - source: hosted - version: "8.13.0" checked_yaml: dependency: transitive description: @@ -185,14 +121,6 @@ packages: url: "https://pub.dev" source: hosted version: "3.0.7" - dart_style: - dependency: transitive - description: - name: dart_style - sha256: "82ade9fc4273f29ed673e33166944465225b4f7fc5d4aaef48605cc751c18fc1" - url: "https://pub.dev" - source: hosted - version: "3.1.13" equatable: dependency: transitive description: @@ -225,14 +153,6 @@ packages: url: "https://pub.dev" source: hosted version: "7.0.1" - fixnum: - dependency: transitive - description: - name: fixnum - sha256: b6dc7065e46c974bc7c5f143080a6764ec7a4be6da1285ececdc37be96de53be - url: "https://pub.dev" - source: hosted - version: "1.1.1" frontend_server_client: dependency: transitive description: @@ -249,14 +169,6 @@ packages: url: "https://pub.dev" source: hosted version: "2.2.0" - graphs: - dependency: transitive - description: - name: graphs - sha256: "741bbf84165310a68ff28fe9e727332eef1407342fca52759cb21ad8177bb8d0" - url: "https://pub.dev" - source: hosted - version: "2.3.2" http: dependency: transitive description: @@ -441,14 +353,6 @@ packages: url: "https://pub.dev" source: hosted version: "0.6.0" - pubspec_parse: - dependency: transitive - description: - name: pubspec_parse - sha256: c38b81cbf34450b67e0265d73433569d12e34782e30ed769c9cc99c9d5f2e796 - url: "https://pub.dev" - source: hosted - version: "1.6.0" shelf: dependency: transitive description: @@ -521,14 +425,6 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.4" - stream_transform: - dependency: transitive - description: - name: stream_transform - sha256: a00e5f18bffc764f923e7dec1038527f7fe7a1791361a7117f0358193f13d53a - url: "https://pub.dev" - source: hosted - version: "2.1.2" string_scanner: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 62743e42..15f396cc 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -2,6 +2,10 @@ name: vgv_ai_cli_workspace description: Workspace root for the Very Good AI CLI monorepo. publish_to: none +# The repository releases as one unit. release-please bumps this, and carries +# the same version into the CLI's pubspec and version.dart. +version: 0.1.0 + environment: sdk: ^3.13.0 From affd73194fe177abb8bf0f1bfe42209ef0adb177 Mon Sep 17 00:00:00 2001 From: Dominik Simonik Date: Mon, 26 Oct 2026 14:07:14 +0100 Subject: [PATCH 5/6] chore: publish both packages to pub.dev MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The two packages ship as one CLI at one version, so both go to pub.dev and both follow the release: release-please writes the version into the root pubspec, the CLI's pubspec and version.dart, plugin_source's pubspec, and the `plugin_source` constraint the CLI depends on, through the x-release-please-version markers on those lines. pub_publish.yaml publishes on the `v*` tag, plugin_source first — the CLI resolves it from pub.dev, so publishing the CLI against a version that is not there yet fails. --- .github/workflows/pub_publish.yaml | 35 +++++++++++++++++++++++++++ .release-please-config.json | 3 ++- packages/plugin_source/pubspec.yaml | 3 +-- packages/vgv_ai_cli/example/README.md | 3 +++ packages/vgv_ai_cli/pubspec.yaml | 6 ++--- 5 files changed, 43 insertions(+), 7 deletions(-) create mode 100644 .github/workflows/pub_publish.yaml create mode 100644 packages/vgv_ai_cli/example/README.md diff --git a/.github/workflows/pub_publish.yaml b/.github/workflows/pub_publish.yaml new file mode 100644 index 00000000..a37037f5 --- /dev/null +++ b/.github/workflows/pub_publish.yaml @@ -0,0 +1,35 @@ +name: pub_publish + +on: + push: + tags: + - "v[0-9]+.[0-9]+.[0-9]+*" # tag pattern on pub.dev: 'v{{version}}' + workflow_dispatch: + +jobs: + publish: + permissions: + id-token: write # Required for authentication using OIDC + runs-on: ubuntu-latest + + steps: + - name: šŸ“š Git Checkout + uses: actions/checkout@v7 + + - name: šŸŽÆ Setup Dart + uses: dart-lang/setup-dart@v1.8.1 + with: + sdk: "3.13.0" + + - name: šŸ“¦ Install Dependencies + run: dart pub get + + # plugin_source first: the CLI resolves it from pub.dev, so publishing + # the CLI against a version that is not there yet fails. + - name: šŸ“¢ Publish plugin_source + working-directory: packages/plugin_source + run: dart pub publish --force + + - name: šŸ“¢ Publish vgv_ai_cli + working-directory: packages/vgv_ai_cli + run: dart pub publish --force diff --git a/.release-please-config.json b/.release-please-config.json index 780a2d9b..93319fd5 100644 --- a/.release-please-config.json +++ b/.release-please-config.json @@ -16,7 +16,8 @@ "changelog-path": "packages/vgv_ai_cli/CHANGELOG.md", "extra-files": [ "packages/vgv_ai_cli/pubspec.yaml", - "packages/vgv_ai_cli/lib/src/version.dart" + "packages/vgv_ai_cli/lib/src/version.dart", + "packages/plugin_source/pubspec.yaml" ] } } diff --git a/packages/plugin_source/pubspec.yaml b/packages/plugin_source/pubspec.yaml index beaacb55..40e8c284 100644 --- a/packages/plugin_source/pubspec.yaml +++ b/packages/plugin_source/pubspec.yaml @@ -2,10 +2,9 @@ name: plugin_source description: >- Resolves VGV Claude Code plugins to a directory on disk and parses them into a harness-neutral asset model. -version: 0.1.0 +version: 0.1.0 # x-release-please-version repository: https://github.com/VeryGoodOpenSource/vgv_ai_cli issue_tracker: https://github.com/VeryGoodOpenSource/vgv_ai_cli/issues -publish_to: none resolution: workspace environment: sdk: ^3.13.0 diff --git a/packages/vgv_ai_cli/example/README.md b/packages/vgv_ai_cli/example/README.md new file mode 100644 index 00000000..10207b8d --- /dev/null +++ b/packages/vgv_ai_cli/example/README.md @@ -0,0 +1,3 @@ +# Example + +`vgv_ai` is used from the terminal. See [../README.md](../README.md) for usage. diff --git a/packages/vgv_ai_cli/pubspec.yaml b/packages/vgv_ai_cli/pubspec.yaml index 94a2b156..18a040d7 100644 --- a/packages/vgv_ai_cli/pubspec.yaml +++ b/packages/vgv_ai_cli/pubspec.yaml @@ -3,9 +3,7 @@ description: A CLI that configures Very Good AI coding agents and tooling version: 0.1.0 # x-release-please-version repository: https://github.com/VeryGoodOpenSource/vgv_ai_cli issue_tracker: https://github.com/VeryGoodOpenSource/vgv_ai_cli/issues -# Not published. `plugin_source`, which this depends on, is `publish_to: none`, -# and the CLI is installed from source rather than pub.dev. -publish_to: none +topics: [cli, ai, agents, tooling] resolution: workspace environment: sdk: ^3.13.0 @@ -20,7 +18,7 @@ dependencies: mason: ^0.1.0 mason_logger: ^0.3.6 path: ^1.9.1 - plugin_source: ^0.1.0 + plugin_source: ^0.1.0 # x-release-please-version pub_semver: ^2.2.1 pub_updater: ^0.6.0 toml: ^0.18.0 From 7e6f003d437b705b7e82dc938a7b5fa556e33008 Mon Sep 17 00:00:00 2001 From: Dominik Simonik Date: Mon, 26 Oct 2026 14:18:52 +0100 Subject: [PATCH 6/6] chore: release the two packages in lockstep instead of from the root MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Releasing from "." meant the workspace root had to carry a version, and the root is not a package. Each package now releases itself, and the linked-versions plugin holds them at the same version, so a fix in plugin_source still releases the CLI — which is how a pin bump reaches users. include-component-in-tag is false for the CLI and true for plugin_source, so the product tag stays `vX.Y.Z` and pub_publish.yaml keeps firing on it. The dart strategy writes each package's own version, so the only lines left with an x-release-please-version marker are the two the generic updater has to reach: lib/src/version.dart and the plugin_source constraint in the CLI's pubspec. mergeUpdates composes that with the strategy's own pubspec update. --- .release-please-config.json | 28 +++++++++++++++++++--------- .release-please-manifest.json | 3 ++- AGENTS.md | 6 +++++- packages/plugin_source/pubspec.yaml | 2 +- packages/vgv_ai_cli/pubspec.yaml | 2 +- pubspec.yaml | 4 ---- 6 files changed, 28 insertions(+), 17 deletions(-) diff --git a/.release-please-config.json b/.release-please-config.json index 93319fd5..427a5535 100644 --- a/.release-please-config.json +++ b/.release-please-config.json @@ -9,16 +9,26 @@ ], "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", "group-pull-request-title-pattern": "chore: release ${branch}", - "include-component-in-tag": false, + "include-component-in-tag": true, "packages": { - ".": { + "packages/vgv_ai_cli": { "release-type": "dart", - "changelog-path": "packages/vgv_ai_cli/CHANGELOG.md", - "extra-files": [ - "packages/vgv_ai_cli/pubspec.yaml", - "packages/vgv_ai_cli/lib/src/version.dart", - "packages/plugin_source/pubspec.yaml" - ] + "component": "vgv_ai_cli", + "changelog-path": "CHANGELOG.md", + "include-component-in-tag": false, + "extra-files": ["pubspec.yaml", "lib/src/version.dart"] + }, + "packages/plugin_source": { + "release-type": "dart", + "component": "plugin_source", + "changelog-path": "CHANGELOG.md" + } + }, + "plugins": [ + { + "type": "linked-versions", + "groupName": "vgv_ai", + "components": ["vgv_ai_cli", "plugin_source"] } - } + ] } diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 466df71c..a768163b 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,4 @@ { - ".": "0.1.0" + "packages/vgv_ai_cli": "0.1.0", + "packages/plugin_source": "0.1.0" } diff --git a/AGENTS.md b/AGENTS.md index 37006ef5..047948df 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -110,7 +110,11 @@ A result with one status enum, such as `EntryHealth` or `ReversedEntry`, is buil ### Generated version file -`lib/src/version.dart` carries the version release-please writes. **Never edit it by hand**, and never bump a version by hand either — the repository releases as one unit from the root `pubspec.yaml`, and release-please carries that version into this file and the CLI's `pubspec.yaml` through the `x-release-please-version` markers on their version lines. +`lib/src/version.dart` carries the version release-please writes. **Never edit it by hand**, and never bump a version by hand either. + +Both packages release together. release-please bumps each package's own `pubspec.yaml`, and the `linked-versions` plugin holds them at the same version, so a fix in `plugin_source` releases the CLI too — which is how a pin bump reaches users. Two lines need the generic updater and carry an `x-release-please-version` marker: this file, and the `plugin_source:` constraint in the CLI's `pubspec.yaml`. Nothing else should ever get that marker. + +The CLI is tagged `vX.Y.Z` and `plugin_source` as `plugin_source-vX.Y.Z`; `pub_publish.yaml` fires on the former. ## Code Conventions diff --git a/packages/plugin_source/pubspec.yaml b/packages/plugin_source/pubspec.yaml index 40e8c284..9bb2b8b1 100644 --- a/packages/plugin_source/pubspec.yaml +++ b/packages/plugin_source/pubspec.yaml @@ -2,7 +2,7 @@ name: plugin_source description: >- Resolves VGV Claude Code plugins to a directory on disk and parses them into a harness-neutral asset model. -version: 0.1.0 # x-release-please-version +version: 0.1.0 repository: https://github.com/VeryGoodOpenSource/vgv_ai_cli issue_tracker: https://github.com/VeryGoodOpenSource/vgv_ai_cli/issues resolution: workspace diff --git a/packages/vgv_ai_cli/pubspec.yaml b/packages/vgv_ai_cli/pubspec.yaml index 18a040d7..cf4226ee 100644 --- a/packages/vgv_ai_cli/pubspec.yaml +++ b/packages/vgv_ai_cli/pubspec.yaml @@ -1,6 +1,6 @@ name: vgv_ai_cli description: A CLI that configures Very Good AI coding agents and tooling -version: 0.1.0 # x-release-please-version +version: 0.1.0 repository: https://github.com/VeryGoodOpenSource/vgv_ai_cli issue_tracker: https://github.com/VeryGoodOpenSource/vgv_ai_cli/issues topics: [cli, ai, agents, tooling] diff --git a/pubspec.yaml b/pubspec.yaml index 15f396cc..62743e42 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -2,10 +2,6 @@ name: vgv_ai_cli_workspace description: Workspace root for the Very Good AI CLI monorepo. publish_to: none -# The repository releases as one unit. release-please bumps this, and carries -# the same version into the CLI's pubspec and version.dart. -version: 0.1.0 - environment: sdk: ^3.13.0