Skip to content

[codex] fix metadata sync fallback and docs alignment#1014

Merged
ashleyshaw merged 2 commits into
developfrom
fix/metadata-governance-sync
Jun 19, 2026
Merged

[codex] fix metadata sync fallback and docs alignment#1014
ashleyshaw merged 2 commits into
developfrom
fix/metadata-governance-sync

Conversation

@ashleyshaw

@ashleyshaw ashleyshaw commented Jun 19, 2026

Copy link
Copy Markdown
Member

file_type: "pr-template"
title: "PR Template - BUG"
description: "Pull request template for BUG changes"
version: "1.0.2"
last_updated: "2026-06-18"
category: "github-templates"

Bugfix Pull Request

This repository enforces changelog, release, and label automation for all PRs and issues.
See the organisation-wide Automation Governance & Release Strategy for required rules.

Linked issues

Fixes #1011

Context

  • Severity/Impact: Medium
  • Affected versions/environments: GitHub issue and PR metadata automation in .github/workflows/project-meta-sync.yml and .github/workflows/metadata-governance.yml

Reproduction

  • Steps: 1) Open an issue or PR without canonical labels, 2) add labels after creation, 3) observe that project fields can remain blank.
  • Expected vs Actual: project fields should refresh from label changes and safe fallbacks; previously they could stay incomplete until a later event or never catch up.

Root Cause

  • project-meta-sync.yml only reacted to a narrower event set and depended on a brittle label snapshot, so late labels could leave Status, Priority, Type, and dates incomplete.
  • derive-project-fields.cjs did not previously backfill missing project values from title/body/branch context.

Fix Summary

  • Reworked the workflow to rerun on issue and PR label changes and to read labels directly from the event payload.
  • Added safe fallback derivation for Status, Priority, Type, Effort, Start date, and Target date.
  • Updated docs, the deprecated agent shim, and the project config guide to match the live contract.

Verification

  • Tests added/updated to cover the bug
  • Manual verification steps (browsers/devices)
  • Negative/edge cases checked

Risk & Rollback

  • Risk level: Low
  • Rollback plan: revert the commit that updates project-meta-sync.yml, derive-project-fields.cjs, and the related docs/tests.

Changelog

Added

Changed

  • Tightened project metadata automation so issue and PR project fields refresh when labels change.

Fixed

  • Fixed empty project fields when canonical labels or issue type intent arrive after creation.

Removed

  • Removed reliance on a push-triggered label snapshot for project metadata sync.

Checklist (Global DoD / PR)

  • All AC met and demonstrated
  • Tests added/updated (unit/E2E as appropriate)
  • Accessibility checklist completed (where relevant):
    • Semantic HTML and heading order verified
    • Keyboard navigation and visible focus states verified
    • ARIA used only where needed
    • Contrast and non-colour cues reviewed (WCAG 2.2 AA or higher)
  • Docs/readme/changelog updated (if user-facing)
  • Security checklist completed (where relevant):
    • Untrusted input validated and sanitised
    • Output escaped for its rendering context
    • Privileged actions enforce nonce and capability checks
    • No secrets/sensitive data introduced; OWASP risks reviewed
  • Code/design reviews approved
  • CI green; linked issues closed; release notes prepared (if shipping)

@github-actions

github-actions Bot commented Jun 19, 2026

Copy link
Copy Markdown
Contributor

✅ Template check passed after update. Thanks for fixing the PR description.

@coderabbitai

coderabbitai Bot commented Jun 19, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

@ashleyshaw, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 54 minutes and 28 seconds. Learn how PR review limits work.

Your organization has run out of usage credits. Purchase more credits in the billing tab to continue.

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based credits.

🚦 How do rate limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan refill rate.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, the refill rate gradually slows as usage increases. The highest same-day bursts are limited more strictly.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Organization UI (inherited)

Review profile: CHILL

Plan: Pro

Run ID: 9a91994c-856b-4284-813c-6e34ac0b652a

📥 Commits

Reviewing files that changed from the base of the PR and between 31f66ac and 5a1f6f8.

📒 Files selected for processing (5)
  • docs/AUTOMATION.md
  • docs/CANONICAL_CONFIGS_GUIDE.md
  • docs/ISSUE_CREATION_GUIDE.md
  • docs/ISSUE_FIELDS.md
  • docs/WORKFLOW_COORDINATION.md
📝 Walkthrough

Walkthrough

Removes the push trigger from project-meta-sync.yml and switches label collection from the gh CLI to an actions/github-script event-payload read. Adds content-based type/priority inference to derive-project-fields.cjs via regex keyword maps, renames main() to run(), expands exports, and updates tests and documentation throughout.

Changes

project-meta-sync label-event & inference overhaul

Layer / File(s) Summary
Workflow trigger, label collection, and env variable wiring
.github/workflows/project-meta-sync.yml
Removes the push trigger, expands pull_request event types to include synchronize and ready_for_review, replaces the gh CLI label collection step with an actions/github-script event-payload read, and adds ITEM_TITLE, ITEM_BODY, and PR_HEAD_REF env vars to the derive step.
Content-based type/priority inference in derive-project-fields.cjs
scripts/agents/includes/derive-project-fields.cjs
Introduces inferTypeFromContext, inferPriorityFromContext, and inferMappedValueFromText backed by branch-prefix and keyword maps; updates deriveProjectFieldValues to accept title, body, headRef and use the new helpers with event-driven fallbacks; renames main() to run() and expands module.exports.
Unit and integration tests
scripts/agents/includes/__tests__/derive-project-fields.test.js, scripts/validation/__tests__/project-meta-sync.test.js
Adds tests for label-absent PR default fallback, content-based inference, and a run() script-mode integration test against a temp GITHUB_OUTPUT file; adds a workflow contract suite asserting the push trigger removal and github-script payload extraction.
Docs, agent, and instructions updates
agents/project-meta-sync.agent.md, docs/AUTOMATION.md, docs/CANONICAL_CONFIGS_GUIDE.md, docs/GITHUB_PROJECT_OPERATIONS_SPEC.md, docs/ISSUE_CREATION_GUIDE.md, docs/ISSUE_FIELDS.md, docs/WORKFLOW_COORDINATION.md, instructions/project-meta-sync.instructions.md
Updates all documentation and instructions to reflect the removed push trigger, label-event re-processing contract, content-based field inference fallbacks, and updated Start date/Target date write scope.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • lightspeedwp/.github#974: Modifies the same project-meta-sync.yml workflow and derive-project-fields.cjs derivation logic, overlapping directly with the status/priority/type and date-handling code paths changed here.

Suggested labels

area:ci, area:scripts, area:documentation, lang:js, lang:yaml, test, type:bug, meta:needs-changelog

Suggested reviewers

  • krugazul
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title '[codex] fix metadata sync fallback and docs alignment' clearly summarises the main change: adding fallback derivation and aligning documentation for metadata synchronisation.
Description check ✅ Passed The PR description follows the bug template, includes all key sections (context, root cause, fix summary, verification, risk/rollback, changelog), and comprehensively details the metadata sync improvements.
Linked Issues check ✅ Passed The PR fully addresses all five acceptance criteria from issue #1011: delivers consistent project fields, implements label-change triggers, maintains assignee/milestone metadata, adds comprehensive tests, and updates all documentation.
Out of Scope Changes check ✅ Passed All changes directly support the metadata automation objectives: workflow trigger fixes, fallback derivation logic, test coverage expansion, and aligned documentation—with no unrelated modifications introduced.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/metadata-governance-sync

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions

github-actions Bot commented Jun 19, 2026

Copy link
Copy Markdown
Contributor

🎨 Mermaid Diagram Validation

✅ All Mermaid diagram checks passed.

Check Result
✅ Syntax (diagram type, direction, bracket matching) Passed
✅ Accessibility (accTitle / accDescr present) Passed
✅ Colour contrast (WCAG 2.2 AA ≥ 4.5:1) Passed

@github-actions

Copy link
Copy Markdown
Contributor

Metadata governance

@github-actions github-actions Bot added status:needs-review Awaiting code review type:bug Bug or defect priority:normal Default priority area:ci Build and CI pipelines area:documentation Docs & guides area:tests Test suites & harnesses area:scripts Scripts & tooling lang:js JavaScript/TypeScript lang:md Markdown content/docs type:chore Chore / small hygiene change meta:needs-changelog Requires a changelog entry before merge labels Jun 19, 2026
@coderabbitai coderabbitai Bot requested a review from krugazul June 19, 2026 10:17

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Code Review

This pull request updates the project metadata synchronization workflow to trigger on issue and pull request label changes, and enhances the derive-project-fields.cjs script to infer issue types and priorities from titles, bodies, and branch prefixes when labels are missing. Feedback on the changes highlights potential short-circuiting bugs in inferMappedValueFromText and inferTypeFromContext when matched keywords or branch prefixes are not mapped in the configuration, as well as a recommendation to use optional chaining on cfg to prevent runtime crashes.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment on lines +117 to +125
function inferMappedValueFromText(text, rules, mapping) {
const haystack = String(text || "");
for (const rule of rules) {
if (rule.patterns.some((pattern) => pattern.test(haystack))) {
return mapping?.[rule.label] || "";
}
}
return "";
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

high

If a keyword matches but its corresponding label is not mapped in the configuration, mapping?.[rule.label] will be undefined. This causes the function to return "" immediately, which short-circuits the loop and prevents subsequent rules from being evaluated. We should only return the mapped value if it is defined.

function inferMappedValueFromText(text, rules, mapping) {
  const haystack = String(text || "");
  for (const rule of rules) {
    if (rule.patterns.some((pattern) => pattern.test(haystack))) {
      const mapped = mapping?.[rule.label];
      if (mapped) return mapped;
    }
  }
  return "";
}

Comment on lines +137 to +142
const lowerHeadRef = String(headRef || "").toLowerCase();
for (const [prefix, typeLabel] of Object.entries(BRANCH_PREFIX_TYPE_MAP)) {
if (lowerHeadRef.startsWith(prefix)) {
return mappings.Type?.[typeLabel] || "";
}
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

high

If the branch prefix matches but the corresponding typeLabel is not mapped in mappings.Type, returning "" immediately short-circuits the function and prevents checking the title or body keywords. We should only return the mapped value if it is defined.

  const lowerHeadRef = String(headRef || "").toLowerCase();
  for (const [prefix, typeLabel] of Object.entries(BRANCH_PREFIX_TYPE_MAP)) {
    if (lowerHeadRef.startsWith(prefix)) {
      const mapped = mappings.Type?.[typeLabel];
      if (mapped) return mapped;
    }
  }

Comment on lines 199 to 200
const mappings = cfg.project_field_mappings || {};
const orgFields = cfg.organization_issue_fields || {};

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

To enforce defensive programming, we should use optional chaining when accessing properties on cfg to prevent runtime crashes if cfg is null or undefined.

  const mappings = cfg?.project_field_mappings || {};
  const orgFields = cfg?.organization_issue_fields || {};

@github-actions github-actions Bot removed the type:chore Chore / small hygiene change label Jun 19, 2026
@coderabbitai coderabbitai Bot added lang:yaml YAML config test labels Jun 19, 2026
@github-actions github-actions Bot added type:test Testing/coverage and removed test labels Jun 19, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
instructions/project-meta-sync.instructions.md (1)

8-33: ⚠️ Potential issue | 🟠 Major

Instruction file structure does not comply with required pattern.

The file is only 34 lines and contains just frontmatter plus an "Active Contract Summary" section. According to the coding guidelines for **/*.instructions.md, instruction files must include: role declaration, Overview, General Rules, Detailed Guidance, Examples, Validation, and References sections. This file is missing all of these structural elements.

Whilst the frontmatter is correct (no references: field, last_updated properly dated), and the Active Contract Summary is clear and actionable, the file fails to follow the mandatory instruction file pattern. The description notes this is "Deprecated compatibility guidance for the legacy project meta sync entrypoint," but that doesn't exempt it from the structural requirements—the guidelines apply to all instruction files.

Either expand the file to meet the required pattern, or consider whether this should be relocated to a different file type (such as documentation rather than instructions).

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@instructions/project-meta-sync.instructions.md` around lines 8 - 33, The
project-meta-sync.instructions.md file does not follow the required instruction
file pattern. Currently it only contains frontmatter and an Active Contract
Summary section, but is missing the mandatory structural elements: role
declaration, Overview, General Rules, Detailed Guidance, Examples, Validation,
and References sections. Expand the file to include all required sections with
appropriate content for the project metadata synchronization workflow, or if the
content is more suitable as documentation rather than instructions, consider
moving it to a different file type that better matches its purpose.

Source: Coding guidelines

🧹 Nitpick comments (3)
scripts/validation/__tests__/project-meta-sync.test.js (1)

1-3: ⚡ Quick win

The jsdom environment isn't needed here.

This test suite only reads YAML files and performs object assertions—no DOM manipulation in sight! The default node environment would be lighter and more appropriate.

✨ Remove the unnecessary environment directive
-/**
- * `@jest-environment` jsdom
- */
-
 const fs = require("fs");
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/validation/__tests__/project-meta-sync.test.js` around lines 1 - 3,
The `@jest-environment` jsdom directive at the top of the
project-meta-sync.test.js file is unnecessary since this test suite only reads
YAML files and performs object assertions without any DOM manipulation. Remove
the `@jest-environment` jsdom comment block to allow the test to use the default
and more lightweight node environment instead.
.github/workflows/project-meta-sync.yml (1)

92-98: 💤 Low value

Consider SHA-pinning this action for enhanced security.

The actions/github-script@v7 reference uses a mutable tag. Per workflow security guidelines, SHA-pinned actions are preferred to guard against supply-chain attacks. That said, v7 is a reasonable balance between security and maintainability for first-party GitHub actions.

The label collection logic itself looks splendid—reading directly from context.payload is cleaner and more reliable than shelling out to the gh CLI. Nice improvement! 🎉

🔒 Optional: SHA-pin the action
-        uses: actions/github-script@v7
+        uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/project-meta-sync.yml around lines 92 - 98, The
`actions/github-script@v7` action reference uses a mutable tag instead of a
specific SHA commit hash, which poses a supply-chain security risk. Replace the
version tag with a SHA-pinned reference by updating the uses field from
`actions/github-script@v7` to the full SHA commit hash of that version (e.g.,
`actions/github-script@<SHA>`). This ensures the workflow always executes the
exact intended version of the action and prevents unexpected changes from tag
reassignments.

Sources: Coding guidelines, Linters/SAST tools

scripts/agents/includes/__tests__/derive-project-fields.test.js (1)

93-131: ⚡ Quick win

Add cleanup for the temporary directory.

The test creates a temp directory but doesn't tidy up afterwards. While the OS will eventually reclaim it, explicitly cleaning up is good hygiene and prevents accumulation during repeated test runs.

🧹 Proposed fix to clean up temp directory
     const output = fs.readFileSync(outputPath, "utf8");
     expect(output).toContain("status=In review");
     expect(output).toContain("priority=Critical");
     expect(output).toContain("type=Bug");
+
+    fs.rmSync(tmpDir, { recursive: true, force: true });
   });

Alternatively, you could use afterEach or move cleanup into the finally block:

     } finally {
       for (const [key, value] of Object.entries(originalEnv)) {
         if (typeof value === "undefined") delete process.env[key];
         else process.env[key] = value;
       }
+      fs.rmSync(tmpDir, { recursive: true, force: true });
     }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/agents/includes/__tests__/derive-project-fields.test.js` around lines
93 - 131, The test creates a temporary directory using fs.mkdtempSync() at the
beginning but does not clean it up, causing directory accumulation during
repeated test runs. Add cleanup code to remove the tmpDir after the test
completes by using fs.rmSync() with the recursive option set to true in the
finally block, ensuring the temporary directory and its contents are properly
deleted after the test execution regardless of success or failure.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs/CANONICAL_CONFIGS_GUIDE.md`:
- Around line 37-39: In the section describing project metadata sync (lines
37-39 in CANONICAL_CONFIGS_GUIDE.md), add a comma before the conjunction "so" in
the compound sentence. The text currently reads "first-class signals so project
fields can catch up" but should be corrected to "first-class signals, so project
fields can catch up" to properly punctuate the join between two independent
clauses.

In `@docs/GITHUB_PROJECT_OPERATIONS_SPEC.md`:
- Around line 88-92: In the bullet point about "Start date" and "Target date"
population, locate the text "the workflow reprocesses label changes so fields
can catch up after triage" and add a comma before the word "so" to properly join
the two independent clauses. The corrected text should read "the workflow
reprocesses label changes, so fields can catch up after triage".

---

Outside diff comments:
In `@instructions/project-meta-sync.instructions.md`:
- Around line 8-33: The project-meta-sync.instructions.md file does not follow
the required instruction file pattern. Currently it only contains frontmatter
and an Active Contract Summary section, but is missing the mandatory structural
elements: role declaration, Overview, General Rules, Detailed Guidance,
Examples, Validation, and References sections. Expand the file to include all
required sections with appropriate content for the project metadata
synchronization workflow, or if the content is more suitable as documentation
rather than instructions, consider moving it to a different file type that
better matches its purpose.

---

Nitpick comments:
In @.github/workflows/project-meta-sync.yml:
- Around line 92-98: The `actions/github-script@v7` action reference uses a
mutable tag instead of a specific SHA commit hash, which poses a supply-chain
security risk. Replace the version tag with a SHA-pinned reference by updating
the uses field from `actions/github-script@v7` to the full SHA commit hash of
that version (e.g., `actions/github-script@<SHA>`). This ensures the workflow
always executes the exact intended version of the action and prevents unexpected
changes from tag reassignments.

In `@scripts/agents/includes/__tests__/derive-project-fields.test.js`:
- Around line 93-131: The test creates a temporary directory using
fs.mkdtempSync() at the beginning but does not clean it up, causing directory
accumulation during repeated test runs. Add cleanup code to remove the tmpDir
after the test completes by using fs.rmSync() with the recursive option set to
true in the finally block, ensuring the temporary directory and its contents are
properly deleted after the test execution regardless of success or failure.

In `@scripts/validation/__tests__/project-meta-sync.test.js`:
- Around line 1-3: The `@jest-environment` jsdom directive at the top of the
project-meta-sync.test.js file is unnecessary since this test suite only reads
YAML files and performs object assertions without any DOM manipulation. Remove
the `@jest-environment` jsdom comment block to allow the test to use the default
and more lightweight node environment instead.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Organization UI (inherited)

Review profile: CHILL

Plan: Pro

Run ID: bbb476da-2554-48af-9d9f-413abe3a156f

📥 Commits

Reviewing files that changed from the base of the PR and between c7267f3 and 31f66ac.

📒 Files selected for processing (12)
  • .github/workflows/project-meta-sync.yml
  • agents/project-meta-sync.agent.md
  • docs/AUTOMATION.md
  • docs/CANONICAL_CONFIGS_GUIDE.md
  • docs/GITHUB_PROJECT_OPERATIONS_SPEC.md
  • docs/ISSUE_CREATION_GUIDE.md
  • docs/ISSUE_FIELDS.md
  • docs/WORKFLOW_COORDINATION.md
  • instructions/project-meta-sync.instructions.md
  • scripts/agents/includes/__tests__/derive-project-fields.test.js
  • scripts/agents/includes/derive-project-fields.cjs
  • scripts/validation/__tests__/project-meta-sync.test.js
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: coderabbit-gate
  • GitHub Check: Mergify Merge Protections
  • GitHub Check: Summary
🧰 Additional context used
📓 Path-based instructions (13)
**/*.{md,markdown,txt,instructions.md}

📄 CodeRabbit inference engine (CLAUDE.md)

Language: Use UK English throughout (optimise, organisation, colour, behaviour).

Files:

  • docs/CANONICAL_CONFIGS_GUIDE.md
  • instructions/project-meta-sync.instructions.md
  • agents/project-meta-sync.agent.md
  • docs/AUTOMATION.md
  • docs/WORKFLOW_COORDINATION.md
  • docs/ISSUE_CREATION_GUIDE.md
  • docs/GITHUB_PROJECT_OPERATIONS_SPEC.md
  • docs/ISSUE_FIELDS.md
**/*.md

📄 CodeRabbit inference engine (AGENTS.md)

All documentation must follow Markdown formatting standards and include YAML frontmatter as specified in instructions/documentation-formats.instructions.md

Files:

  • docs/CANONICAL_CONFIGS_GUIDE.md
  • instructions/project-meta-sync.instructions.md
  • agents/project-meta-sync.agent.md
  • docs/AUTOMATION.md
  • docs/WORKFLOW_COORDINATION.md
  • docs/ISSUE_CREATION_GUIDE.md
  • docs/GITHUB_PROJECT_OPERATIONS_SPEC.md
  • docs/ISSUE_FIELDS.md
**/docs/**/*.md

⚙️ CodeRabbit configuration file

**/docs/**/*.md: Review documentation files:

  • Ensure markdown is linted and formatted per project style guides.
  • Flag illogical folder structures, file naming, or misplaced content.
  • Confirm documentation is up to date, accurate, and cross-referenced.
  • Ensure accessibility (heading hierarchy, alt text for images, UK English).

Files:

  • docs/CANONICAL_CONFIGS_GUIDE.md
  • docs/AUTOMATION.md
  • docs/WORKFLOW_COORDINATION.md
  • docs/ISSUE_CREATION_GUIDE.md
  • docs/GITHUB_PROJECT_OPERATIONS_SPEC.md
  • docs/ISSUE_FIELDS.md
**/*.instructions.md

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.instructions.md: Do not create instruction files with a 'references' frontmatter field; use inline links or footer sections instead.
Instruction files must follow the pattern: frontmatter + role declaration + Overview + General Rules + Detailed Guidance + Examples + Validation + References.

Files:

  • instructions/project-meta-sync.instructions.md
instructions/**

⚙️ CodeRabbit configuration file

instructions/**: Review portable instruction files:

  • Verify frontmatter follows the canonical pattern (file_type, version, last_updated, owners, tags, status, domain, stability).
  • Flag any references: frontmatter field — prohibited by CLAUDE.md.
  • Confirm the file has: Overview, General Rules, Detailed Guidance, Examples, Validation, and Cross-References sections.
  • Check that language is UK English throughout.

Files:

  • instructions/project-meta-sync.instructions.md
**/*.{php,js,ts,jsx,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{php,js,ts,jsx,tsx}: Follow WordPress Coding Standards for PHP files, ESLint/Prettier for JS/TS files, and PHPCS/WPCS for PHP files.
Security: Validate all input, escape all output, use nonces, never commit secrets.

Files:

  • scripts/validation/__tests__/project-meta-sync.test.js
  • scripts/agents/includes/__tests__/derive-project-fields.test.js
**/*.{js,ts,jsx,tsx,html}

📄 CodeRabbit inference engine (CLAUDE.md)

Performance: Avoid unnecessary JS, defer/lazy-load where possible, prefer native blocks.

Files:

  • scripts/validation/__tests__/project-meta-sync.test.js
  • scripts/agents/includes/__tests__/derive-project-fields.test.js
**/*.{php,js,ts}

📄 CodeRabbit inference engine (CLAUDE.md)

Do not enqueue editor-only WordPress assets on the front end (and vice versa).

Files:

  • scripts/validation/__tests__/project-meta-sync.test.js
  • scripts/agents/includes/__tests__/derive-project-fields.test.js
**/*.{php,js,css,html}

📄 CodeRabbit inference engine (AGENTS.md)

Follow WordPress Coding Standards (CSS, HTML, JavaScript, PHP) and inline-documentation standards at all times

Files:

  • scripts/validation/__tests__/project-meta-sync.test.js
  • scripts/agents/includes/__tests__/derive-project-fields.test.js
**/*.{js,ts,jsx,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

JavaScript and TypeScript files must follow linting standards defined in instructions/languages.instructions.md, including JSDoc documentation

Files:

  • scripts/validation/__tests__/project-meta-sync.test.js
  • scripts/agents/includes/__tests__/derive-project-fields.test.js
**/*.{test,spec}.{js,ts,jsx,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

All test files must follow Jest testing standards and maintain minimum coverage thresholds as defined in instructions/quality-assurance.instructions.md

Files:

  • scripts/validation/__tests__/project-meta-sync.test.js
  • scripts/agents/includes/__tests__/derive-project-fields.test.js
**/*.{js,ts}

⚙️ CodeRabbit configuration file

**/*.{js,ts}: Review JavaScript/TypeScript:

  • Ensure code is linted and follows project style guides.
  • Check for dead code, unused variables, and clear function naming.
  • Validate accessibility and performance optimisations.
  • Ensure tests are isolated and do not depend on external state.
  • Check for descriptive test names and clear test structure.

Files:

  • scripts/validation/__tests__/project-meta-sync.test.js
  • scripts/agents/includes/__tests__/derive-project-fields.test.js
**/.github/workflows/*.yml

⚙️ CodeRabbit configuration file

**/.github/workflows/*.yml: Review GitHub Actions workflows for this governance repo:

  • Security: check for least-privilege permissions (use permissions: at job level, default to read-only).
  • Secret handling: ensure secrets are passed via env vars, not interpolated directly into run: steps to prevent injection.
  • Action pinning: prefer SHA-pinned actions over mutable tags (e.g. actions/checkout@v4 is acceptable; SHA pins are better).
  • No pull_request_target with untrusted code execution unless explicitly justified.
  • Avoid storing sensitive outputs as unmasked step outputs.
  • Check for reusable workflow patterns and matrix strategies where appropriate.
  • Validate on: triggers: ensure branch/path filters are present to avoid unnecessary runs.
  • Confirm workflows are documented, DRY, and maintainable.
  • Ensure agent-triggered workflows use workflow_dispatch with defined inputs.

Files:

  • .github/workflows/project-meta-sync.yml
🪛 ESLint
scripts/validation/__tests__/project-meta-sync.test.js

[error] 5-5: 'require' is not defined.

(no-undef)


[error] 6-6: 'require' is not defined.

(no-undef)


[error] 7-7: 'require' is not defined.

(no-undef)

scripts/agents/includes/__tests__/derive-project-fields.test.js

[error] 2-2: 'require' is not defined.

(no-undef)


[error] 3-3: 'require' is not defined.

(no-undef)


[error] 4-4: 'require' is not defined.

(no-undef)


[error] 8-8: 'require' is not defined.

(no-undef)

🪛 GitHub Actions: CI • Unified Checks (Lint, Test, Validate) / 1_Validation.txt
docs/CANONICAL_CONFIGS_GUIDE.md

[error] 1-1: Frontmatter freshness validation failed: body changed but version was not updated (v1.0.3).

docs/AUTOMATION.md

[error] 1-1: Frontmatter freshness validation failed: body changed but last_updated was not updated (2026-06-18).


[error] 1-1: Frontmatter freshness validation failed: body changed but version was not updated (v1.0.4).

docs/WORKFLOW_COORDINATION.md

[error] 1-1: Frontmatter freshness validation failed: body changed but last_updated was not updated (2026-06-18).


[error] 1-1: Frontmatter freshness validation failed: body changed but version was not updated (v1.1.2).

docs/ISSUE_CREATION_GUIDE.md

[error] 1-1: Frontmatter freshness validation failed: body changed but last_updated was not updated (2026-06-18).


[error] 1-1: Frontmatter freshness validation failed: body changed but version was not updated (1.0.5).

docs/ISSUE_FIELDS.md

[error] 1-1: Frontmatter freshness validation failed: body changed but last_updated was not updated (2026-06-18).


[error] 1-1: Frontmatter freshness validation failed: body changed but version was not updated (v1.0.5).

🪛 GitHub Actions: CI • Unified Checks (Lint, Test, Validate) / Validation
docs/CANONICAL_CONFIGS_GUIDE.md

[error] 1-1: Frontmatter freshness validation failed: body changed but version was not updated (v1.0.3).

docs/AUTOMATION.md

[error] 1-1: Frontmatter freshness validation failed: body changed but last_updated was not updated (2026-06-18).


[error] 1-1: Frontmatter freshness validation failed: body changed but version was not updated (v1.0.4).

docs/WORKFLOW_COORDINATION.md

[error] 1-1: Frontmatter freshness validation failed: body changed but last_updated was not updated (2026-06-18).


[error] 1-1: Frontmatter freshness validation failed: body changed but version was not updated (v1.1.2).

docs/ISSUE_CREATION_GUIDE.md

[error] 1-1: Frontmatter freshness validation failed: body changed but last_updated was not updated (2026-06-18).


[error] 1-1: Frontmatter freshness validation failed: body changed but version was not updated (1.0.5).

docs/ISSUE_FIELDS.md

[error] 1-1: Frontmatter freshness validation failed: body changed but last_updated was not updated (2026-06-18).


[error] 1-1: Frontmatter freshness validation failed: body changed but version was not updated (v1.0.5).

🪛 GitHub Actions: Meta Agent / front-matter-validate
docs/CANONICAL_CONFIGS_GUIDE.md

[error] 1-1: validate-frontmatter-freshness: body changed but version was not updated (currently v1.0.3).

docs/AUTOMATION.md

[error] 1-1: validate-frontmatter-freshness: body changed but last_updated was not updated (expected update, last_updated unchanged at 2026-06-18).


[error] 1-1: validate-frontmatter-freshness: body changed but version was not updated (expected version bump, currently v1.0.4).

docs/WORKFLOW_COORDINATION.md

[error] 1-1: validate-frontmatter-freshness: body changed but last_updated was not updated (expected update, last_updated unchanged at 2026-06-18).


[error] 1-1: validate-frontmatter-freshness: body changed but version was not updated (currently v1.1.2).

docs/ISSUE_CREATION_GUIDE.md

[error] 1-1: validate-frontmatter-freshness: body changed but last_updated was not updated (expected update, last_updated unchanged at 2026-06-18).


[error] 1-1: validate-frontmatter-freshness: body changed but version was not updated (currently 1.0.5).

docs/ISSUE_FIELDS.md

[error] 1-1: validate-frontmatter-freshness: body changed but last_updated was not updated (expected update, last_updated unchanged at 2026-06-18).


[error] 1-1: validate-frontmatter-freshness: body changed but version was not updated (currently v1.0.5).

🪛 LanguageTool
docs/CANONICAL_CONFIGS_GUIDE.md

[uncategorized] ~38-~38: Possible missing comma found.
Context: ...content/branch fallbacks as first-class signals so project fields can catch up when lab...

(AI_HYDRA_LEO_MISSING_COMMA)

docs/GITHUB_PROJECT_OPERATIONS_SPEC.md

[uncategorized] ~88-~88: Loose punctuation mark.
Context: ...nt Derivation source notes: - Status, Priority, and Type are mapped from ...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~88-~88: The official name of this software platform is spelled with a capital “H”.
Context: ..., and Type are mapped from labels via .github/issue-fields.yml mappings. - Effort ...

(GITHUB)


[uncategorized] ~91-~91: Use a comma before ‘so’ if it connects two independent clauses (unless they are closely connected and short).
Context: ...d the workflow reprocesses label changes so fields can catch up after triage. - Met...

(COMMA_COMPOUND_SENTENCE_2)


[grammar] ~102-~102: There seems to be a noun/verb agreement error. Did you mean “writes” or “wrote”?
Context: ...Y` Safe automation boundary: - Active write path covers the five core derived field...

(SINGULAR_NOUN_VERB_AGREEMENT)

🪛 zizmor (1.25.2)
.github/workflows/project-meta-sync.yml

[error] 92-92: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)

(unpinned-uses)

🔇 Additional comments (16)
.github/workflows/project-meta-sync.yml (1)

111-113: LGTM!

scripts/agents/includes/derive-project-fields.cjs (5)

23-100: LGTM!


117-159: LGTM!


161-185: LGTM!


187-247: Nicely structured fallback chain for status and type derivation.

The event-driven defaults and inference fallbacks are well-organised. The logic correctly prioritises: labels → branch prefix → title → body → configured defaults. Lovely work! 🎯


266-305: LGTM!

Also applies to: 311-317

scripts/agents/includes/__tests__/derive-project-fields.test.js (1)

56-91: Cracking test coverage for the new inference logic!

These tests nicely validate the PR default fallback and content-based inference paths. The test data is clear and the assertions cover the key derived fields.

scripts/validation/__tests__/project-meta-sync.test.js (1)

9-47: Solid contract tests for the workflow configuration!

These tests act as a lovely safeguard against accidental workflow regressions. Testing that the push trigger is removed and that label collection uses the event payload is exactly what's needed to enforce the PR's objectives. Well done! 🎉

agents/project-meta-sync.agent.md (1)

70-72: LGTM!

docs/AUTOMATION.md (1)

78-78: LGTM!

docs/CANONICAL_CONFIGS_GUIDE.md (1)

96-96: LGTM!

docs/GITHUB_PROJECT_OPERATIONS_SPEC.md (1)

84-92: LGTM on content clarity and PR alignment!

The new "Derivation source notes" section accurately documents the fallback logic and the label-event re-triggering contract. The additions effectively explain when and how fields are populated, which directly supports the PR's goal of documenting the active automation path.

docs/ISSUE_CREATION_GUIDE.md (1)

125-125: LGTM!

docs/ISSUE_FIELDS.md (1)

439-445: LGTM!

docs/WORKFLOW_COORDINATION.md (1)

52-52: LGTM!

instructions/project-meta-sync.instructions.md (1)

27-33: LGTM on the Active Contract Summary!

The three-point summary is crystal clear and directly supports the PR's goals. It's perfect for quick reference—contributors can immediately understand the label-canonicity requirements, issue-type-as-source-of-truth principle, and the re-run-on-label-changes contract. Lovely stuff! 🎯

Comment on lines +37 to +39
Project metadata sync is label-driven, but it also treats issue type selection
and safe content/branch fallbacks as first-class signals so project fields can
catch up when labels are added after creation.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Add missing comma in compound sentence.

Line 37–39 joins two independent clauses with "so", but a comma is needed before the conjunction. The sentence currently reads: "…first-class signals so project fields can catch up…" but should read: "…first-class signals, so project fields can catch up…"

🔧 Proposed fix
-Project metadata sync is label-driven, but it also treats issue type selection
-and safe content/branch fallbacks as first-class signals so project fields can
-catch up when labels are added after creation.
+Project metadata sync is label-driven, but it also treats issue type selection
+and safe content/branch fallbacks as first-class signals, so project fields can
+catch up when labels are added after creation.
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
Project metadata sync is label-driven, but it also treats issue type selection
and safe content/branch fallbacks as first-class signals so project fields can
catch up when labels are added after creation.
Project metadata sync is label-driven, but it also treats issue type selection
and safe content/branch fallbacks as first-class signals, so project fields can
catch up when labels are added after creation.
🧰 Tools
🪛 LanguageTool

[uncategorized] ~38-~38: Possible missing comma found.
Context: ...content/branch fallbacks as first-class signals so project fields can catch up when lab...

(AI_HYDRA_LEO_MISSING_COMMA)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/CANONICAL_CONFIGS_GUIDE.md` around lines 37 - 39, In the section
describing project metadata sync (lines 37-39 in CANONICAL_CONFIGS_GUIDE.md),
add a comma before the conjunction "so" in the compound sentence. The text
currently reads "first-class signals so project fields can catch up" but should
be corrected to "first-class signals, so project fields can catch up" to
properly punctuate the join between two independent clauses.

Source: Linters/SAST tools

Comment on lines 88 to 92
- `Status`, `Priority`, and `Type` are mapped from labels via `.github/issue-fields.yml` mappings.
- `Effort` uses the configured default from canonical issue-fields configuration.
- `Start date` and `Target date` stay empty at creation time and are only populated after kickoff-ready metadata is present (`status:ready` or `status:in-progress`).
- `Type` and `Priority` now fall back to safe content-based inference when labels are missing or late.
- `Start date` and `Target date` are populated when kickoff-ready metadata is present (`status:ready` or `status:in-progress`) and the workflow reprocesses label changes so fields can catch up after triage.
- Metadata governance for assignees, milestones, and relationships is handled separately by `.github/workflows/metadata-governance.yml`.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Add missing comma in compound sentence (line ~91).

The clause "the workflow reprocesses label changes so fields can catch up after triage" needs a comma before "so" to properly join two independent clauses. It should read: "…label changes, so fields can catch up…"

🔧 Proposed fix
-- `Type` and `Priority` now fall back to safe content-based inference when labels are missing or late.
-- `Start date` and `Target date` are populated when kickoff-ready metadata is present (`status:ready` or `status:in-progress`) and the workflow reprocesses label changes so fields can catch up after triage.
+- `Type` and `Priority` now fall back to safe content-based inference when labels are missing or late.
+- `Start date` and `Target date` are populated when kickoff-ready metadata is present (`status:ready` or `status:in-progress`), and the workflow reprocesses label changes, so fields can catch up after triage.
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
- `Status`, `Priority`, and `Type` are mapped from labels via `.github/issue-fields.yml` mappings.
- `Effort` uses the configured default from canonical issue-fields configuration.
- `Start date` and `Target date` stay empty at creation time and are only populated after kickoff-ready metadata is present (`status:ready` or `status:in-progress`).
- `Type` and `Priority` now fall back to safe content-based inference when labels are missing or late.
- `Start date` and `Target date` are populated when kickoff-ready metadata is present (`status:ready` or `status:in-progress`) and the workflow reprocesses label changes so fields can catch up after triage.
- Metadata governance for assignees, milestones, and relationships is handled separately by `.github/workflows/metadata-governance.yml`.
- `Status`, `Priority`, and `Type` are mapped from labels via `.github/issue-fields.yml` mappings.
- `Effort` uses the configured default from canonical issue-fields configuration.
- `Type` and `Priority` now fall back to safe content-based inference when labels are missing or late.
- `Start date` and `Target date` are populated when kickoff-ready metadata is present (`status:ready` or `status:in-progress`), and the workflow reprocesses label changes, so fields can catch up after triage.
- Metadata governance for assignees, milestones, and relationships is handled separately by `.github/workflows/metadata-governance.yml`.
🧰 Tools
🪛 LanguageTool

[uncategorized] ~88-~88: Loose punctuation mark.
Context: ...nt Derivation source notes: - Status, Priority, and Type are mapped from ...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~88-~88: The official name of this software platform is spelled with a capital “H”.
Context: ..., and Type are mapped from labels via .github/issue-fields.yml mappings. - Effort ...

(GITHUB)


[uncategorized] ~91-~91: Use a comma before ‘so’ if it connects two independent clauses (unless they are closely connected and short).
Context: ...d the workflow reprocesses label changes so fields can catch up after triage. - Met...

(COMMA_COMPOUND_SENTENCE_2)


[uncategorized] ~92-~92: The official name of this software platform is spelled with a capital “H”.
Context: ... relationships is handled separately by .github/workflows/metadata-governance.yml. Cu...

(GITHUB)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/GITHUB_PROJECT_OPERATIONS_SPEC.md` around lines 88 - 92, In the bullet
point about "Start date" and "Target date" population, locate the text "the
workflow reprocesses label changes so fields can catch up after triage" and add
a comma before the word "so" to properly join the two independent clauses. The
corrected text should read "the workflow reprocesses label changes, so fields
can catch up after triage".

Source: Linters/SAST tools

@chatgpt-codex-connector chatgpt-codex-connector Bot 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 31f66acb35

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +117 to +121
function inferMappedValueFromText(text, rules, mapping) {
const haystack = String(text || "");
for (const rule of rules) {
if (rule.patterns.some((pattern) => pattern.test(haystack))) {
return mapping?.[rule.label] || "";

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Strip template boilerplate before inferring fields

When labels are missing, this matcher scans the entire issue/PR body, including untouched template comments and examples. The default PR template contains examples such as Critical risk and New feature, and the documentation issue template asks whether the work is blocking, so an otherwise unlabelled item created from those templates can be projected as Critical/Feature even though the user did not choose those values. Please strip template comments/boilerplate or restrict fallback inference to explicit answers/title text before writing project fields.

Useful? React with 👍 / 👎.

Comment on lines +96 to +98
const labels = context.payload.issue?.labels || context.payload.pull_request?.labels || [];
const labelNames = labels.map((label) => label.name).filter(Boolean).join('\n');
core.setOutput('labels', labelNames);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Read live labels before updating project fields

For opened/edited/synchronize runs, this now uses the webhook snapshot rather than the item's current labels. Since labeling.yml runs independently on the same events and later label events also trigger this workflow, an older run that captured no labels can finish after the label-triggered run and overwrite the project fields with fallback/default values. Please fetch the current labels at update time or add per-item concurrency/cancellation before deriving fields.

Useful? React with 👍 / 👎.

Comment on lines +29 to +33
- Keep `status:*`, `priority:*`, and `type:*` labels canonical and one-hot.
- Treat issue types as the source of truth for canonical `type:*` intent and let
`project-meta-sync.yml` project that intent into GitHub Project fields.
- Allow the workflow to re-run on label changes so late-applied labels and issue
type corrections catch up in the project board.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Move the summary outside the frontmatter block

These bullets are still before the closing ---, so YAML treats them as additional apply_to entries instead of rendered instruction content. That pollutes the instruction metadata with prose targets and hides the new contract summary from readers/processors expecting it in the Markdown body; close the frontmatter before the ## Active Contract Summary section.

Useful? React with 👍 / 👎.

@github-actions

Copy link
Copy Markdown
Contributor

🔍 Reviewer Summary for PR #1014

CI Status:success
Files changed: 12
Risk Distribution: 1 critical, 0 high, 2 medium, 9 low

Recommendations

  • ⚠️ 1 critical-risk file(s) modified (workflows, secrets)
  • ⚠️ Security-sensitive files modified (review carefully)

@ashleyshaw ashleyshaw merged commit 2029f69 into develop Jun 19, 2026
29 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:ci Build and CI pipelines area:documentation Docs & guides area:scripts Scripts & tooling area:tests Test suites & harnesses lang:js JavaScript/TypeScript lang:md Markdown content/docs lang:yaml YAML config meta:needs-changelog Requires a changelog entry before merge priority:normal Default priority status:needs-review Awaiting code review type:bug Bug or defect type:test Testing/coverage

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Automate issue and PR metadata completion end to end

1 participant