尚未偵測到更新。GitHub 發布版本後會顯示在這裡。
個人 GitHub 帳號下公開儲存庫的擁有者可以登入並驗證所有權,自行管理介紹,無需管理員核准。
登入並產生驗證檔案,在 30 分鐘內將其提交至此儲存庫的預設分支。其他分支或分叉儲存庫中的檔案無效。然後在下方檢查檔案,即可無需管理員核准直接管理專案。請保留檔案以維持管理權限。
如需登入,將前往登入頁面。登入後請回到此處,再次點擊所選的驗證按鈕。
在專案資料夾中執行 /nomorevibe verify,即可驗證所有權並自行管理介紹。
一分鐘完成驗證製作者的介紹僅有上面的一句話。 更多詳情請閱讀儲存庫 README。 儲存庫 README ↗
正在載入完整 README。
檢視完整 README ↗The shared foundation for our projects — the one place our development guardrails live, so every other project points here instead of repeating the rules per repo.
Each project is its own standalone repo and points at this foundation for shared
CI guardrails, permissions, and skills. Only the process is shared — not the
design, with one exception: WordPress plugin admin screens, which all come from the
shared blueworx-admin-design system committed here at
.claude/skills/blueworx-admin-design/.
That system also carries the page editor — the shared shell and behaviour for any screen where a
site owner edits a record or plugin settings, so every plugin's editing experience is the same one.
Page content is edited in WordPress's block editor, not on a screen of ours.
New projects are set up by pasting the matching Starter Prompt (standalone / WordPress plugin / headless) into Claude Code — there are no starter template repos to clone from.
As part of that setup, every new project copies
CLAUDE.md.template into its own repo root as CLAUDE.md.
This carries the condensed global rules into the project itself, so the guardrails
stay consistent regardless of whose machine the project is opened on — rather than
relying on each person's personal ~/.claude/CLAUDE.md.
# from a new project's repo root
curl -o CLAUDE.md \
https://raw.githubusercontent.com/blueworx-io/bluegroup_core_foundation/main/CLAUDE.md.template
All three are saved here, and each is self-contained — paste the matching one into Claude Code in the new, empty repo and the result passes its CI workflow on the first pull request:
docs/starter-prompt-standalone.mddocs/starter-prompt-wordpress-plugin.mdFor headless projects there is a saved follow-on prompt,
docs/starter-prompt-headless-framework.md,
that scaffolds the standard framework — Next.js (App Router) + TypeScript — on top
of the initial setup.
Skills note: the approved skills load automatically from the shared Claude Code settings, with one exception — graphify is a per-machine Python CLI. Install it once per machine with
uv tool install graphifyy && graphify install. The CLI installs to~/.local/bin(Windows:%USERPROFILE%\.local\bin), which may not be on PATH — ifgraphifyisn't found, add that directory to PATH rather than reinstalling. The template's Skill Usage Policy section then tells Claude Code when and how to fire each skill automatically, so nobody has to remember to invoke them.
Instead of repeating the rules per repo, a project adds one small caller workflow
that points at the reusable workflow for its type. On every pull request the shared
workflow installs + lints, builds, checks the version bump, checks the changelog,
checks dependencies against the project's approved-deps.json, checks a WordPress
plugin's copy of the shared admin design system is current, runs PHPCS and
PHPUnit when their configs are present, and runs Playwright.
Standalone
# .github/workflows/ci.yml
name: CI
on: pull_request
jobs:
guardrails:
uses: blueworx-io/bluegroup_core_foundation/.github/workflows/ci-standalone.yml@v1
with:
foundation_ref: v1
Headless
name: CI
on: pull_request
jobs:
guardrails:
uses: blueworx-io/bluegroup_core_foundation/.github/workflows/ci-headless.yml@v1
with:
foundation_ref: v1
The Netlify deploy preview is a required check on headless projects, and it is the only thing that makes headless different from standalone. The workflow waits for Netlify's
deploy-previewcommit status on the PR head, fails if it failed or never arrived, then fails again if the preview URL doesn't answer — a green status on a site that 404s behind deploy protection is not a preview anyone can review. Connect the repo to Netlify, or setrequire_netlify_preview: falseand say in the caller workflow why this project has no preview.
WordPress plugin (Playwright runs against a disposable WordPress the run provisions itself — PHP + SQLite, no Docker, no hosting):
name: CI
on: pull_request
jobs:
guardrails:
uses: blueworx-io/bluegroup_core_foundation/.github/workflows/ci-wordpress.yml@v1
with:
plugin_slug: my-plugin
use_local_wordpress: true
foundation_ref: v1
secrets: inherit
This is the default for new plugin projects. See
docs/wordpress-test-harness.mdfor how to run the same instance locally, and add.wp-test/to the project's.gitignore.The alternative —
preview_url: https://staging.example.comagainst a hosted staging site — is still supported, but it is how CI came to report green while running zero tests: a placeholder URL makes every spec skip itself. If you use it, point it at something real and passWP_ADMIN_USER/WP_ADMIN_PASS.
secrets: inheritis not optional in practice. Tests that sign in to wp-admin needWP_ADMIN_USERandWP_ADMIN_PASSas repo secrets. Without them those specs skip themselves and the run reports green having asserted nothing. Pass them explicitly instead if you prefer:secrets: WP_ADMIN_USER: ${{ secrets.WP_ADMIN_USER }} WP_ADMIN_PASS: ${{ secrets.WP_ADMIN_PASS }}The same trap applies to
preview_url: point it at a real instance. Specs that guard on a placeholder URL skip too.
All inputs have sensible defaults (node_version, lint_command, build_command,
test_command, foundation_ref; WordPress adds php_version, preview_url,
plugin_slug, wp_login_path, changelog_dir). Override only what a project
needs. A WordPress theme sets theme_slug instead of plugin_slug.
Set
foundation_refto match the@refyou called with. The@refpicks the workflow;foundation_refpicks the check scripts the workflow fetches. They default apart —foundation_refdefaults tomain— so calling@v1without it runs the v1 workflow against whatever is onmaintoday.
The foundation is fetched outside the project's workspace, into the runner's temp directory. It used to land in the workspace as
.foundation/, where a project whose lint script is a plaineslint .would lint the foundation's own scripts and fail the build on someone else's code style. Nothing in a project needs to ignore it.
What ships in a plugin zip is decided in one place,
scripts/plugin-zip-excludes.txt. Every PR stages the tree the release would zip and fails if anything that must never reach a live site survives — apreview/harness that bootstraps its ownABSPATH, test specs,composer.json,CLAUDE.md, keys. Project-specific additions go in theexclude_pathsinput; set it identically on the CI and release callers, or the check and the build disagree about what ships.
If you override
test_command, keep the json reporter. Every workflow fails the build when a Playwright run executes zero tests —npx playwright testexits 0 when everything skips, so without that gate a suite that skips itself reports green having asserted nothing. The check reads the json reporter's output, so a custom command needs--reporter=list,json(or equivalent) or it will fail asking for it.WordPress projects have a temporary escape hatch,
allow_zero_tests: true, which downgrades that failure to a warning for a project that has no working test host yet. It is not a fix — a project setting it is not being tested — so it should always have an open issue against it and be removed once real tests run.
A PR passes the changelog guardrail by either editing CHANGELOG.md — the
original rule, and still the default for a project that does nothing — or by
adding a file under a fragment directory, changelog.d/ by default.
Fragments exist because the first shape has a cost that grows with the number of
open branches. Every entry goes at the top of one shared file, so any two live
branches change the same lines and every merge hits the same conflict. It is
trivial to resolve and easy to resolve wrongly, which is how it earns its keep as
a source of bugs. A file per branch cannot conflict; a release step folds the
pending fragments into CHANGELOG.md on the default branch, where nothing is
running in parallel.
A project opts in by creating the directory — there is no workflow change,
because changelog_dir already defaults to changelog.d. A project without that
directory can never match the second shape, so nothing about its CI changes. Set
changelog_dir only to use a different name, or '' to turn the second shape
off entirely.
The directory's own README.md is excluded: documenting the format is not a
changelog entry.
Opting in means adding the assembly workflow too. The check above only
accepts fragments; something has to clear them, or the directory grows forever
and CHANGELOG.md never moves. That is assemble-changelog.yml, reusable like
the CI workflows:
# .github/workflows/changelog.yml
name: Assemble changelog
on:
push:
branches: [main]
workflow_dispatch:
jobs:
assemble:
uses: blueworx-io/bluegroup_core_foundation/.github/workflows/assemble-changelog.yml@v1
with:
version_source: plugin-header # WordPress plugins; omit for package.json
foundation_ref: v1
permissions:
contents: write
It folds the pending fragments into CHANGELOG.md under the current version,
deletes them, and commits to the default branch. version_source must match
whatever the project's version bump check uses, or the two disagree about which
version an entry belongs to.
Branch protection blocks this job. It commits straight to the default branch, so a ruleset requiring pull requests rejects the push and the job fails saying so. Add the GitHub Actions bot to the ruleset's bypass list. Opening an assembly PR instead does not work: it changes the changelog and bumps no version, so the version bump guardrail fails it every time.
The foundation is tagged, and projects pin to a tag rather than tracking main.
On @main every change to a reusable workflow lands in every project's CI the moment
it merges, with no way to stage it.
Two kinds of tag, following the GitHub Actions convention:
v1 — a moving major tag. It is force-moved forward to the newest
backward-compatible release. This is what projects pin to: they pick up fixes and
compatible additions without a PR per repo.v1.0.0, v1.1.0, … — immutable release tags. Cut once, never moved. Pin to
one of these when a project needs an exact, frozen snapshot (debugging a CI change,
or a repo that must not move on its own).A breaking change — removing or renaming a workflow input, changing a check's pass
condition so a previously-green project fails, or a rename that changes how a caller
must invoke a workflow — gets a new major (v2 / v2.0.0) instead. v1 is never
moved onto it.
From an up-to-date main:
git tag -a v1.1.0 -m "v1.1.0" # immutable release tag
git push origin v1.1.0
git tag -f -a v1 -m "v1 -> v1.1.0" # move the major tag forward
git push -f origin v1
Force-pushing v1 is deliberate and is the only tag that is ever force-pushed.
Because it moves, it is a convenience, not a reproducibility guarantee — pin an
immutable v1.x.y when you need the run to be repeatable.
v1Every project pins @v1 and foundation_ref: v1. Nothing on main reaches any of
them until v1 is force-moved onto it, so a shared check merged and left there is
running nowhere.
That failure is quiet, which is what makes it worth a heading. A check that compares
a project against the foundation finds nothing to compare against an older checkout
and passes — so the guardrail looks green everywhere while being switched off
everywhere. This happened to the design system sync check: it sat on main for days,
reporting success in every plugin, having never run.
So cut the release tag and move v1 in the same sitting as the merge, using the
two commands above. If a change genuinely should not reach projects yet, say so in
the pull request — do not leave it looking done.
Projects normally need no action: @v1 follows compatible releases. A project moves
deliberately only for a major bump — change both the @ref and foundation_ref in
its caller workflow (@v1 → @v2, foundation_ref: v2) and let its own CI prove
the new major is green before merging.
Plugins update themselves on live sites from GitHub Releases — no manual zip uploads. A plugin repo adds one more caller workflow:
# .github/workflows/release.yml
name: Release
on:
push:
tags: ['v*']
jobs:
release:
uses: blueworx-io/bluegroup_core_foundation/.github/workflows/release-wordpress.yml@v1
with:
plugin_slug: my-plugin
foundation_ref: v1
permissions:
contents: write
permissions: contents: writeis required. A reusable workflow cannot widen the permissions its caller gives it, so without this the publish step fails with a 403.
Pushing a v* tag verifies the tag matches the plugin's Version: header, builds
a clean zip, checks the archive nests exactly one level, and publishes it as a
Release asset. Sites running the vendored Plugin Update Checker install it like
any other update.
Full setup — vendoring the library, the paste-in bootstrap, the per-site token,
and the release checklist — is in
docs/wordpress-auto-updates.md.
CLAUDE.md.template → the project's CLAUDE.mdtemplates/approved-deps.json → the project's
approved-deps.json (then fill in its allowed dependencies).github/PULL_REQUEST_TEMPLATE.md and
.github/ISSUE_TEMPLATE/task.md.claude/settings.json — shared permissions + approved-skill
enablement.claude/hooks/admin-ui-adherence.mjs — the
Write/Edit hook .claude/settings.json wires up. It self-disables on a repo with no
design system, so it is harmless to carry into every project, but without this file
present .claude/settings.json alone makes it fail on every Write and Edit.templates/plugin-update-checker-bootstrap.php
→ pasted into the plugin's main file (see
docs/wordpress-auto-updates.md).github/workflows/ — the three reusable guardrail workflows (ci-*.yml), the reusable
WordPress release workflow (release-wordpress.yml), the reusable changelog assembly
workflow (assemble-changelog.yml), plus this repo's own
foundation-ci.yml (runs the check-script tests on every PR, across an older and a
current Node; required by branch protection)scripts/ — the generic check scripts the workflows call (version bump, changelog,
approved deps, plugin version-sync, design system sync, admin UI adherence, plugin zip,
plugin zip content, tests-actually-ran, release-tag match, Netlify preview) plus their
tested cores in scripts/lib/, the
plugin-info resolver, stage-plugin-tree.sh + plugin-zip-excludes.txt (what ships
in a plugin zip, in one place), and wp-test-env.mjs, the local WordPress harnesstemplates/ — approved-deps.json (the empty allow-list starter) and
plugin-update-checker-bootstrap.php (paste-in auto-update wiring for plugins).github/ PR + issue templates.claude/settings.json — shared Claude Code permissions and approved skillsCLAUDE.md.template — condensed global rules every project carries as its CLAUDE.mddocs/ — the Recipe Book (the standard approach to problems
we keep solving), the design spec, implementation plan, the local WordPress test
harness guide, and the saved prompts (setup, standalone starter, WordPress plugin
starter, headless framework starter)The Team Guidelines doc (the other reference) lives in ClickUp.