You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Moves every scaffold, test, doc and skill from rtcamp/wp-framework^1.0 to rtcamp/wp-primitives^2.0 (namespace rtCamp\WPPrimitives\), following rtCamp/wp-primitives#98. It also brings over the scaffold fixes from #63; that PR keeps its VIP scaffolds and lens.
wp-framework is renamed to wp-primitives in 2.0.0 (rtCamp/wp-primitives#98).
- composer deps and WPPrimitives namespace across templates, tests, snippets
- docs/wp-framework-contract.md renamed to docs/wp-primitives-contract.md
- block JS keeps WordPress spacing; docblock and CHANGELOG follow-ups
An apostrophe or backslash in --description produced a PHP string literal that did not parse. The description now goes through a derived description_php input with the php-escape transform, as the other display-text scaffolds do, and wp/cli joins the quoted display text test.
The new discover_from allow-list rejected code:*, which docs/ai-orchestration.md documents as resolved by the orchestrating skill, so project and remote manifests using it failed validation.
…ctly
Acme\Blog against Acme_Blog sorted the same way under a whole-string compare, so the test could not catch a regression. Acme\Blog against AcmeZ only passes segment-wise.
* fix(scaffolds): harden generation and tooling
* feat(scaffolds)!: target rtcamp/wp-primitives ^2.0
wp-framework is renamed to wp-primitives in 2.0.0 (rtCamp/wp-primitives#98).
- composer deps and WPPrimitives namespace across templates, tests, snippets
- docs/wp-framework-contract.md renamed to docs/wp-primitives-contract.md
- block JS keeps WordPress spacing; docblock and CHANGELOG follow-ups
* fix(scaffolds): escape the wp/cli command description
An apostrophe or backslash in --description produced a PHP string literal that did not parse. The description now goes through a derived description_php input with the php-escape transform, as the other display-text scaffolds do, and wp/cli joins the quoted display text test.
* fix(scaffolds): accept skill-resolved code: discover sources
The new discover_from allow-list rejected code:*, which docs/ai-orchestration.md documents as resolved by the orchestrating skill, so project and remote manifests using it failed validation.
* fix(scaffolds): drop wiring targets that normalise to exactly ..
path.posix.normalize('a/../..') returns '..' with no trailing slash, which slipped past the startsWith('../') check.
* docs(ai-orchestration): list plugin-header as engine-resolved
The discovery section still said plugin-header:* was the skill's job, while the engine resolves it and the contract above says so.
* test(php-imports): use a pair only the segment-wise sort orders correctly
Acme\Blog against Acme_Blog sorted the same way under a whole-string compare, so the test could not catch a regression. Acme\Blog against AcmeZ only passes segment-wise.
---------
Co-authored-by: AnuragVasanwala <75766877+AnuragVasanwala@users.noreply.github.com>
Stopping at the first */ makes discovery ignore a valid WordPress header when a license/doc comment precedes it. WordPress scans the full first 8 KB, and a representative file with /** License */ before the plugin header resolves here to the fallback my-plugin; parse the comment containing Plugin Name/Theme Name (while still preventing later code comments from overriding header values).
Missing recursive scaffold scan for stale wp-framework references
Issue #69 explicitly requires a recursive regression test that rejects wp-framework or WPFramework anywhere under scaffolds/. These assertions update known values but no such guard was added, so a copied stale scaffold can silently reintroduce the old dependency or namespace; add the requested catalogue-wide scan.
* fix(scaffolds): harden generation and tooling
* feat(scaffolds)!: target rtcamp/wp-primitives ^2.0
wp-framework is renamed to wp-primitives in 2.0.0 (rtCamp/wp-primitives#98).
- composer deps and WPPrimitives namespace across templates, tests, snippets
- docs/wp-framework-contract.md renamed to docs/wp-primitives-contract.md
- block JS keeps WordPress spacing; docblock and CHANGELOG follow-ups
* ci: lint and test every pull request and push to main
Nothing ran the suites on a pull request, while every merge to main is
split straight onto the npm/* branches that the skeletons and the shared
workflows install from. A broken merge therefore reached new installs
with no gate in between.
The new workflow runs every workspace lint and Jest suite with coverage
thresholds on Node 22.19 (the engines floor) and 24, and installs and
tests each composer package standalone, the way it ships after the
subtree split, on PHP 8.2, 8.3 and 8.4.
* ci(release): repair diverged mirrors and narrow secret and token scope
Both mirrors already carry a commit the split did not make (an org bot
merged a Copilot review workflow into rtCamp/wp-phpcs and
rtCamp/wp-phpstan on 2026-08-13). The release refuses to fast-forward
over that, so the next tag would fail before reaching Packagist, and the
only way out was a force push that also mints a throwaway tag.
- release-php: add a resync_branch dispatch input that forces just the
mirror branch back onto the split and pushes no tag, and say exactly
that in the error when a release does not fast-forward.
- release-php: reference the deploy keys by name instead of
secrets[matrix.secret_name], which hands the job the whole secrets
context, and check the secret name before the indirect lookup.
- split-npm-packages: grant contents: write to the split job only.
* chore(composer): add Packagist metadata to wp-phpcs and wp-phpstan
Both packages are about to be submitted to Packagist from their split
mirrors, which are read-only. Point homepage, support.issues and
support.source at the monorepo so the Packagist page sends issues and
contributions to the right place, and name rtCamp as the author.
* fix(detect-changes): add --strict and randomise the GitHub output delimiter
A failed git diff counted as zero changes, which skipped every job gated
on the counts and left the run green. rtCamp/wp-shared-workflows works
around it by grepping stderr. --strict (detectChanges({ strict: true }))
now exits 1 with a DetectChangesError instead; it is off by default so
existing callers see no change, and the stderr keeps the 'git diff
failed' phrase the shared workflow matches.
Multi-line outputs used the fixed heredoc delimiter EOF_WP_TOOLING, but
the file list comes from the pull request: a file named EOF_WP_TOOLING
followed by one named php-count=0 closed the heredoc early and overrode
the real count. Each output now gets a random delimiter that no value
line may equal. coverage-gate shares the formatter and gets the same fix.
New tests run detect-changes against real git repositories (pull request
base, push before-SHA, new-branch fallback, explicit base, soft and
strict failure) and pin the forged-output case.
* fix(scaffolds): install the @rtCamp config packages from git, not npm
lint/eslint, lint/stylelint and setup/tailwind reported
@rtcamp/eslint-config, @rtcamp/stylelint-config and
@rtcamp/tailwind-config at ^0.1.0. None of the three is on the npm
registry (each returns 404, and the packages are at 1.0.0), so the
reported install failed with E404, and features --enable tailwind
--record-deps wrote that spec into package.json, breaking the project's
next npm install.
Use the git specs the theme and plugin skeletons already install from
(github:rtCamp/wp-tooling#npm/<package>). Verified in a scratch project:
the ^0.1.0 spec fails with E404 and the git spec installs.
* test(features): cover the features CLI end to end and fix two report bugs
The features command (also embedded by the theme init through
runFeatures) had 38% line coverage: nothing exercised argument parsing,
status output, the human report, the interactive flow or the JSON error
path. The new suites run it against the bundled Tailwind feature in
throwaway projects (status, enable, --record-deps, --dry-run, disable
with and without --force, unknown ids, prompts, cancellation, a failing
change) and against a mocked npm for the install success and failure
reports.
They found two bugs, fixed here:
- after a failed npm install, the retry commands put runtime
dependencies under --save-dev;
- a failed interactive change read 'Failed to enabling <id>'.
* test(add): cover the human report sections and the interactive wizard
The add command sat at 58% line coverage: the interactive wizard
(prompting for missing inputs, confirm, spinner, cancel, dry run) and
most human report sections (composer installs, secrets, wiring,
scaffolded tests, skipped files, warnings, the available-scaffolds list
for an unknown id) never ran in tests. The new suite drives them with
the real Wizard and stubbed prompts.
* test(init): cover the FeatureApi helpers skeleton feature hooks rely on
The theme's Tailwind toggle flips a PHP define through readDefine and
setDefine, and its HMR toggle edits .env.local through readEnv and
setEnv; none of those, nor writeFlag or hasDep, had a test. The new suite
pins reading and writing, that every mutation's journal entry restores
exactly what it changed (including directories a write created), that
remove refuses directories, and that paths cannot leave the project.
Fixes what it found: the key and define name were interpolated into a
regular expression, so a name containing a metacharacter such as '.'
matched other lines. Both are now escaped.
* test: cover manage-mode flags, list CLI errors and the Tailwind webpack hooks
- init manage mode driven by flags, the way CI and AI callers run it
(--features, --enable, --disable, --yes alone refused, undeclared keys
rejected), plus the read-only status view (drift, unknown state,
retired keys);
- wp-tooling list: space-separated flag forms, argument errors, the
empty table, and a registry that fails to load, in plain and --json
output;
- tailwind-config: GenerateTailwindThemePlugin.apply(), which wires the
run, watchRun (skip rebuilds that did not touch theme.json) and
afterEmit hooks. Its functions go from 60% to 100% covered.
* docs(changelog): restore the wp/cli description escaping note
The merge from main kept the older wording and dropped the entry for the wp/cli description fix that #70 shipped.
* docs(examples): install @rtcamp/eslint-config at ^1.0.0
The package publishes to npm as 1.0.0, and ^0.1.0 only matches versions below 0.2.0.
* fix(ci): export DetectChangesError from @rtcamp/wp-tooling/ci
The class was exported from src/ci/detect-changes.js but not from the ci barrel, so consumers of the documented @rtcamp/wp-tooling/ci entry point could not catch it by type. Adds the export and a test next to the existing GateError one.
* docs(changelog): separate the Unreleased sections
---------
Co-authored-by: Aditya Singh <adityasinghboss1234@gmail.com>
Co-authored-by: Anurag Vasanwala <75766877+AnuragVasanwala@users.noreply.github.com>
* fix(scaffolds): harden generation and tooling
* feat(scaffolds)!: target rtcamp/wp-primitives ^2.0
wp-framework is renamed to wp-primitives in 2.0.0 (rtCamp/wp-primitives#98).
- composer deps and WPPrimitives namespace across templates, tests, snippets
- docs/wp-framework-contract.md renamed to docs/wp-primitives-contract.md
- block JS keeps WordPress spacing; docblock and CHANGELOG follow-ups
* ci: lint and test every pull request and push to main
Nothing ran the suites on a pull request, while every merge to main is
split straight onto the npm/* branches that the skeletons and the shared
workflows install from. A broken merge therefore reached new installs
with no gate in between.
The new workflow runs every workspace lint and Jest suite with coverage
thresholds on Node 22.19 (the engines floor) and 24, and installs and
tests each composer package standalone, the way it ships after the
subtree split, on PHP 8.2, 8.3 and 8.4.
* ci(release): repair diverged mirrors and narrow secret and token scope
Both mirrors already carry a commit the split did not make (an org bot
merged a Copilot review workflow into rtCamp/wp-phpcs and
rtCamp/wp-phpstan on 2026-08-13). The release refuses to fast-forward
over that, so the next tag would fail before reaching Packagist, and the
only way out was a force push that also mints a throwaway tag.
- release-php: add a resync_branch dispatch input that forces just the
mirror branch back onto the split and pushes no tag, and say exactly
that in the error when a release does not fast-forward.
- release-php: reference the deploy keys by name instead of
secrets[matrix.secret_name], which hands the job the whole secrets
context, and check the secret name before the indirect lookup.
- split-npm-packages: grant contents: write to the split job only.
* chore(composer): add Packagist metadata to wp-phpcs and wp-phpstan
Both packages are about to be submitted to Packagist from their split
mirrors, which are read-only. Point homepage, support.issues and
support.source at the monorepo so the Packagist page sends issues and
contributions to the right place, and name rtCamp as the author.
* fix(detect-changes): add --strict and randomise the GitHub output delimiter
A failed git diff counted as zero changes, which skipped every job gated
on the counts and left the run green. rtCamp/wp-shared-workflows works
around it by grepping stderr. --strict (detectChanges({ strict: true }))
now exits 1 with a DetectChangesError instead; it is off by default so
existing callers see no change, and the stderr keeps the 'git diff
failed' phrase the shared workflow matches.
Multi-line outputs used the fixed heredoc delimiter EOF_WP_TOOLING, but
the file list comes from the pull request: a file named EOF_WP_TOOLING
followed by one named php-count=0 closed the heredoc early and overrode
the real count. Each output now gets a random delimiter that no value
line may equal. coverage-gate shares the formatter and gets the same fix.
New tests run detect-changes against real git repositories (pull request
base, push before-SHA, new-branch fallback, explicit base, soft and
strict failure) and pin the forged-output case.
* fix(scaffolds): install the @rtCamp config packages from git, not npm
lint/eslint, lint/stylelint and setup/tailwind reported
@rtcamp/eslint-config, @rtcamp/stylelint-config and
@rtcamp/tailwind-config at ^0.1.0. None of the three is on the npm
registry (each returns 404, and the packages are at 1.0.0), so the
reported install failed with E404, and features --enable tailwind
--record-deps wrote that spec into package.json, breaking the project's
next npm install.
Use the git specs the theme and plugin skeletons already install from
(github:rtCamp/wp-tooling#npm/<package>). Verified in a scratch project:
the ^0.1.0 spec fails with E404 and the git spec installs.
* test(features): cover the features CLI end to end and fix two report bugs
The features command (also embedded by the theme init through
runFeatures) had 38% line coverage: nothing exercised argument parsing,
status output, the human report, the interactive flow or the JSON error
path. The new suites run it against the bundled Tailwind feature in
throwaway projects (status, enable, --record-deps, --dry-run, disable
with and without --force, unknown ids, prompts, cancellation, a failing
change) and against a mocked npm for the install success and failure
reports.
They found two bugs, fixed here:
- after a failed npm install, the retry commands put runtime
dependencies under --save-dev;
- a failed interactive change read 'Failed to enabling <id>'.
* test(add): cover the human report sections and the interactive wizard
The add command sat at 58% line coverage: the interactive wizard
(prompting for missing inputs, confirm, spinner, cancel, dry run) and
most human report sections (composer installs, secrets, wiring,
scaffolded tests, skipped files, warnings, the available-scaffolds list
for an unknown id) never ran in tests. The new suite drives them with
the real Wizard and stubbed prompts.
* test(init): cover the FeatureApi helpers skeleton feature hooks rely on
The theme's Tailwind toggle flips a PHP define through readDefine and
setDefine, and its HMR toggle edits .env.local through readEnv and
setEnv; none of those, nor writeFlag or hasDep, had a test. The new suite
pins reading and writing, that every mutation's journal entry restores
exactly what it changed (including directories a write created), that
remove refuses directories, and that paths cannot leave the project.
Fixes what it found: the key and define name were interpolated into a
regular expression, so a name containing a metacharacter such as '.'
matched other lines. Both are now escaped.
* test: cover manage-mode flags, list CLI errors and the Tailwind webpack hooks
- init manage mode driven by flags, the way CI and AI callers run it
(--features, --enable, --disable, --yes alone refused, undeclared keys
rejected), plus the read-only status view (drift, unknown state,
retired keys);
- wp-tooling list: space-separated flag forms, argument errors, the
empty table, and a registry that fails to load, in plain and --json
output;
- tailwind-config: GenerateTailwindThemePlugin.apply(), which wires the
run, watchRun (skip rebuilds that did not touch theme.json) and
afterEmit hooks. Its functions go from 60% to 100% covered.
* docs(changelog): restore the wp/cli description escaping note
The merge from main kept the older wording and dropped the entry for the wp/cli description fix that #70 shipped.
* docs(examples): install @rtcamp/eslint-config at ^1.0.0
The package publishes to npm as 1.0.0, and ^0.1.0 only matches versions below 0.2.0.
* fix(ci): export DetectChangesError from @rtcamp/wp-tooling/ci
The class was exported from src/ci/detect-changes.js but not from the ci barrel, so consumers of the documented @rtcamp/wp-tooling/ci entry point could not catch it by type. Adds the export and a test next to the existing GateError one.
* docs(changelog): separate the Unreleased sections
---------
Co-authored-by: Aditya Singh <adityasinghboss1234@gmail.com>
Co-authored-by: Anurag Vasanwala <75766877+AnuragVasanwala@users.noreply.github.com>
* fix(scaffolds): harden generation and tooling
* feat(scaffolds)!: target rtcamp/wp-primitives ^2.0
wp-framework is renamed to wp-primitives in 2.0.0 (rtCamp/wp-primitives#98).
- composer deps and WPPrimitives namespace across templates, tests, snippets
- docs/wp-framework-contract.md renamed to docs/wp-primitives-contract.md
- block JS keeps WordPress spacing; docblock and CHANGELOG follow-ups
* ci: lint and test every pull request and push to main
Nothing ran the suites on a pull request, while every merge to main is
split straight onto the npm/* branches that the skeletons and the shared
workflows install from. A broken merge therefore reached new installs
with no gate in between.
The new workflow runs every workspace lint and Jest suite with coverage
thresholds on Node 22.19 (the engines floor) and 24, and installs and
tests each composer package standalone, the way it ships after the
subtree split, on PHP 8.2, 8.3 and 8.4.
* ci(release): repair diverged mirrors and narrow secret and token scope
Both mirrors already carry a commit the split did not make (an org bot
merged a Copilot review workflow into rtCamp/wp-phpcs and
rtCamp/wp-phpstan on 2026-08-13). The release refuses to fast-forward
over that, so the next tag would fail before reaching Packagist, and the
only way out was a force push that also mints a throwaway tag.
- release-php: add a resync_branch dispatch input that forces just the
mirror branch back onto the split and pushes no tag, and say exactly
that in the error when a release does not fast-forward.
- release-php: reference the deploy keys by name instead of
secrets[matrix.secret_name], which hands the job the whole secrets
context, and check the secret name before the indirect lookup.
- split-npm-packages: grant contents: write to the split job only.
* chore(composer): add Packagist metadata to wp-phpcs and wp-phpstan
Both packages are about to be submitted to Packagist from their split
mirrors, which are read-only. Point homepage, support.issues and
support.source at the monorepo so the Packagist page sends issues and
contributions to the right place, and name rtCamp as the author.
* fix(detect-changes): add --strict and randomise the GitHub output delimiter
A failed git diff counted as zero changes, which skipped every job gated
on the counts and left the run green. rtCamp/wp-shared-workflows works
around it by grepping stderr. --strict (detectChanges({ strict: true }))
now exits 1 with a DetectChangesError instead; it is off by default so
existing callers see no change, and the stderr keeps the 'git diff
failed' phrase the shared workflow matches.
Multi-line outputs used the fixed heredoc delimiter EOF_WP_TOOLING, but
the file list comes from the pull request: a file named EOF_WP_TOOLING
followed by one named php-count=0 closed the heredoc early and overrode
the real count. Each output now gets a random delimiter that no value
line may equal. coverage-gate shares the formatter and gets the same fix.
New tests run detect-changes against real git repositories (pull request
base, push before-SHA, new-branch fallback, explicit base, soft and
strict failure) and pin the forged-output case.
* fix(scaffolds): install the @rtCamp config packages from git, not npm
lint/eslint, lint/stylelint and setup/tailwind reported
@rtcamp/eslint-config, @rtcamp/stylelint-config and
@rtcamp/tailwind-config at ^0.1.0. None of the three is on the npm
registry (each returns 404, and the packages are at 1.0.0), so the
reported install failed with E404, and features --enable tailwind
--record-deps wrote that spec into package.json, breaking the project's
next npm install.
Use the git specs the theme and plugin skeletons already install from
(github:rtCamp/wp-tooling#npm/<package>). Verified in a scratch project:
the ^0.1.0 spec fails with E404 and the git spec installs.
* test(features): cover the features CLI end to end and fix two report bugs
The features command (also embedded by the theme init through
runFeatures) had 38% line coverage: nothing exercised argument parsing,
status output, the human report, the interactive flow or the JSON error
path. The new suites run it against the bundled Tailwind feature in
throwaway projects (status, enable, --record-deps, --dry-run, disable
with and without --force, unknown ids, prompts, cancellation, a failing
change) and against a mocked npm for the install success and failure
reports.
They found two bugs, fixed here:
- after a failed npm install, the retry commands put runtime
dependencies under --save-dev;
- a failed interactive change read 'Failed to enabling <id>'.
* test(add): cover the human report sections and the interactive wizard
The add command sat at 58% line coverage: the interactive wizard
(prompting for missing inputs, confirm, spinner, cancel, dry run) and
most human report sections (composer installs, secrets, wiring,
scaffolded tests, skipped files, warnings, the available-scaffolds list
for an unknown id) never ran in tests. The new suite drives them with
the real Wizard and stubbed prompts.
* test(init): cover the FeatureApi helpers skeleton feature hooks rely on
The theme's Tailwind toggle flips a PHP define through readDefine and
setDefine, and its HMR toggle edits .env.local through readEnv and
setEnv; none of those, nor writeFlag or hasDep, had a test. The new suite
pins reading and writing, that every mutation's journal entry restores
exactly what it changed (including directories a write created), that
remove refuses directories, and that paths cannot leave the project.
Fixes what it found: the key and define name were interpolated into a
regular expression, so a name containing a metacharacter such as '.'
matched other lines. Both are now escaped.
* test: cover manage-mode flags, list CLI errors and the Tailwind webpack hooks
- init manage mode driven by flags, the way CI and AI callers run it
(--features, --enable, --disable, --yes alone refused, undeclared keys
rejected), plus the read-only status view (drift, unknown state,
retired keys);
- wp-tooling list: space-separated flag forms, argument errors, the
empty table, and a registry that fails to load, in plain and --json
output;
- tailwind-config: GenerateTailwindThemePlugin.apply(), which wires the
run, watchRun (skip rebuilds that did not touch theme.json) and
afterEmit hooks. Its functions go from 60% to 100% covered.
* docs(changelog): restore the wp/cli description escaping note
The merge from main kept the older wording and dropped the entry for the wp/cli description fix that #70 shipped.
* docs(examples): install @rtcamp/eslint-config at ^1.0.0
The package publishes to npm as 1.0.0, and ^0.1.0 only matches versions below 0.2.0.
* fix(ci): export DetectChangesError from @rtcamp/wp-tooling/ci
The class was exported from src/ci/detect-changes.js but not from the ci barrel, so consumers of the documented @rtcamp/wp-tooling/ci entry point could not catch it by type. Adds the export and a test next to the existing GateError one.
* docs(changelog): separate the Unreleased sections
---------
Co-authored-by: Aditya Singh <adityasinghboss1234@gmail.com>
Co-authored-by: Anurag Vasanwala <75766877+AnuragVasanwala@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What this PR does
Moves every scaffold, test, doc and skill from
rtcamp/wp-framework^1.0tortcamp/wp-primitives^2.0(namespacertCamp\WPPrimitives\), following rtCamp/wp-primitives#98. It also brings over the scaffold fixes from #63; that PR keeps its VIP scaffolds andlens.Closes
Closes #69
Changes
fix(scaffolds): harden generation and toolingblock.json.base_path.feat(scaffolds)!: target rtcamp/wp-primitives ^2.0@linkacross scaffolds, tests and snippets.docs/wp-framework-contract.mdis renamed todocs/wp-primitives-contract.md.How I verified
npm run checkpasses: 1,288 tests."rtcamp/wp-primitives":"^2.0", thertCamp\WPPrimitives\import, andNo syntax errors detected.560b189) has 0 rtCampWP and rtCampWP-Basic errors across 84 files.Reviewer notes
features-plugin-skeleton(which useswp-prettier) new blocks neednpm run lint:js:fix.