# AGENTS.md

A README for coding agents working in **merchant-art-agents** — the reference home for reusable AI agents, skills, and rules that automate code review, dependency upgrades, and Snap Finance standards across services. This file follows the [agents.md](https://agents.md/) open format so any compatible agent (Cursor, Claude Code, Codex, etc.) can use it.

## Project overview

This repository is a **content/automation repository**, not an application. It ships:

- **Agents** (`agents/*.md`) — initializer, orchestrators, and specialized reviewer / upgrader personas.
- **Skills** (`skills/<category>/<name>/SKILL.md`) — the detailed, reusable procedures the agents follow.
- **Rules** (`rules/general/*.mdc`, `rules/observability/*.mdc`, `rules/<service-name>/*.mdc`) — shared, observability, and service-specific conventions for API projects.

There is **no build, test, or lint step** — the "code" is structured Markdown that drives AI behavior. Validate changes by reading them and confirming frontmatter is well-formed.

## Directory map

```text
merchant-art-agents/
├── AGENTS.md                       # this file (cross-agent guide)
├── README.md                       # human-facing purpose + usage
├── agents/                         # subagent source files (copy to .cursor/agents in consumer repos)
│   ├── api-spec-orchestrator.md
│   ├── code-review-orchestrator.md
│   ├── cursor-project-initializer.md
│   ├── dependency-upgrade-orchestrator.md
│   ├── git-operations-coordinator.md
│   ├── git-repository-cloner.md
│   ├── git-repository-puller.md
│   ├── java-code-reviewer.md
│   ├── owasp-validation.md
│   ├── aws-secrets-manager-validation.md
│   ├── liquibase-code-reviewer.md
│   ├── liquibase-report-writer.md
│   ├── java-parent-pom-dependency-upgrader.md
│   ├── java-spring-boot-dependency-upgrader.md
│   ├── java-spring-boot-starter-dependency-upgrader.md
│   ├── java-serverless-dependency-upgrader.md
│   ├── merchant-api-spec-bulk-generator.md
│   ├── merchant-api-spec-creator.md
│   ├── merchant-api-spec-deployment-generator.md
│   ├── merchant-api-spec-updater.md
│   ├── merchant-observability-assistant-orchestrator.md
│   ├── node-serverless-code-reviewer.md
│   ├── node-serverless-dependency-upgrader.md
│   ├── nextjs-react-prisma-serverless-code-reviewer.md
│   ├── nextjs-react-prisma-serverless-dependency-upgrader.md
│   ├── php-laravel-serverless-code-reviewer.md
│   ├── php-laravel-serverless-dependency-upgrader.md
│   ├── readme-updater-coordinator.md
│   ├── report-writer-coordinator.md
│   ├── java-spring-boot-report-writer.md
│   ├── java-spring-boot-serverless-report-writer.md
│   ├── java-spring-boot-starter-report-writer.md
│   ├── node-serverless-report-writer.md
│   ├── nextjs-react-prisma-serverless-report-writer.md
│   ├── php-laravel-serverless-report-writer.md
│   ├── merchant-api-spec-report-writer.md
│   ├── java-spring-boot-readme-updater.md
│   ├── java-spring-boot-starter-readme-updater.md
│   ├── java-spring-boot-job-readme-updater.md
│   ├── node-serverless-readme-updater.md
│   ├── nextjs-react-prisma-serverless-readme-updater.md
│   ├── php-laravel-serverless-readme-updater.md
│   ├── parent-pom-readme-updater.md
│   ├── parent-pom-report-writer.md
│   ├── service-version-definer.md
│   └── backstage-api-spec-readme-updater.md
├── skills/                         # SKILL.md source files, grouped by category
│   ├── api-spec/
│   │   ├── merchant-api-spec-bulk-generate/SKILL.md
│   │   ├── merchant-api-spec-create/SKILL.md
│   │   ├── merchant-api-spec-deployment-files/SKILL.md
│   │   └── merchant-api-spec-update/SKILL.md
│   ├── api-standards/
│   │   └── snap-rest-api-standards/SKILL.md
│   ├── observability/
│   │   ├── ensure-repo-ready/SKILL.md
│   │   ├── scan-endpoint-timing-logs/SKILL.md
│   │   ├── report-endpoint-timing-coverage/SKILL.md
│   │   ├── generate-sumo-dashboards/SKILL.md
│   │   ├── generate-sumo-monitors/SKILL.md
│   │   └── report-sumo-upload-summary/SKILL.md
│   ├── code-review/
│   │   ├── java-spring-boot-code-review/SKILL.md
│   │   ├── owasp-dependency-check-validation/SKILL.md
│   │   ├── aws-secrets-manager-validation/SKILL.md
│   │   ├── liquibase-code-review/SKILL.md
│   │   ├── node-serverless-code-review/SKILL.md
│   │   ├── nextjs-react-prisma-serverless-code-review/SKILL.md
│   │   └── php-laravel-serverless-code-review/SKILL.md
│   ├── dependency-upgrade/
│   │   ├── dependency-upgrade-breaking-change-preflight/SKILL.md
│   │   ├── java-parent-pom-dependency-upgrade/SKILL.md
│   │   ├── java-spring-boot-dependency-upgrade/SKILL.md
│   │   ├── java-spring-boot-starter-dependency-upgrade/SKILL.md
│   │   ├── java-serverless-dependency-upgrade/SKILL.md
│   │   ├── node-serverless-dependency-upgrade/SKILL.md
│   │   ├── nextjs-react-prisma-serverless-dependency-upgrade/SKILL.md
│   │   └── php-laravel-serverless-dependency-upgrade/SKILL.md
│   ├── reporting/
│   │   ├── review-upgrade-report-write/SKILL.md
│   │   └── merchant-api-spec-report-write/SKILL.md
│   ├── version-definition/
│   │   └── service-version-definition/SKILL.md
│   └── readme-update/
│       ├── readme-format-contract/SKILL.md
│       ├── readme-update/SKILL.md
│       └── backstage-api-spec-readme-update/SKILL.md
└── rules/                          # shared and service-specific Cursor rules
    ├── general/
    │   ├── snap-standards.mdc
    │   ├── save-tokens.mdc
    │   ├── report-output.mdc
    │   ├── dependencies-upgrade.mdc
    │   ├── service-version-definition.mdc
    │   ├── nextjs-react-prisma-serverless-single-service.mdc
    │   ├── nextjs-react-prisma-serverless-solid.mdc
    │   ├── nextjs-react-prisma-serverless-react-best-practices.mdc
    │   ├── nextjs-react-prisma-serverless-react-security.mdc
    │   ├── nextjs-react-prisma-serverless-react-testing.mdc
    │   ├── nextjs-react-prisma-serverless-react-performance.mdc
    │   ├── php-laravel-serverless-dependencies-upgrade.mdc
    │   ├── php-laravel-serverless-readme-format.mdc
    │   ├── enterprise-biz-platform-microservice-child.mdc
    │   ├── code-review-git-worktree.mdc
    │   ├── code-review-n-plus-one-hot-path.mdc
    │   ├── code-review-magic-numbers-hardcoding.mdc
    │   ├── code-review-sql-reserved-parameter-names.mdc
    │   ├── code-review-aws-secrets-manager.mdc
    │   ├── code-review-liquibase.mdc
    │   ├── readme-format.mdc
    │   ├── backstage-api-spec-structure.mdc
    │   ├── backstage-api-spec-servers.mdc
    │   └── backstage-api-spec-sync.mdc
    ├── observability/
    │   ├── repo-readiness-gate.mdc
    │   ├── project-naming.mdc
    │   ├── monitor-rules.mdc
    │   ├── dashboard-per-endpoint-rules.mdc
    │   └── dashboard-overview-rules.mdc
    └── <service-name>/
        └── <service-specific-rule>.mdc
```

## How the pieces fit together

- **Rules** are passive and always-on (e.g. `rules/general/snap-standards.mdc` applies to API source files). They are the normative source of truth for conventions.
- **Skills** are invokable, single-purpose procedures. Each code-review and dependency-upgrade skill is a faithful adaptation of a Snap prompt and is the authoritative step-by-step for that stack.
- **Agents** are thin personas that delegate to skills. The **orchestrators** detect the stack and route to the right reviewer or upgrader, so a developer can ask for review or dependency upgrades without naming the stack-specific agent.

```text
cursor-project-initializer ──reads README project-type──▶ root AGENTS.md + git-operations agents + code-review/dependency-upgrade agents/skills/rules (always)
                         └─ java-spring-boot / java-spring-boot-serverless ──▶ merchant-observability-assistant-orchestrator + skills/observability/* + rules/observability/*
                         └─ backstage-api-spec only ──▶ api-spec agents + skills + backstage-api-spec-* rules
                         └────────────▶ rules/<service-name> when present
                         └─ purge legacy assets ──▶ team-dependency-upgrade-* agents/skills/rules when present from older installs

code-review-orchestrator  ──detects stack──▶  java-code-reviewer ──▶ java-spring-boot-code-review (skill)
                                          │                              ├─ Maven in scope ──▶ owasp-validation ──▶ owasp-dependency-check-validation (skill)
                                          │                              └─ java-spring-boot / java-spring-boot-serverless + SM detected ──▶ aws-secrets-manager-validation ──▶ aws-secrets-manager-validation (skill)
                                          └─▶  node-serverless-code-reviewer ──▶ node-serverless-code-review (skill)
                                          └─▶  nextjs-react-prisma-serverless-code-reviewer ──▶ nextjs-react-prisma-serverless-code-review (skill)
                                          └─▶  php-laravel-serverless-code-reviewer ──▶ php-laravel-serverless-code-review (skill)
                                          └─▶  liquibase-code-reviewer ──▶ liquibase-code-review (skill) + code-review-liquibase (rule)
                                                                  └──────────▶ snap-rest-api-standards (skill) + snap-standards (rule)  [application stacks; not liquibase]
                                                                  └──────────▶ report-writer-coordinator ──▶ project-type report writer ──approved──▶ readme-updater-coordinator ──▶ project-type readme updater
                                                                               (liquibase => liquibase-report-writer; omit JaCoCo / dependency vulnerabilities / API spec; skip readme updater)

dependency-upgrade-orchestrator ──breaking-change preflight──▶ Plan mode when breaking required (never block — always plan + ask); else direct upgrade
                                  ──root .git──▶ process 1: single-repo upgrade (all types, including parent-pom → code-review-orchestrator → parent-pom-report-writer when no feature reviewer applies)
                                  ──no root .git──▶ process 2 (all parent-pom) or 3 (mixed): install assets → Jira + project list/Confluence → clone → read-only preflight all → combined Plan when any BREAKING_REQUIRED → sequential one-by-one: report + README + service-version-definer for every project; code review mandatory for every non-parent-pom
                                  ──detects stack──▶ java-parent-pom-dependency-upgrader ──▶ java-parent-pom-dependency-upgrade (skill)
                                                  ├▶ java-spring-boot-dependency-upgrader ──▶ java-spring-boot-dependency-upgrade (skill)
                                                  ├▶ java-serverless-dependency-upgrader ──▶ java-serverless-dependency-upgrade (skill)
                                                  ├▶ java-spring-boot-starter-dependency-upgrader ──▶ java-spring-boot-starter-dependency-upgrade (skill)
                                                  └▶ node-serverless-dependency-upgrader ──▶ node-serverless-dependency-upgrade (skill)
                                                  └▶ nextjs-react-prisma-serverless-dependency-upgrader ──▶ nextjs-react-prisma-serverless-dependency-upgrade (skill)
                                                  └▶ php-laravel-serverless-dependency-upgrader ──▶ php-laravel-serverless-dependency-upgrade (skill)
                                                  └▶ code-review-orchestrator (single-repo and non-parent-pom multi-project) ──▶ report-writer-coordinator ──▶ project-type report writer (parent-pom => parent-pom-report-writer)
                                                  └▶ multi-project parent-pom only ──▶ owasp-validation ──▶ parent-pom-report-writer
                                                                                              └▶ report-writer-coordinator ──▶ project-type report writer ──approved──▶ readme-updater-coordinator ──▶ project-type readme updater ──approved──▶ service-version-definer ──▶ service-version-definition (skill)

api-spec-orchestrator ──detects scope──▶ merchant-api-spec-creator ──▶ merchant-api-spec-create (skill)
                                       ├▶ merchant-api-spec-updater ──▶ merchant-api-spec-update (skill)
                                       ├▶ merchant-api-spec-bulk-generator ──▶ merchant-api-spec-bulk-generate (skill)
                                       │                                    └─per folder─▶ create / update skills
                                       create/update/bulk success ──▶ merchant-api-spec-deployment-generator ──▶ merchant-api-spec-deployment-files (skill)
                                                                            └──────────▶ report-writer-coordinator ──▶ merchant-api-spec-report-writer
                                                                            └──────────▶ readme-updater-coordinator ──▶ backstage-api-spec-readme-updater (when README/package.json alignment is needed)
                                       (+ backstage-api-spec-* and merchants-api-documentation-* rules for project-type: backstage-api-spec)

merchant-observability-assistant-orchestrator ──repo readiness──▶ ensure-repo-ready
                                             ──scan──▶ scan-endpoint-timing-logs ──▶ report-endpoint-timing-coverage
                                             ──operation timing found──▶ generate-sumo-dashboards + generate-sumo-monitors
                                             ──▶ report-sumo-upload-summary (curl commands; no upload unless asked)
                                             (+ rules/observability/* for java-spring-boot and java-spring-boot-serverless)
```

## Conventions for editing content

### Add a new agent
Create `agents/<name>.md` with frontmatter `name`, `description` (this drives delegation — invest in it), optional `model` (`inherit` or a model id), `readonly`, `is_background`. Keep the body a focused system prompt: a one-line role, a numbered "When invoked" checklist, and a "Report" section. Delegate detail to a skill rather than inlining a 2,000-word prompt.

### Add a new skill
Create `skills/<category>/<name>/SKILL.md`. The folder name **must equal** the `name` frontmatter field (lowercase, hyphens). Required frontmatter: `name`, `description` (what it does + when to use it). Optional: `paths` (globs to scope it), `disable-model-invocation`, `metadata`. Category subfolders are organizational only. Consumer repos should copy this tree into `.cursor/skills/`, which Cursor scans recursively.

### Add a new rule
Create shared rules under `rules/general/<name>.mdc` or service-specific rules under `rules/<service-name>/<name>.mdc` with frontmatter `description`, `globs`, and optionally `alwaysApply: true`. Consumer repos should copy these files into `.cursor/rules/`.

### Naming
- Agents: `<role>-<stack>`, `<role>-orchestrator`, or focused setup roles such as `cursor-project-initializer` (e.g. `java-code-reviewer`).
- Skills: `<stack>-<purpose>` (e.g. `node-serverless-code-review`).
- Keep skill filenames distinct from rule filenames.

## README format contract

Every supported `project-type` has a mandatory root `README.md` structure defined in `skills/readme-update/readme-format-contract/SKILL.md` and `rules/general/readme-format.mdc`. Canonical full examples:

| `project-type` | Reference repo |
| --- | --- |
| `backstage-api-spec` | `merchants-api-documentation` |
| `java-spring-boot` | `merchants-service` |
| `java-spring-boot-serverless` | `service-merchant-assets` |
| `node-serverless` | `merchant-services-cloud-resources` |
| `nextjs-react-prisma-serverless` | `shopify-marketing-plugin` |
| `php-laravel-serverless` | `bigcommerce-app` |
| `java-spring-boot-starter` | `snap-rules-spring-boot-starter` |
| `parent-pom` | `snap-serverless-parent` |
| `liquibase` | `snap-storelocator-schema` |

- **Code review:** pre-validation step **1b** in Java/Node review skills rejects non-compliant READMEs before substantive review.
- **Readme updaters:** after an approved report, enforce the contract first (add/fix mandatory sections and heading order), then update stale service-specific content.
- **Initializer:** always install `readme-format-contract` skill and `readme-format.mdc` rule for every supported `project-type`.

## Using the agents

- Invoke a subagent explicitly by typing `/<name>` in Agent chat (e.g. `/cursor-project-initializer configure this project`, `/code-review-orchestrator review the current branch`, `/merchant-observability-assistant-orchestrator generate Sumo dashboards`, or `/service-version-definer define the next version`), or describe the task and let the Agent delegate based on `description`.
- Skills load automatically when relevant, or run on demand via `/<skill-name>`.
- Reviewers **identify issues only — they never fix code** — and must invoke `report-writer-coordinator` after completion instead of writing `CODE_REVIEW.md` themselves.

## Project initializer contract

- The initializer reads `project-type` from the target `README.md` (`## Cursor init`) and must not guess.
- **Always install:** root `AGENTS.md`, `cursor-project-initializer`, `git-operations-coordinator`, `git-repository-cloner`, `git-repository-puller`, `report-writer-coordinator`, `readme-updater-coordinator`, the one project-type report writer matching `project-type`, the one project-type readme updater matching `project-type`, shared `save-tokens` / `report-output` / `readme-format` when present, and `skills/readme-update/readme-format-contract/` for all supported project types. Re-runs purge removed legacy assets such as `team-dependency-upgrade-coordinator`, `skills/team-dependency-upgrade/`, and `team-dependency-upgrade-*.mdc` / `upgrade-dependencies-manager.mdc` when present from older installs.
- **Always install for review/upgrade project types:** applicable code-review and dependency-upgrade orchestrators, specialists, their skills, `service-version-definer`, `skills/version-definition/service-version-definition/`, and shared rules (`snap-standards`, `code-review-git-worktree`, `code-review-n-plus-one-hot-path`, `code-review-magic-numbers-hardcoding`, `code-review-sql-reserved-parameter-names`, `dependencies-upgrade`, `service-version-definition`, `report-output`, `readme-format`). For `parent-pom`, install the dependency-upgrade orchestrator, `java-parent-pom-dependency-upgrader`, `code-review-orchestrator`, `parent-pom-report-writer`, `parent-pom-readme-updater`, `service-version-definer`, and dependency-upgrade + version-definition + readme-format skills; copy `dependencies-upgrade.mdc`, `service-version-definition.mdc`, and `readme-format.mdc` but not `snap-standards.mdc`, `code-review-git-worktree.mdc`, `code-review-n-plus-one-hot-path.mdc`, `code-review-magic-numbers-hardcoding.mdc`, `code-review-sql-reserved-parameter-names.mdc`, or `code-review-aws-secrets-manager.mdc`.
- **Install only when `project-type: liquibase`:** `code-review-orchestrator`, `liquibase-code-reviewer`, `liquibase-report-writer`, `skills/code-review/liquibase-code-review/`, `skills/reporting/review-upgrade-report-write/`, `skills/readme-update/readme-format-contract/`, and rules `code-review-git-worktree.mdc`, `code-review-liquibase.mdc`, `save-tokens.mdc`, `report-output.mdc`, `readme-format.mdc`. Do **not** install dependency-upgrade agents/skills, `service-version-definer`, a project-type readme updater, `snap-standards.mdc`, N+1/magic-numbers/SQL-reserved/AWS SM gates, or observability assets. Canonical README example: **snap-storelocator-schema**. When `project-type` is not `liquibase`, remove previously installed Liquibase reviewer/report-writer/skill/`code-review-liquibase.mdc` from the target.
- **Install only when `project-type: backstage-api-spec`:** `api-spec-orchestrator`, Merchant API spec specialists, `skills/api-spec/*`, and `backstage-api-spec-*.mdc` rules.
- **Install when `project-type` is `java-spring-boot` or `java-spring-boot-serverless`:** `merchant-observability-assistant-orchestrator`, all `skills/observability/*`, and flattened copies of `rules/observability/*.mdc` (`repo-readiness-gate.mdc`, `project-naming.mdc`, `monitor-rules.mdc`, `dashboard-per-endpoint-rules.mdc`, `dashboard-overview-rules.mdc`). Also install `aws-secrets-manager-validation` (agent), `skills/code-review/aws-secrets-manager-validation/`, and `code-review-aws-secrets-manager.mdc` (conditional Secrets Manager gate during code review). When those project types are not selected, remove previously installed observability agent, skills, those rule basenames, and the Secrets Manager validation agent/skill/rule from the target.
- **Install only when `project-type: nextjs-react-prisma-serverless`:** `dependency-upgrade-orchestrator`, `code-review-orchestrator`, `nextjs-react-prisma-serverless-dependency-upgrader`, `nextjs-react-prisma-serverless-code-reviewer`, `nextjs-react-prisma-serverless-report-writer`, `nextjs-react-prisma-serverless-readme-updater`, breaking-change preflight, `nextjs-react-prisma-serverless-dependency-upgrade`, `nextjs-react-prisma-serverless-code-review`, `snap-rest-api-standards`, `review-upgrade-report-write`, `readme-update`, `readme-format-contract`, `snap-standards`, `code-review-git-worktree`, `code-review-n-plus-one-hot-path`, `code-review-magic-numbers-hardcoding`, `code-review-sql-reserved-parameter-names`, `dependencies-upgrade`, `nextjs-react-prisma-serverless-single-service`, `nextjs-react-prisma-serverless-solid`, `nextjs-react-prisma-serverless-react-best-practices`, `nextjs-react-prisma-serverless-react-security`, `nextjs-react-prisma-serverless-react-testing`, and `nextjs-react-prisma-serverless-react-performance` rules. Service-specific rules install from `rules/shopify-marketing-plugin/` when the repo folder name matches — including `shopify-marketing-plugin-best-practices.mdc`, `shopify-marketing-plugin-security.mdc`, `shopify-marketing-plugin-performance.mdc`, `shopify-marketing-plugin-testing.mdc`, `shopify-marketing-plugin-shopify-plugin-best-practices.mdc`, and `shopify-marketing-plugin-shopify-plugin-security.mdc`. Canonical README example: **shopify-marketing-plugin** (same section contract as **merchant-services-cloud-resources**).
- **Install only when `project-type: php-laravel-serverless`:** `dependency-upgrade-orchestrator`, `code-review-orchestrator`, `php-laravel-serverless-dependency-upgrader`, `php-laravel-serverless-code-reviewer`, `php-laravel-serverless-report-writer`, `php-laravel-serverless-readme-updater`, breaking-change preflight, `php-laravel-serverless-dependency-upgrade`, `php-laravel-serverless-code-review`, `snap-rest-api-standards`, `review-upgrade-report-write`, `readme-update`, `readme-format-contract`, `snap-standards`, `code-review-git-worktree`, `code-review-n-plus-one-hot-path`, `code-review-magic-numbers-hardcoding`, `code-review-sql-reserved-parameter-names`, `php-laravel-serverless-dependencies-upgrade`, and `php-laravel-serverless-readme-format` rules. Canonical README example: **bigcommerce-app**.
- **When not `backstage-api-spec`:** do not copy those assets; remove any previously installed Merchant API spec agents, `skills/api-spec/`, and `backstage-api-spec-*.mdc` from the target.

## Agent asset freshness contract

- Every agent starts with step `0. Agent asset freshness`.
- Before doing its normal work, the agent checks target `.cursor/agents/*.md` file ages using a creation-oriented timestamp (macOS birth time with mtime fallback; Linux birth time with mtime fallback).
- If any agent file is older than **3 hours** (10800 seconds), missing when expected, or age cannot be determined, the agent runs `/cursor-project-initializer configure this project` to completion, then restarts from the freshness gate.
- `cursor-project-initializer` performs the same check but does not recursively invoke itself; stale assets mean it continues with the full install/refresh workflow.

## Code review output contract

- All code reviews use STATUS **APPROVED / REJECTED** only.
- **Git worktree rule (non-negotiable):** Untracked, unstaged, or uncommitted files alone must never cause `REJECTED`, a `Must fix` item, or a rejection rationale. Reviewers evaluate file content on the full working tree; Git-only or clean-checkout compile gates are forbidden. Findings whose only remedy is add/commit/stage files must be discarded.
- **N+1 / hot-path gate (non-negotiable for application stacks):** Application reviewers must apply `code-review-n-plus-one-hot-path`. If the feature **introduces** or **worsens** an N+1 query pattern or a request-scaling hot path on a list/search/page/batch (or equivalent) production path → **REJECTED** with Must fix items citing file/method, how I/O scales, and the expected batch/join direction. Single-resource get-by-id with a fixed query count is not a rejection by itself. Pre-existing untouched N+1 is out of scope. Skip for `liquibase`.
- **Magic numbers / configuration hardcoding gate (non-negotiable for application stacks):** Application reviewers must apply `code-review-magic-numbers-hardcoding`. If the feature **introduces** unexplained magic numbers or hardcodes configuration (URLs, secrets, env-specific hosts, tunable timeouts/TTLs/limits that belong in config) in production code → **REJECTED** with Must fix items citing file/method, the literal, and the expected named-constant or config-property direction. Idiomatic `0`/`1`/`-1`, test-only fixtures, and values already bound from config are out of scope. Pre-existing untouched literals are out of scope. Skip for `liquibase`.
- **SQL reserved parameter names gate (non-negotiable for application stacks):** Application reviewers must apply `code-review-sql-reserved-parameter-names`. If the feature **introduces** or **changes** a controller/handler query, path, request, header, or request-body JSON parameter/property name that is a SQL reserved word (including Snap-forbidden `limit` / `offset`) → **REJECTED** with Must fix items citing file/method, the forbidden name, and the expected rename (`maxRows` / `start` for pagination). Legacy sibling params are not a waiver. Pre-existing untouched handlers are out of scope. Skip for `liquibase`.
- **AWS Secrets Manager gate (conditional — non-negotiable when SM is in use):** For `project-type` `java-spring-boot` or `java-spring-boot-serverless`, `java-code-reviewer` must invoke `aws-secrets-manager-validation` (step **5b** / `code-review-aws-secrets-manager`). That specialist runs only when Secrets Manager is detected (`spring-cloud-aws-starter-secrets-manager`, `aws-secretsmanager:` import, or serverless SM → env wiring); otherwise returns `N/A` and does not block. When SM is in use, use `application-local.yml` as the effective config reference, classify MUST_SECRET vs NOT_SECRET fields, and if the feature **introduces** plaintext MUST_SECRET values in committed non-local config, missing SM wiring for new MUST_SECRET keys, incomplete migration, or secret logging → **REJECTED** with Must fix items. Pre-existing untouched SM gaps are out of scope. Plaintext credentials only in `application-local.yml` are not Must fix.
- **Liquibase best-practices / security gate (non-negotiable for `liquibase`):** For `project-type` `liquibase`, `liquibase-code-reviewer` must apply `code-review-liquibase` (plus any service-specific schema rule). If the feature **introduces** changeset best-practice violations, unguarded destructive changes, unsafe `NOT NULL`/constraint rollouts, injection risks, hardcoded secrets, or unsafe grants → **REJECTED** with Must fix items. Pre-existing untouched changesets are out of scope. Liquibase reviews do **not** require JaCoCo, dependency vulnerabilities, or API spec assessment.
- **README format gate (non-negotiable):** Before substantive review, validate root `README.md` against the `readme-format-contract` skill for the resolved `project-type`. Missing sections, wrong heading text, wrong order, missing Cursor init fields, or missing required tables/footers → **REJECTED** with Must fix items. Reviewers do not edit README during review.
- **Java** reviews use the handoff set in the `java-spring-boot-code-review` skill.
- **Node** reviews use the handoff set in the `node-serverless-code-review` skill.
- **Next.js React Prisma serverless** reviews use the handoff set in the `nextjs-react-prisma-serverless-code-review` skill, including the mandatory single-service repository gate (`nextjs-react-prisma-serverless-single-service.mdc`), **mandatory SOLID §7** (`nextjs-react-prisma-serverless-solid.mdc`), and React UI rules (`nextjs-react-prisma-serverless-react-best-practices.mdc`, `nextjs-react-prisma-serverless-react-security.mdc`, `nextjs-react-prisma-serverless-react-testing.mdc`, `nextjs-react-prisma-serverless-react-performance.mdc`) when React/TSX surfaces change.
- **Liquibase** reviews use the handoff set in the `liquibase-code-review` skill. Approved Liquibase reports include only `## Status` and `## Commit message suggestions` (Liquibase checklist); rejected reports include only `## Status` and `## Must fix`.
- Reviewers must not write `CODE_REVIEW.md`. They must invoke `report-writer-coordinator`, which routes to the project-type report writer to create or update the single ignored report under `docs/`.
- When a review ends **APPROVED**, the report/status section must not explain or add notes about the approval process.
- When a review ends **REJECTED**, the report must explain why it was rejected and include the blocking findings in **Must fix**.
- When a review report's status or merged final status is **APPROVED**, the routed project-type report writer must invoke `readme-updater-coordinator` after writing the report **except for `liquibase`** (code-review-only; no project-type readme updater). For other types, the coordinator routes to the project-type readme updater, which must enforce `readme-format-contract`, then refresh stale service-specific content inside the compliant structure.
- Reviewers must roll back any temporary edits (serverless Tomcat/shade edits, `application.yml` overwrite, transient `package-lock.json`) and verify the working tree before finishing. OWASP temporary `pom.xml` edits are rolled back by `owasp-validation`.
- **OWASP NVD data source (non-negotiable):** `owasp-validation` must attempt verification against the local NVD cache at `~/.dependency-check-data` with `autoUpdate=false` before any remote NVD API update. Use the remote-update fallback only when the local cache is missing, unusable, or the local scan fails or hangs. Report the NVD data source (`local` vs `remote`) in the OWASP handoff and `## Dependency vulnerabilities` summary row.
- For `project-type` `java-spring-boot` or `java-spring-boot-serverless`, when code review ends **APPROVED**, the reviewer must assess whether a Merchant API spec update is required from the feature diff (step **12a** in `java-spring-boot-code-review`). Pass `Required` (`Yes` or `No`) and `Rationale` in the handoff. This does not perform the spec update; it flags follow-up work in `merchants-api-documentation` when HTTP contract code changed.

## Dependency upgrade output contract

- **Three upgrade processes:** `dependency-upgrade-orchestrator` routes to **(1) existing project** when the workspace root has `.git` — single-repo upgrade with Plan mode for breaking changes; single-repo `parent-pom` still invokes `code-review-orchestrator` → `parent-pom-report-writer` (no feature review); **(2) parent POM batch** when the root has no `.git` and every selected project is `parent-pom` — combined Plan when any project is `BREAKING_REQUIRED`, then sequential parent-POM upgrades with OWASP + report + README + version definition (no `code-review-orchestrator`); **(3) mixed services batch** when the root has no `.git` and one or more projects is not `parent-pom` — combined Plan for all projects before any edits when any project is `BREAKING_REQUIRED`, then sequential upgrades one-by-one with **mandatory code review** for every non-`parent-pom` project and report + README + version definition for **every** project. **Never block breaking upgrades** — the only valid gate is Plan mode plus explicit developer acceptance.
- **Mandatory per-project deliverables (all project types):** Every dependency-upgrade workflow must produce `[project_path]/docs/review-report.md` on disk. When the report is approved, `readme-updater-coordinator` must update each project's `README.md` with the latest dependency, runtime, build/test, setup, and compatibility information, then `service-version-definer` must compute and apply the next project version per `service-version-definition` (`parent-pom` patch-only `NO_BREAKING` scope may leave the version unchanged with `version_unchanged: true`). In multi-project mode, verify report, README, and version deliverables before starting the next project.
- **Mandatory code review (non-`parent-pom`, plus single-repo `parent-pom` orchestration):** Every non-`parent-pom` dependency upgrade — single-repo or multi-project — must invoke `code-review-orchestrator` after dependency edits finish or are blocked. Never skip code review for services, plugins, serverless apps, starters, or libraries. Single-repo `parent-pom` upgrades also invoke `code-review-orchestrator`, which routes directly to `parent-pom-report-writer` without a feature reviewer. Multi-project `parent-pom` is the exception — the orchestrator runs OWASP and `parent-pom-report-writer` instead. The on-disk report must include code-review results (or the parent-POM report outcome) before the orchestrator proceeds to the next multi-project upgrade.
- **Multi-project temporary workspace:** When the workspace root has **no** `.git`, the orchestrator owns the full workflow — **do not invoke `cursor-project-initializer`**. Install the full dependency-upgrade and code-review asset set into root `.cursor/` from `merchant-art-agents`. Ask for Jira ticket id and project name(s) — single name, comma-separated list, or a [Merchants ART Confluence catalog](https://snapfinance.atlassian.net/wiki/spaces/SE/pages/9013166081/Information+Merchants+ART+projects) URL (list extracted names and require developer approval before cloning). **When the list comes from Confluence, always exclude Snap App (`snap-app`) — never clone, pull, or upgrade it.** Clone or refresh each remaining repo from `git@bitbucket.org:snap-finance-business-platform/[project-name]`, create `feature/[jira_ticket_id]` from `master`, resolve each clone's `project-type`, run read-only preflight on every project, publish **one combined Plan** when any project is `BREAKING_REQUIRED`, then upgrade **one project at a time**. Route each project by its `project-type`: **`parent-pom`** — OWASP + `parent-pom-report-writer` + README + `service-version-definer` (no code review); **all other types** — stack specialist + mandatory `code-review-orchestrator` + report + README + `service-version-definer`. When the workspace root **has** `.git`, use process **1** only.
- **Breaking-change preflight (mandatory):** `dependency-upgrade-orchestrator` must run `dependency-upgrade-breaking-change-preflight` after resolving `project-type` and before delegating to any stack-specific upgrader or editing dependency versions. When the preflight finds framework/runtime line changes, breaking or incompatible majors, or residual risk that requires a breaking target, switch to **Plan** mode, publish developer approval questions (always include **newest stable** and **latest backward-compatible** versions for every gated target) plus a migration plan, **end the turn**, and **stop** until the developer sends a **separate follow-up message** that approves the plan and answers every gate. **Never treat breaking work as a permanent block** — always publish a plan and ask for acceptance, including for `parent-pom` and `multi_project_workspace` runs. In multi-project mode, when any project is `BREAKING_REQUIRED`, publish **one combined plan** covering all affected projects before starting any upgrades. When preflight result is `NO_BREAKING`, do not switch to Plan mode and proceed directly with dependency upgrades. Stack-specific upgraders must run the same preflight when invoked directly without an orchestrator handoff.
- **Framework/runtime hard boundaries (non-negotiable):** Spring Boot major generation changes (for example `3.5.15` → `4.1.0`), Spring Framework major changes, Java baseline changes, Node.js runtime line changes, Serverless Framework major changes, and build framework/tooling generation changes are **always** `framework_runtime`, **never** `compatible_major`, and **always** require Plan-mode approval or a recorded in-chat gate decision before any manifest edit. Looking up a newer stable line does not waive approval. Never apply Spring Boot or other framework/runtime version bumps silently.
- **Newest stable version (mandatory lookup):** For every in-scope coordinate, look up the absolute latest confirmed GA/final/release version from the official registry. The newest stable version is the latest GA across **all** stable release lines — never cap to the repo's current line or highest patch on the current line. When the developer accepts a framework/runtime or breaking upgrade, apply the confirmed newest stable target — never an older stable on a prior line (for example, Spring Boot 4.1.0 when that is the newest GA, not 4.0.7).
- **Stable-only recommendation (non-negotiable):** Recommend, propose, and apply **only stable** versions. Never recommend unstable/pre-release versions unless the developer explicitly states in chat that an unstable version is accepted and waives the stable-only policy. When an unstable version is applied, record the waiver in the upgrade handoff and require every final suggested git commit message to mention that the developer explicitly accepted the unstable version and waived the stable-only policy, including the coordinate and unstable version applied.
- All dependency upgrades use **Status APPROVED / Status REJECTED** only.
- Java/Maven dependency upgraders must first determine whether the target is a multi-module Maven repo by inspecting the root POM `<modules>` and nested `pom.xml` files. They must discover every `pom.xml` in the target repo, excluding build/generated folders, and treat the root POM plus all submodule POMs as the Maven upgrade scope. They must update every POM that declares or overrides the dependency, BOM, plugin, Java level, or version property being upgraded; root-only updates are incomplete when module POMs still pin older versions.
- **Maven version properties centralization (mandatory via `dependency-upgrade-orchestrator` step 5.5):** Do not specify dependency/plugin versions directly in declarations. Centralize every project-level pin in `<properties>` and reference `${…}`; omit `<version>` when parent/BOM already manages the coordinate. Literal inline versions on dependency/plugin declarations are incomplete upgrade output.
- **Company-approved parent baseline (non-`parent-pom` workflows):** For `java-spring-boot`, `java-spring-boot-serverless`, `java-spring-boot-job`, and external-parent `java-spring-boot-starter` repositories, treat every version declared or managed by the external/platform parent POM as the latest company-approved baseline. Java dependency upgraders must **not** suggest upgrading the external parent POM, bumping `<parent><version>`, comparing parent-managed coordinates to newer public GA releases, or routing to `java-parent-pom-dependency-upgrader` during a service upgrade. Upgrade scope is project-level explicit version pins plus npm/Serverless manifests when applicable. Removing stale local overrides that duplicate parent management is required.
- **Parent-managed dependency precedence:** Before changing any dependency or plugin version in a service or child module POM, Java dependency upgraders must resolve the effective parent chain and imported BOMs. If the coordinate is already declared or managed by the parent POM, an imported BOM, or a parent-owned property, they must **not** add, retain, or bump a local `<version>`, local version property, or child `dependencyManagement` override. They must remove redundant local version overrides so parent/BOM management wins. Local overrides may remain only when service-specific, explicitly documented in the handoff, and justified. When `project-type` is `parent-pom`, parent-owned coordinates are upgraded in the parent repository per `java-parent-pom-dependency-upgrade`.
- **Java parent POM** upgrades follow `java-parent-pom-dependency-upgrade` and must invoke `code-review-orchestrator` after dependency edits finish in single-repo mode. In `multi_project_workspace` mode with `project-type: parent-pom`, skip `code-review-orchestrator`; the orchestrator runs OWASP and `parent-pom-report-writer` instead. They must not invoke `report-writer-coordinator` directly from the upgrader.
- **Java Spring Boot starter** upgrades follow `java-spring-boot-starter-dependency-upgrade` and must invoke `code-review-orchestrator` after dependency edits finish. They must preserve starter-library contracts such as artifact coordinates, `@AutoConfiguration` imports, `@ConfigurationProperties` prefixes, public APIs, bean names, and consumer override behavior unless an explicit breaking-change gate is accepted.
- **Java serverless** upgrades follow `java-serverless-dependency-upgrade` and must invoke `code-review-orchestrator` after dependency edits finish with one combined Maven + npm handoff. They must not create npm side reports such as `security-exception-npm-serverless-*.md`; npm package results belong in `## Updated dependencies` via the single final report.
- **Node serverless** upgrades follow `node-serverless-dependency-upgrade` and must invoke `code-review-orchestrator` after dependency edits finish.
- **Next.js React Prisma serverless** upgrades follow `nextjs-react-prisma-serverless-dependency-upgrade` (including SOLID preservation during migration refactors per `nextjs-react-prisma-serverless-solid.mdc`) and must invoke `code-review-orchestrator` after dependency edits finish.
- **PHP Laravel serverless** upgrades follow `php-laravel-serverless-dependency-upgrade` and must invoke `code-review-orchestrator` after dependency edits finish with one combined Composer + npm handoff. They must not create Composer or npm security side reports; audit results belong in `## Dependency vulnerabilities` via the single final report.
- **No validation or code review in upgraders:** Dependency upgraders apply dependency edits only. They must not run Maven/npm build, test, lint, OWASP, npm audit, local startup, JaCoCo, nyc coverage, or any code review. Validation, audit, coverage, and code review belong to the automatic post-upgrade `code-review-orchestrator` path.
- **Automatic post-upgrade code review:** Single-repo upgraders (including `java-parent-pom-dependency-upgrader`) must invoke `code-review-orchestrator` automatically when dependency edits finish or are blocked — never skip for multi-project service/plugin/serverless/library upgrades. **`parent-pom` multi-project exception:** In `multi_project_workspace` mode, skip `code-review-orchestrator`; the orchestrator runs OWASP and `parent-pom-report-writer` instead. The orchestrator routes to the correct reviewer when applicable, or invokes `report-writer-coordinator` once when no reviewer applies or when edits could not be completed. Exactly one report at `docs/review-report.md` must exist at the end of the full workflow per project.
- Upgraders must not write `docs/dependency-upgrade-report.md`, `CODE_REVIEW.md`, npm security side reports, or any other report directly. Upgraders must not invoke `report-writer-coordinator` directly.
- When a dependency upgrade ends **Status APPROVED**, the report/status section must not explain or add notes about the approval process.
- When a dependency upgrade ends **Status REJECTED**, the report must explain why it was rejected and include the blocking findings in **Must fix**.
- When a dependency-upgrade report's status or merged final status is **APPROVED**, the routed project-type report writer must invoke `readme-updater-coordinator` after writing the report. The coordinator routes to the project-type readme updater, which must enforce `readme-format-contract`, then refresh stale dependency, runtime, build/test, setup, or compatibility content inside the compliant structure. After README update on approved outcomes, `dependency-upgrade-orchestrator` must invoke `service-version-definer` to apply the next version per `service-version-definition`.
- Major dependency/plugin/BOM upgrades are allowed only when the target is stable, compatible with the existing accepted tech stack, does **not** cross a framework/runtime hard boundary, and does not require framework, runtime, API, code, or configuration migration. A major version number alone is not a breaking change; if compatibility is proven and no framework/runtime line changes, the upgrader must apply the newest compatible stable major. Spring Boot major generation changes (for example `3.5.15` → `4.1.0`) always require explicit developer approval — never classify them as compatible-major or apply them without Plan-mode approval or a recorded in-chat gate decision.
- When a major dependency/plugin/BOM/framework/runtime target is applied because it is verified compatible or because the developer explicitly accepted the framework/runtime or breaking upgrade, the upgrader must perform a full compatibility closure pass. That means update every dependency, BOM, plugin, runtime, peer, Java/Spring/Node/Serverless line, lockfile, and configuration required to make the accepted target mutually compatible; single-package major bumps are incomplete when the surrounding dependency set remains incompatible.
- Spring ecosystem BOMs and libraries with **project-level explicit version pins** must align to the newest stable line compatible with the **company-approved Spring Boot baseline** declared in the parent/root POM. Do not treat a newer public Spring Boot GA as an upgrade target when Boot is parent-managed. For every Spring dependency managed by that Spring Boot BOM, remove local version overrides in root and submodule POMs so Spring Boot management wins. If a local dependency declaration, dependencyManagement entry, or version property overrides the same Spring-managed dependency, remove that local version override so Spring Boot management wins. This is a narrow exception to the "do not delete dependencies/plugins" rule: remove stale version overrides, not the dependency itself, unless an override-only dependencyManagement entry has no purpose except pinning a different version.
- Framework or runtime line upgrades must always pause before editing and ask this exact question: "I found that this upgrade changes a framework or runtime line. Would you like to accept the framework/runtime upgrade and continue, or should I stay on the latest stable version compatible with the current stack instead?" This is mandatory even when the proposed framework target appears compatible. Parent framework/runtime gates include Spring Boot major/minor generation changes, Spring Framework major changes, Java baseline changes, Node.js runtime changes, Serverless Framework major changes, and build framework/tooling line changes.
- Spring Cloud, Spring Cloud AWS, AWS Serverless Java Container, Serverless plugins, and other ecosystem BOM/library upgrades are not framework/runtime gates when they simply align to the currently accepted framework/runtime lines and do not require API, code, or configuration migration. If one of these upgrades requires a parent framework/runtime change or migration, the parent framework/runtime or breaking-change gate applies before editing.
- Breaking or incompatible dependency upgrades must pause before editing and ask this exact question: "I found that upgrading this library would introduce a breaking change. Would you like to accept the breaking change and continue with the upgrade, or should I upgrade to the latest backward-compatible version instead?" This applies to **any dependency upgrade that introduces a breaking change or stack incompatibility**: unsupported Spring/Java/Node/Serverless combinations, incompatible BOMs, peer/platform conflicts, Maven/npm dependency or plugin semver-major bumps with migration requirements, and release notes or migration guides that require code/configuration work. If the developer accepts, the upgrader must upgrade the dependency and the rest of the dependency/platform set required for compatibility with the accepted target.
- If the developer explicitly declines a breaking target, the upgrader uses the latest stable backward-compatible version, records in the dependency-upgrade handoff that final commit messages must mention the user accepted the risk of not upgrading that dependency because the newer target introduces a breaking change, and continues the rest of the upgrade process. If no valid post-plan follow-up has been collected, the upgrader must stop, publish Section A if not yet shown, and ask in chat before continuing; it must not treat silence, upgrade scope ("upgrade to latest"), Task-prompt instructions, or a missing response as a decision.
- If the latest stable current-line fallback leaves unresolved production risk, record the known risk and developer gate decisions in the dependency-upgrade handoff for the code-review path. Do not run audits during the upgrade phase to obtain that evidence.
- When residual current-line risk is explicitly accepted and the result is approved, every suggested commit message must mention the accepted risk or Security exception/reference in the vulnerable-deps checklist text. Never imply the risk was resolved when it was only accepted.
- When the developer explicitly accepted an unstable/pre-release dependency version and waived the stable-only policy, every suggested commit message must mention that the developer explicitly accepted the unstable version and waived the stable-only policy, including the coordinate and unstable version applied.
- Approved dependency-upgrade commit suggestions use `## Commit message suggestions` in reports, followed by exactly four labeled options in this order: `Copy option 1 — Short (subject only)`, `Copy option 2 — Conventional style`, `Copy option 3 — More concise conventional`, and `Copy option 4 — Minimal (ticket + one line)`. Each label is followed by one fenced copy-paste commit message, and every message ends with `Checklist: [x] compiles, [x] local startup, [x] tests/coverage, [x] vulnerable deps (<concise audit/security status>)`. `report-writer-coordinator` owns building these from detected changes for every `project-type`; upgraders must not omit the post-upgrade report path that reaches the coordinator, and must not themselves invent a separate commit-suggestion channel.
- Upgraders must not stage or commit unless the developer explicitly asks.

## Service version definition contract

- **`service-version-definer`** may be invoked standalone or is **mandatory** at the end of every **approved** `dependency-upgrade-orchestrator` run (after README update) for versioned project types.
- **`parent-pom` scheme:** `{springBootMajor}.{minor}.{patch}-SNAPSHOT` — first segment MUST match the Spring Boot major from the parent POM; update the project version **only** on major or minor scope (Spring Boot major change or platform/breaking/framework changes); **never** bump parent POM project version for patch-only compatible dependency upgrades; `-SNAPSHOT` is mandatory when the version is updated.
- **Services, plugins, libraries, serverless:** regular semver `MAJOR.MINOR.PATCH` from Git branch type and change scope — `bugfix/`/`hotfix/` or compatible dependency-only upgrade → patch; non-backward-compatible change → major; backward-compatible feature → minor.
- Apply versions to Maven `pom.xml`/`revision`, `package.json`, `composer.json`, and README version metadata when the project-type contract requires it. Do not bump external/platform parent versions from service workflows.
- When `parent-pom` patch-only scope leaves the version unchanged, report `version_unchanged: true` and `{previous_version}` explicitly — do not edit manifests or README version metadata.
- Skip version definition when the dependency-upgrade report is `REJECTED` or `project-type` is `backstage-api-spec` or `liquibase`.
- Authoritative procedure: `skills/version-definition/service-version-definition/SKILL.md`; passive rule: `rules/general/service-version-definition.mdc`.

## Shared report output contract

- `report-writer-coordinator` is mandatory after every completed code review, dependency upgrade, or Merchant API spec workflow. It **always** builds four git commit message suggestions from detected working-tree and handoff changes for **every** `project-type` (including `parent-pom` and `backstage-api-spec`), attaches them as `commit_message_suggestions`, then routes to exactly one project-type report writer; the specialist writes the report. For `backstage-api-spec`, commit suggestions are surfaced in the coordinator chat report only — they are not embedded in `docs/api-spec-report.md`.
- For dependency upgrades routed through `code-review-orchestrator`, upgraders must not invoke `report-writer-coordinator` directly. The orchestrator or the routed code reviewer invokes `report-writer-coordinator` exactly once at the end to create the single merged or standalone report.
- For code review and dependency upgrades, the routed project-type report writer creates or updates exactly one report at `docs/review-report.md` and ensures the report path is ignored in `.gitignore`.
- For Merchant API spec workflows, the routed project-type report writer creates or updates exactly one report at `docs/api-spec-report.md` and ensures the report path is ignored in `.gitignore`.
- For code review and dependency upgrades, after writing an approved standalone report or approved merged final report, the routed project-type report writer must invoke `readme-updater-coordinator`. The coordinator routes to the project-type readme updater. Do not invoke `readme-updater-coordinator` for rejected reports.
- For Merchant API spec workflows, invoke `readme-updater-coordinator` only when README or root `package.json` alignment is needed after completed API spec work. The coordinator routes to `backstage-api-spec-readme-updater`.
- For code review and dependency upgrades, the Jira ticket id is the report title.
- Approved reports use only `## Status`, optional `## Updated dependencies` when dependency rows exist, required coverage metrics (`## JaCoCo metrics` for Java, `## PHPUnit metrics` for PHP), required `## Dependency vulnerabilities` covering OWASP plus Composer and npm when applicable, optional `## API spec update` when `project-type` is `java-spring-boot` or `java-spring-boot-serverless` and code review is approved, and `## Commit message suggestions`. **Exception — `liquibase`:** approved reports use only `## Status` and `## Commit message suggestions` (no JaCoCo, dependency vulnerabilities, or API spec). Rejected Liquibase reports use only `## Status` and `## Must fix`.
- Approved code-review commit suggestions for `java-spring-boot` and `java-spring-boot-serverless` use the same four labeled options as other review/upgrade reports, and every message ends with `Checklist: [x] compiles, [x] local startup, [x] tests/coverage, [x] vulnerable deps (<concise audit/security status>), [x] api spec update (required)` or `[x] api spec update (not required)` matching the assessment. Other project types keep the four-item checklist without the API spec item.
- Rejected reports use `## Status`, required `## Dependency vulnerabilities` covering OWASP plus npm when applicable, and `## Must fix`. When dependency upgrade is already **APPROVED** and code review later returns **REJECTED** for the same Jira ticket, the merged rejected report must preserve the approved dependency-upgrade sections (`## Updated dependencies`, coverage metrics when present, dependency vulnerabilities/audit rows, developer risk/security decisions, and dependency-upgrade commit suggestions) and add the code-review rejected status plus `## Must fix`.
- `## Updated dependencies` is a table with `Dependency | Source | Previous version | New version`, where `Source` is `MAVEN`, `NPM`, or `COMPOSER`.
- If both code review and dependency upgrade results are present, the report `## Status` section is one table with `Dependency upgrade status`, `Code review status`, and `Final status`.
- When code review and dependency upgrade both complete for the same Jira ticket, the project-type report writer must read the existing `docs/review-report.md`, normalize the existing report plus incoming handoff by work type, preserve both completed results, and merge them into the same file. The invocation order must not matter: dependency-upgrade first then code-review, and code-review first then dependency-upgrade, must produce the same combined status table and combined information. Approved merged reports regenerate commit message suggestions so they cover both the dependency-upgrade and code-review changes; exact duplicate commit message bodies must be removed, and the final approved report must contain four distinct combined options. The writer must not overwrite the prior result or create a second report.
- Report writers must read `docs/review-report.md` back from disk after writing and verify the status cells match the handoff. Reviewers and orchestrators must not claim a workflow is complete until the on-disk report status matches the stated outcome. A later rejected code-review rerun must replace any stale code-review `APPROVED` cell; chat summaries that say `REJECTED` while the file still shows `APPROVED` are invalid.
- Do not add extra trailing sections or notes after the required report sections.
- For Merchant API spec workflows, specialists invoke `report-writer-coordinator`, which routes to `merchant-api-spec-report-writer` for `backstage-api-spec`. That writer uses `docs/api-spec-report.md` and keeps exactly two sections: `## Create or Updated API specs` and `## Skipped or failed`. The orchestrator always invokes `report-writer-coordinator` with the aggregated handoff before claiming success. Reviewers and orchestrators must not claim an API-spec workflow is complete until the on-disk run report reflects the handoff.
- API spec bulk runs overwrite the API spec run report for the current run; single create/update/deployment-file runs merge rows by repo into the two-section API report.

## API spec output contract

- API-spec agents operate on the `merchants-api-documentation` repo (`project-type: backstage-api-spec`) and treat the source Java service as the source of truth.
- **Single create** follows `merchant-api-spec-create` (new `[api_name]/src/` split layout); **single update** follows `merchant-api-spec-update` (controller-by-controller audit + bundle rebuild); **bulk** follows `merchant-api-spec-bulk-generate`. `api-spec-orchestrator` invokes `merchant-api-spec-deployment-generator` **only** after at least one successful `Created` or `Updated` row. **Deployment files** follows `merchant-api-spec-deployment-files` and does not run standalone. Every API-spec specialist and the orchestrator **must** invoke `report-writer-coordinator`, which routes to the project-type report writer (`merchant-api-spec-report-writer` for `backstage-api-spec`). Specialists must never write `docs/api-spec-report.md` directly. The orchestrator invokes `report-writer-coordinator` with the full aggregated handoff as the authoritative final report write. The routed writer produces the two-section report at `docs/api-spec-report.md` (`## Create or Updated API specs` and `## Skipped or failed`).
- `merchant-api-spec-deployment-files` regenerates `openapi-backstage.yaml` and creates or refreshes `catalog-info.yaml` only for the specific API folder(s) in the explicit `api_folders` handoff from a create or changed update in the same orchestrator run. It never processes all APIs, never uses Git or README lists for scope, and does not clone Java service repos.
- `api-spec-orchestrator` reads git clone commands from the local `README.md` **Clone Merchant ART service repositories** tables into `[readme_clone_rows]` before clone/sync work. It deletes only temporary `.py` / `.sh` scripts created for the run at the end and must not delete the `projects/` folder.
- Create, update, and bulk workflows enforce the `develop` branch gate on the service clone and HTTPS-only, lower-environment-only `servers` (no prod/training/local; prefer direct over API Gateway). Deployment-files workflows run only after successful create or update handoff folders and do not clone Java service repos. On any blocker, agents stop the affected spec rather than forcing a partial result, and must not stage or commit unless the developer explicitly asks.

## Security considerations

- Follow `save-tokens.mdc`; never hardcode or commit secrets.
- OWASP scans prefer the local NVD cache at `~/.dependency-check-data` (`autoUpdate=false`) before triggering a remote NVD API update. The test-only NVD API key embedded in the Java OWASP procedure is for local runs only and must never be committed to a shared branch.

## Roadmap

This structure is built to scale: more reviewers, generators, and upgrade agents will be added under `agents/` and `skills/` following the conventions above.
