Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
105 changes: 80 additions & 25 deletions .github/agents/project-meta-sync.agent.md
Original file line number Diff line number Diff line change
@@ -1,52 +1,107 @@
---
title: "Project Meta Sync Agent Spec"
version: "v1.0"
last_updated: "2025-10-21"
version: "v1.1"
last_updated: "2025-11-13"
author: "LightSpeed"
maintainer: "Ash Shaw"
description: "Spec for the Project Meta Sync Agent."
tags: ["lightspeed","project","meta","agents"]
description: "Spec for the Project Meta Sync Agent that maps labels and branch conventions to GitHub ProjectV2 fields."
tags: ["lightspeed","project","meta","agents","automation"]
type: "agent"
references:
- ".github/automation/project-fields.yml"
- ".github/automation/project-labeler.yml"
- ".github/automation/labels.yml"
- "schemas/automation/project-fields.schema.json"
- ".github/workflows/project-meta-sync.yml"
- ".github/agents/project-meta-sync.js"
---
Comment on lines 1 to 17

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

Add missing frontmatter fields: stability and domain.

Per coding guidelines, agent spec metadata must include a domain (exactly one from the approved taxonomy) and a stability field with a value of stable, experimental, or incubating.

Extend the YAML frontmatter to include:

 version: "v1.1"
 last_updated: "2025-11-13"
 author: "LightSpeed"
 maintainer: "Ash Shaw"
+stability: "experimental"
+domain: "generic"
 description: "Spec for the Project Meta Sync Agent that maps labels and branch conventions to GitHub ProjectV2 fields."

(Adjust domain if a more specific domain applies, and confirm stability reflects the agent's readiness for production.)

📝 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
---
title: "Project Meta Sync Agent Spec"
version: "v1.0"
last_updated: "2025-10-21"
version: "v1.1"
last_updated: "2025-11-13"
author: "LightSpeed"
maintainer: "Ash Shaw"
description: "Spec for the Project Meta Sync Agent."
tags: ["lightspeed","project","meta","agents"]
description: "Spec for the Project Meta Sync Agent that maps labels and branch conventions to GitHub ProjectV2 fields."
tags: ["lightspeed","project","meta","agents","automation"]
type: "agent"
references:
- ".github/automation/project-fields.yml"
- ".github/automation/project-labeler.yml"
- ".github/automation/labels.yml"
- "schemas/automation/project-fields.schema.json"
- ".github/workflows/project-meta-sync.yml"
- ".github/agents/project-meta-sync.js"
---
---
title: "Project Meta Sync Agent Spec"
version: "v1.1"
last_updated: "2025-11-13"
author: "LightSpeed"
maintainer: "Ash Shaw"
stability: "experimental"
domain: "generic"
description: "Spec for the Project Meta Sync Agent that maps labels and branch conventions to GitHub ProjectV2 fields."
tags: ["lightspeed","project","meta","agents","automation"]
type: "agent"
references:
- ".github/automation/project-fields.yml"
- ".github/automation/project-labeler.yml"
- ".github/automation/labels.yml"
- "schemas/automation/project-fields.schema.json"
- ".github/workflows/project-meta-sync.yml"
- ".github/agents/project-meta-sync.js"
---
🤖 Prompt for AI Agents
In .github/agents/project-meta-sync.agent.md around lines 1 to 17 the YAML
frontmatter is missing the required fields `domain` and `stability`; add a
`domain` entry using one approved taxonomy term (e.g., domain: "automation" —
change if a more specific approved domain applies) and add a `stability` entry
set to one of: "stable", "experimental", or "incubating" (pick the one that
correctly reflects production readiness), then save the file (update
last_updated only if you actually changed readiness).

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

Verify agent spec is referenced from agent index and confirm domain/stability.

Confirm the following:

  1. This spec is referenced in a central agent index file (e.g., .github/agents/README.md or similar)
  2. Confirm domain value: generic, automation, or another approved taxonomy entry
  3. Confirm stability value: is this agent experimental, incubating, or approaching stable?

Run the script below to search for index references:


🏁 Script executed:

#!/bin/bash
# Search for agent index or registry file that references project-meta-sync
fd -e md -e yml -e yaml '.github' | xargs rg -l 'project-meta-sync' | grep -E '(README|index|registry|catalog)' || echo "No agent index found—consider creating one if missing"

Length of output: 53


I need to gather more information. Let me search the codebase for the complete agent spec file, check if other agent specs exist to understand the pattern, and verify the required fields.


🏁 Script executed:

#!/bin/bash
# Check full content of the agent spec file and find other agent specs
echo "=== Full content of project-meta-sync.agent.md ==="
find .github -name "project-meta-sync.agent.md" -exec cat {} \;

echo -e "\n=== All agent spec files in .github/agents/ ==="
fd -e 'agent.md' '.github/agents/'

echo -e "\n=== Check if any agent spec has domain/stability fields ==="
fd -e 'agent.md' '.github/agents/' -exec rg -l 'domain:|stability:' {} \;

Length of output: 5795


Let me fix the script syntax to find other agent specs and check for existing domain/stability patterns:


🏁 Script executed:

#!/bin/bash
# Find all agent spec files with corrected syntax
echo "=== All agent spec files ==="
fd . '.github/agents/' --extension agent.md --full-path

echo -e "\n=== Search for domain/stability in agent specs ==="
rg 'domain:|stability:' '.github/agents/' --type md

echo -e "\n=== Search for approved domain taxonomy ==="
rg -i 'approved.*domain|domain.*taxonomy' '.github/' --type md --type yml -A3

Length of output: 1607


Let me verify whether any of the active agent specs have domain/stability fields:


🏁 Script executed:

#!/bin/bash
# Check frontmatter of a few active agent specs for domain/stability
echo "=== Check sample active agents for domain/stability ==="
for file in .github/agents/labeling.agent.md .github/agents/reviewer.agent.md .github/agents/wp-security-review.agent.md; do
  echo "--- $file ---"
  head -30 "$file" | rg 'domain:|stability:|^---' || echo "  (no matches found)"
done

echo -e "\n=== Grep first few lines of project-meta-sync.agent.md frontmatter ==="
head -20 .github/agents/project-meta-sync.agent.md

Length of output: 1007


Add required frontmatter fields (domain and stability) and complete spec content sections.

The spec is missing two required frontmatter fields per coding guidelines for .github/agents/*.agent.md:

  1. domain: Must be one of: wp-core, block-theme, plugin-hardening, perf, a11y, i18n, security, headless, or generic. Given this agent syncs GitHub ProjectV2 fields via automation, generic or automation would be appropriate (confirm which fits your taxonomy).
  2. stability: Must be experimental, incubating, or stable. Determine the maturity level of this agent.

Additionally, per agent spec guidelines, the following content sections need expansion:

  • Security considerations: Address API access, token handling, and permissions.
  • Error handling: Detail failure modes and recovery strategies.
  • Logging practices: Specify log format, verbosity levels, and sensitive data redaction.
  • Example usage: Provide a walkthrough scenario.
  • Troubleshooting tips: Add common issues and resolutions.

No centralized agent index was found in the repository. If specs should be discoverable via an index (e.g., .github/agents/README.md), create or update it to reference this agent.

🤖 Prompt for AI Agents
In .github/agents/project-meta-sync.agent.md around lines 1 to 17 the
frontmatter is missing required fields `domain` and `stability` and the spec
body lacks several mandatory sections; add a `domain` value (choose one from
wp-core, block-theme, plugin-hardening, perf, a11y, i18n, security, headless, or
use `generic` if appropriate) and a `stability` value (`experimental`,
`incubating`, or `stable`) to the YAML frontmatter, then expand the markdown to
include the required sections: Security considerations (API scopes, token
storage/rotation, least-privilege permissions), Error handling (failure modes,
retries, backoff, alerting), Logging practices (format, levels, redact rules),
Example usage (step-by-step scenario with inputs/outputs), and Troubleshooting
tips (common issues and resolutions); finally, add or update a centralized
agents index (e.g., .github/agents/README.md) to reference this spec so it’s
discoverable.


# Role
Sync project board meta fields (Status, Priority, Type) from labels and branch names.
Sync GitHub ProjectV2 fields (Status, Priority, Type, Area, etc.) from labels and branch name conventions.

# Purpose
- Keep GitHub Projects and issues/PRs in sync.
- Automate project field updates based on repo activity.
- Keep GitHub Projects V2 and issues/PRs in sync automatically.
- Automate project field updates based on repository activity.
- Provide a single source of truth for project field mappings via `.github/automation/project-fields.yml`.

# Type of Task
- Add new items to project on issue/PR events.
- Map labels/branches to project fields.
- Add new items to project board on issue/PR events.
- Map labels and branch patterns to ProjectV2 fields using canonical mapping.
- Sync field values non-destructively (preserve manual changes unless override flag present).

Comment on lines 19 to 31

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 | 🟠 Major

Add explicit Inputs section before Process.

The specification lacks a structured Inputs section documenting what data/events trigger the agent and what information it receives. This is essential for agent specifications per guidelines.

Propose adding an Inputs section after "Type of Task" and before "Process" (around line 32):

# Inputs
- **Issue/PR events**: `opened`, `edited`, `labeled`, `unlabeled`, `closed`, `reopened`, `synchronize`
- **Event context**: issue/PR metadata, labels, branch name, author, merge status
- **Configuration**: `.github/automation/project-fields.yml`, `.github/automation/project-labeler.yml`
- **User override**: `meta:auto-sync` label to enable manual field overwrites
🧰 Tools
🪛 LanguageTool

[uncategorized] ~25-~25: The official name of this software platform is spelled with a capital “H”.
Context: ...of truth for project field mappings via .github/automation/project-fields.yml. # Type...

(GITHUB)

🤖 Prompt for AI Agents
In .github/agents/project-meta-sync.agent.md around lines 19 to 31, the spec is
missing a formal "Inputs" section; add a new Inputs heading after "Type of Task"
and before "Process" that lists the triggers and data the agent receives
(Issue/PR events like
opened/edited/labeled/unlabeled/closed/reopened/synchronize; event context such
as issue/PR metadata, labels, branch name, author, merge status; configuration
files .github/automation/project-fields.yml and
.github/automation/project-labeler.yml; and the user override label
meta:auto-sync) so the agent clearly documents what initiates it and what
payload it consumes.

# Process
- Trigger on issue/PR open/edit/label.
- Use mapping rules to set Status, Priority, Type.
- Update project fields via API.
1. Trigger on issue/PR open/edit/label/unlabel/close events.
2. Load canonical field mappings from `.github/automation/project-fields.yml`.
3. Derive field values using:
- Label-based mapping (e.g., `status:in-progress` → Status: "In progress")
- Branch-based mapping (e.g., `feat/*` → Type: "Feature")
- Event-based mapping (e.g., closed + merged → Status: "Done")
4. Update ProjectV2 fields via GraphQL API.
5. Log all changes for audit trail.

# Constraints
- Must not overwrite manual changes without warning.
- Support per-project mapping config.
- Must not overwrite manual field changes without explicit override (via `meta:auto-sync` label).
- Support per-project field mapping configurations (via `types` in project-fields.yml).
- Enforce single status label per issue/PR (warn or auto-tidy multiple status labels).
- Validate all mappings against JSON schema (`schemas/automation/project-fields.schema.json`).

# What to do
- Ensure project fields are always up to date with labels.
- Ensure ProjectV2 fields are always synchronized with canonical labels and branch conventions.
- Use `.github/automation/project-fields.yml` as the single source of truth for field definitions.
- Reference `.github/automation/project-labeler.yml` for label-to-field mapping rules.
- Log all field updates with timestamps and triggering events.

# What not do
- Do not remove items from project without confirmation.
# What not to do
- Do not remove items from project board without explicit confirmation.
- Do not bypass manual field changes unless `meta:auto-sync` label is present.
- Do not create duplicate status labels (enforce single status label rule).

# Best Practices
- Log all changes.
- Allow per-repo/project config.
- Log all changes with event context (issue/PR number, triggering action, old/new values).
- Allow per-repository and per-project configuration overrides.
- Validate project-fields.yml against schema before applying changes.
- Use GraphQL batching for efficient field updates.
- Provide clear error messages and warnings for mapping conflicts.

# Guardrails
- Notify maintainers on mapping conflicts.
- Provide rollback/audit if possible.
- Notify maintainers on mapping conflicts or schema validation failures.
- Provide rollback capability via audit log.
- Rate-limit API calls to prevent quota exhaustion.
- Skip updates if field values haven't changed (idempotent operations).
Comment on lines 32 to +70

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 | 🟠 Major

Add explicit Dependencies, Security, and Error Handling sections.

Per agent specification guidelines, the spec must document dependencies (external APIs, libraries), security constraints, and error handling strategies. These are currently implicit or missing.

Propose adding sections after "Guardrails" (around line 71):

# Dependencies
- GitHub GraphQL API (v4) for ProjectV2 field updates
- Node.js runtime with `@octokit/graphql` or equivalent
- `.github/automation/project-fields.yml` and `.github/automation/project-labeler.yml` files
- JSON Schema validator for `schemas/automation/project-fields.schema.json`

# Security
- Use GitHub Actions secrets for API token (`GITHUB_TOKEN` with minimum required permissions)
- Validate all external inputs (labels, branch names) against schema
- Enforce rate-limiting to prevent API quota exhaustion
- Do not log sensitive data (API responses, token details)
- Audit all field mutations for compliance monitoring

# Error Handling
- If schema validation fails, log warning and skip field updates
- If GraphQL API call fails, retry with exponential backoff (max 3 retries)
- If mapping conflict detected (multiple status labels), warn maintainers and defer update
- If `meta:auto-sync` label state is ambiguous, default to non-destructive behavior
- Propagate errors to workflow run summary for visibility
🧰 Tools
🪛 LanguageTool

[uncategorized] ~34-~34: The official name of this software platform is spelled with a capital “H”.
Context: .... 2. Load canonical field mappings from .github/automation/project-fields.yml. 3. Deri...

(GITHUB)


[uncategorized] ~50-~50: The official name of this software platform is spelled with a capital “H”.
Context: ...al labels and branch conventions. - Use .github/automation/project-fields.yml as the s...

(GITHUB)


[uncategorized] ~51-~51: The official name of this software platform is spelled with a capital “H”.
Context: ...ruth for field definitions. - Reference .github/automation/project-labeler.yml for lab...

(GITHUB)

🤖 Prompt for AI Agents
In .github/agents/project-meta-sync.agent.md around lines 32 to 70, the spec is
missing explicit Dependencies, Security, and Error Handling sections; add three
new sections after "Guardrails" documenting: Dependencies (list GitHub GraphQL
API v4, Node.js runtime and library like @octokit/graphql, the two YAML config
files, and a JSON Schema validator), Security (use GitHub Actions secrets with
least-privilege GITHUB_TOKEN, validate external inputs against schema, enforce
rate limits, avoid logging sensitive data, and audit mutations), and Error
Handling (skip updates and log when schema validation fails, retry GraphQL calls
with exponential backoff up to 3 attempts, warn/notify maintainers on mapping
conflicts and defer updates, treat ambiguous meta:auto-sync as non-destructive,
and surface errors to the workflow run summary).


# Checklist
- [ ] Items added to project.
- [ ] Meta fields synced.
- [ ] Items added to project board for new issues/PRs.
- [ ] Status field synced from labels and event state.
- [ ] Priority field synced from labels and branch patterns.
- [ ] Type field synced from branch prefix or labels.
- [ ] Area field synced from file changes (if configured).
- [ ] Manual changes preserved (unless override present).
- [ ] Single status label enforced.
- [ ] All changes logged for audit.
Comment on lines 72 to +80

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 | 🟠 Major

Add Troubleshooting section.

Agent specs should include common troubleshooting scenarios and how to resolve them. This helps users debug issues.

Propose adding a Troubleshooting section after the Checklist:

# Troubleshooting
- **Fields not syncing**: Verify `meta:auto-sync` label is present if overriding manual changes; check schema validation in logs
- **Mapping conflicts**: Multiple status labels detected—remove extras or configure label automation via project-labeler.yml
- **GraphQL rate-limit errors**: Check API quota usage; agent retries automatically with backoff
- **Schema validation failures**: Ensure project-fields.yml matches `schemas/automation/project-fields.schema.json`; refer to Configuration Files
🤖 Prompt for AI Agents
.github/agents/project-meta-sync.agent.md around lines 72 to 80: add a new
"Troubleshooting" section immediately after the Checklist that lists common
failure scenarios and actionable resolutions; include bullet items for "Fields
not syncing" (check meta:auto-sync label and validation logs), "Mapping
conflicts" (remove duplicate status labels or update project-labeler.yml),
"GraphQL rate-limit errors" (inspect API quota and note automatic backoff
retries), and "Schema validation failures" (ensure project-fields.yml matches
schemas/automation/project-fields.schema.json and refer to Configuration Files);
keep wording concise and place the section between the Checklist and the next
header.


# Outputs
- Project board updates.
- Sync logs.
- ProjectV2 field updates via GraphQL API.
- Audit logs (JSON format) with timestamps, event context, and field changes.
- Warnings for mapping conflicts or validation errors.

# Configuration Files
- **`.github/automation/project-fields.yml`**: Canonical project field definitions (source of truth)
- **`.github/automation/project-labeler.yml`**: Label mapping rules (harmonised with labels.yml)
- **`.github/automation/labels.yml`**: Canonical label definitions
- **`schemas/automation/project-fields.schema.json`**: JSON Schema for field validation
- **`.github/workflows/project-meta-sync.yml`**: Workflow trigger configuration
- **`.github/agents/project-meta-sync.js`**: Agent implementation (Node.js)

# Field Mapping Examples
| Label/Branch | Field | Value |
|--------------|-------|-------|
| `status:in-progress` | Status | "In progress" |
| `status:needs-review` | Status | "In review" |
| `priority:critical` | Priority | "Critical" |
| `feat/*` branch | Type | "Feature" |
| `fix/*` branch | Type | "Bug" |
| `hotfix/*` branch | Priority | "Critical" |
| closed + merged | Status | "Done" |

# Override Mechanism
Add the `meta:auto-sync` label to allow the agent to overwrite manual field changes. Without this label, the agent will only update empty fields or fields set to default values.
176 changes: 176 additions & 0 deletions .github/agents/project-meta-sync.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
#!/usr/bin/env node
/**
* Project Meta Sync Agent
*
* Maps labels/branch conventions to ProjectV2 fields (Status, Priority, Type)
* and updates the corresponding item. Non-destructive by default.
*
* @author LightSpeed
* @requires @octokit/graphql, js-yaml, fs
* @see .github/agents/project-meta-sync.agent.md
*/
const fs = require('fs');
const path = require('path');
const { graphql } = require('@octokit/graphql');
const yaml = require('js-yaml');

// Parse CLI args
const args = process.argv.slice(2);
const eventName = args.find(a => a.startsWith('--event'))?.split('=')[1];
const payloadPath = args.find(a => a.startsWith('--payload'))?.split('=')[1];

if (
!eventName || typeof eventName !== 'string' || eventName.trim() === '' ||
!payloadPath || typeof payloadPath !== 'string' || payloadPath.trim() === ''
) {
console.error('Usage: project-meta-sync.js --event=<event_name> --payload=<path_to_payload>');
process.exit(1);
}

// Load event payload
let event;
try {
event = JSON.parse(fs.readFileSync(payloadPath, 'utf8'));
} catch (e) {
console.error('Failed to parse event payload:', e.message);
process.exit(1);
}

// Environment
const GITHUB_TOKEN = process.env.GITHUB_TOKEN;

if (!GITHUB_TOKEN) {
console.error('❌ GITHUB_TOKEN not set');
process.exit(1);
}

// GraphQL client

/**
* Load canonical project fields mapping (if present)
* TODO: Implement loading of normalized mapping dictionary
*/
function loadFieldsMapping() {
const fieldsPath = path.resolve('.github/automation/project-fields.yml');
if (fs.existsSync(fieldsPath)) {
return yaml.load(fs.readFileSync(fieldsPath, 'utf8'));
}
return null;
}

/**
* Derive Status from labels and event
*/
function deriveStatus(labels, eventName, eventAction, isMerged = false) {

Copilot AI Nov 12, 2025

Copy link

Choose a reason for hiding this comment

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

Missing JSDoc documentation for this function. According to WordPress JavaScript Documentation Standards, all exported or significant functions should have JSDoc comments describing parameters, return values, and purpose. Add: /** * Derive Status from labels and event. * @param {Array} labels - Array of label objects or strings. * @param {string} eventName - GitHub event name. * @param {string} eventAction - GitHub event action. * @param {boolean} [isMerged=false] - Whether PR is merged. * @returns {string} Status value. */.

Copilot generated this review using guidance from repository custom instructions.
const labelNames = labels.map(l => l.name || l);

// Check status labels
if (labelNames.some(l => l === 'status:in-progress')) return 'In progress';
if (labelNames.some(l => l === 'status:needs-review')) return 'In review';
if (labelNames.some(l => l === 'status:needs-qa')) return 'In QA';
if (labelNames.some(l => l === 'status:blocked')) return 'Blocked';
if (labelNames.some(l => l === 'status:ready')) return 'Ready';

// Check closed/merged events
if (eventAction === 'closed') {
if (eventName === 'issues') return 'Done';
if (eventName === 'pull_request' && isMerged) return 'Done';
}

// Default to Triage
return 'Triage';
}

/**
* Derive Priority from labels
*/
function derivePriority(labels) {

Copilot AI Nov 12, 2025

Copy link

Choose a reason for hiding this comment

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

Missing JSDoc documentation for this function. Add: /** * Derive Priority from labels. * @param {Array} labels - Array of label objects or strings. * @returns {string|null} Priority value or null if not set. */.

Copilot generated this review using guidance from repository custom instructions.
const labelNames = labels.map(l => l.name || l);

if (labelNames.some(l => l === 'priority:critical')) return 'Critical';
if (labelNames.some(l => l === 'priority:important')) return 'Important';
if (labelNames.some(l => l === 'priority:normal')) return 'Normal';
if (labelNames.some(l => l === 'priority:minor')) return 'Minor';

return null; // No priority set
}

/**
* Derive Type from branch name or labels
*/
function deriveType(branchName, labels) {

Copilot AI Nov 12, 2025

Copy link

Choose a reason for hiding this comment

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

Missing JSDoc documentation for this function. Add: /** * Derive Type from branch name or labels. * @param {string|null} branchName - Branch name from PR. * @param {Array} labels - Array of label objects or strings. * @returns {string|null} Type value or null if not set. */.

Copilot generated this review using guidance from repository custom instructions.
// Try branch conventions first
if (branchName) {
if (branchName.startsWith('feat/')) return 'Feature';
if (branchName.startsWith('fix/')) return 'Bug';
if (branchName.startsWith('doc/') || branchName.startsWith('docs/')) return 'Documentation';
if (branchName.startsWith('chore/') || branchName.startsWith('build/')) return 'Task';
}

// Try labels
const labelNames = labels.map(l => l.name || l);
if (labelNames.some(l => l === 'type:feature')) return 'Feature';
if (labelNames.some(l => l === 'type:bug')) return 'Bug';
if (labelNames.some(l => l === 'type:documentation')) return 'Documentation';
if (labelNames.some(l => l === 'type:task')) return 'Task';

return null; // No type set
}

/**
* Main sync logic
*/
async function sync() {
console.log(`project-meta-sync: handling ${eventName} event`);

// Extract item details from event
const item = event.issue || event.pull_request;
if (!item) {
console.log('No issue or PR in event payload');
return;
}

const labels = item.labels || [];
const branchName = event.pull_request?.head?.ref || null;
const eventAction = event.action;
const isMerged = event.pull_request?.merged || false;

// Derive field values
const status = deriveStatus(labels, eventName, eventAction, isMerged);
const priority = derivePriority(labels);
const type = deriveType(branchName, labels);

console.log(`Derived fields:`, { status, priority, type });

// TODO: Enforce single status:* label (warn or auto-tidy)
const statusLabels = labels.filter(l => (l.name || l).startsWith('status:'));
if (statusLabels.length > 1) {
console.warn(`[WARN] Multiple status labels found: ${statusLabels.map(l => l.name || l).join(', ')}`);
console.warn('Consider using label-sync to enforce single status label');
}

// TODO: Use GraphQL to upsert ProjectV2 item & fields
// For now, just log what would be updated
console.log(`Would update ProjectV2 item for ${item.html_url}:`);
console.log(` Status: ${status}`);
if (priority) console.log(` Priority: ${priority}`);
if (type) console.log(` Type: ${type}`);

// TODO: Guard against overwriting manual fields unless override label present
const hasOverride = labels.some(l => (l.name || l) === 'meta:auto-sync');
if (!hasOverride) {
console.log('ℹ️ No override label (meta:auto-sync) - would check for manual changes');
}

// TODO: Load normalized mapping dictionary if present
const fieldsMapping = loadFieldsMapping();
if (fieldsMapping) {
console.log('✅ Loaded project fields mapping');
}
}

// Run
sync().catch(err => {
console.error('❌ Error:', err.message);
process.exit(1);
});
Loading
Loading