Skip to content

Go-live fixes: CI, release, security and scaffold installs - #72

Merged
AnuragVasanwala merged 17 commits into
mainfrom
chore/go-live-fixes
Oct 1, 2026
Merged

AnuragVasanwala merged 17 commits into
mainfrom
chore/go-live-fixes

Conversation

@aryanjasala

Copy link
Copy Markdown
Member

Stacked on #70. Merge after #70: once #70 merges and its branch is deleted, GitHub retargets this PR to main.

Fixes found while preparing the public release. The PHPCS scaffold fix is left to #70, which covers the same bug.

CI and release

  • Lint and test every pull request and push to main (e1e7331). Nothing ran the suites before, while every merge to main is split straight onto the npm/* branches that the skeletons and the shared workflows install from. Runs every workspace lint and Jest suite with coverage thresholds on Node 22.19 and 24, and tests each Composer package standalone on PHP 8.2, 8.3 and 8.4.
  • Repair the diverged mirrors and narrow token scope (182a9f1). rtCamp/wp-phpcs and rtCamp/wp-phpstan carry a commit the split did not make, so the next release tag would fail to push. Adds a resync_branch dispatch input that resets the mirror branch without minting a tag, references the deploy keys by name instead of handing the job the whole secrets context, and grants contents: write to the npm split job only.
  • Packagist metadata for rtcamp/wp-phpcs and rtcamp/wp-phpstan (dd2d79f): homepage, issues and source point at this repo.

Security

  • detect-changes output could be forged from a pull request (31323d9). Multi-line outputs used the fixed heredoc delimiter EOF_WP_TOOLING, so a PR adding a file named EOF_WP_TOOLING followed by one named php-count=0 could override the real count and skip the PHP jobs. Each output now gets a random delimiter; coverage-gate shares the formatter and gets the same fix.
  • Same commit: detect-changes --strict makes a failed git diff exit 1 instead of reporting zero changes and leaving the run green. Off by default, so existing callers see no change.

Scaffold fixes

  • The @rtcamp/*-config packages were not installable (a540b21). lint/eslint, lint/stylelint and setup/tailwind reported ^0.1.0, which is not on the npm registry (404), and features --enable tailwind --record-deps wrote that spec into package.json, breaking the next npm install. They now use the git specs the skeletons already install from (github:rtCamp/wp-tooling#npm/<package>).

Tests, and the bugs they found

  • features CLI end to end (e439903). Fixes: retry commands after a failed npm install put runtime dependencies under --save-dev, and a failed interactive change read "Failed to enabling".
  • add report sections and the interactive wizard (5a2533c).
  • FeatureApi helpers the skeleton feature hooks rely on (62be651). Fixes: define and env key names were interpolated into a regular expression, so a name containing . matched other lines.
  • Init manage mode driven by flags, CLI error paths and the Tailwind webpack hooks (b076fe2).

Testing

  • npm run check: lint clean, 82 suites, 1,371 tests passing (Node 24.12)
  • PHP packages: rtcamp/wp-phpcs 3 tests, rtcamp/wp-phpstan 2 tests, passing
  • @rtcamp/wp-tooling CLI line coverage 88% -> 93% (measured on the same commits against main)

Adi-ty and others added 11 commits October 1, 2026 16:01
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
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.
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.
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.
…imiter

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.
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.
…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>'.
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.
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.
…ck 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.
Base automatically changed from v1.0.0/task/wp-primitives-rename to main October 1, 2026 17:06

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

The new error class is missing from the public CI barrel, and shipped setup documentation retains an invalid dependency specification.

Review effort: Balanced
Findings: 1 Medium severity · 1 Low severity

Open (2)
What changed in this PR

Hardens release readiness across CI, security, package splitting, scaffold dependencies, and CLI behavior.

Changes:

  • Adds comprehensive Node/PHP CI and safer release workflows.
  • Secures GitHub output handling and strict change detection.
  • Fixes scaffold dependencies, CLI reporting, regex handling, and expands tests.
File Description
node-packages/​wp-tooling/​tests/​scaffolds/​list-cli.test.js Tests list CLI paths.
node-packages/​wp-tooling/​tests/​scaffolds/​features-cli.test.js Tests feature CLI flows.
node-packages/​wp-tooling/​tests/​scaffolds/​features-cli-install.test.js Tests npm installation reporting.
node-packages/​wp-tooling/​tests/​scaffolds/​add-cli.test.js Tests add reports and wizard.
node-packages/​wp-tooling/​tests/​init/​manage-flags.test.js Tests flag-driven management.
node-packages/​wp-tooling/​tests/​init/​feature-api.test.js Tests feature API helpers.
node-packages/​wp-tooling/​tests/​ci/​detect-changes.test.js Updates delimiter assertions.
node-packages/​wp-tooling/​tests/​ci/​detect-changes-git.test.js Tests strict mode and output security.
node-packages/​wp-tooling/​src/​scaffolds/​features.js Corrects retry commands and messages.
node-packages/​wp-tooling/​src/​init/​features.js Escapes regex literals.
node-packages/​wp-tooling/​src/​ci/​detect-changes.js Adds strict mode and random delimiters.
node-packages/​wp-tooling/​skills/​setup/​SKILL.md Uses GitHub ESLint config spec.
node-packages/​wp-tooling/​scaffolds/​setup/​tailwind/​scaffold.json Fixes Tailwind config dependency.
node-packages/​wp-tooling/​scaffolds/​setup/​claude-skills/​templates/​setup-SKILL.md Updates generated setup guidance.
node-packages/​wp-tooling/​scaffolds/​lint/​stylelint/​scaffold.json Fixes Stylelint config dependency.
node-packages/​wp-tooling/​scaffolds/​lint/​eslint/​scaffold.json Fixes ESLint config dependency.
node-packages/​wp-tooling/​CHANGELOG.md Documents fixes and strict mode.
node-packages/​tailwind-config/​tests/​GenerateTailwindThemePlugin.test.js Tests webpack lifecycle hooks.
composer-packages/​phpstan/​composer.json Adds Packagist metadata.
composer-packages/​phpstan/​CHANGELOG.md Documents metadata.
composer-packages/​phpcs/​composer.json Adds Packagist metadata.
composer-packages/​phpcs/​CHANGELOG.md Documents metadata.
AGENTS.md Documents the new CI workflow.
.github/​workflows/​split-npm-packages.yml Narrows write permissions.
.github/​workflows/​release-php.yml Adds mirror resynchronization and scoped secrets.
.github/​workflows/​ci.yml Adds Node and PHP CI matrices.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

runCli,
takeValue,
formatGithubLine,
DetectChangesError,
The merge from main kept the older wording and dropped the entry for the wp/cli description fix that #70 shipped.
The package publishes to npm as 1.0.0, and ^0.1.0 only matches versions below 0.2.0.
Copilot AI balanced review requested due to automatic review settings October 1, 2026 17:16
AnuragVasanwala and others added 3 commits October 1, 2026 22:46
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.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

The public error export is incomplete, one install example remains broken, and CI does not enforce the claimed workspace coverage thresholds.

Review effort: Balanced
Findings: 1 Medium severity · 1 Low severity

Open (2)
Resolved since last review (1)
Previously missed (1)

In code that hasn't changed since last review

Medium severity Enforce coverage thresholds for every workspace

.github/​workflows/​ci.yml:57

This command collects coverage for every workspace, but it does not enforce a threshold for every suite as the PR description and workflow comment claim. Only node-packages/wp-tooling/jest.config.js defines coverageThreshold; the ESLint config has no threshold, and the Stylelint/Tailwind packages have no Jest config or package-level threshold, so coverage regressions in three workspaces still pass CI. Add thresholds for those workspaces or narrow the stated guarantee.

Copilot AI balanced review requested due to automatic review settings October 1, 2026 17:19
@AnuragVasanwala
AnuragVasanwala merged commit fd25e77 into main Oct 1, 2026
12 checks passed
@AnuragVasanwala
AnuragVasanwala deleted the chore/go-live-fixes branch October 1, 2026 17:21
github-actions Bot pushed a commit that referenced this pull request Oct 1, 2026
* 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>
github-actions Bot pushed a commit that referenced this pull request Oct 1, 2026
* 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>

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🔵 Needs a closer look

The broad release, credential, CI, and security-sensitive workflow changes warrant final human validation.

Review effort: Balanced
Findings: 1 Medium severity

Open (1)
Resolved since last review (1)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants