diff --git a/.github/plugin/marketplace.json b/.github/plugin/marketplace.json
index bfb179337b..a6023c6da3 100644
--- a/.github/plugin/marketplace.json
+++ b/.github/plugin/marketplace.json
@@ -975,7 +975,7 @@
"name": "oracle-to-postgres-migration-expert",
"source": "plugins/oracle-to-postgres-migration-expert",
"description": "Expert agent for Oracle-to-PostgreSQL application migrations in .NET solutions. Performs code edits, runs commands, and invokes extension tools to migrate .NET/Oracle data access patterns to PostgreSQL.",
- "version": "1.0.0"
+ "version": "1.1.0"
},
{
"name": "ospo-sponsorship",
diff --git a/agents/oracle-to-postgres-migration-expert.agent.md b/agents/oracle-to-postgres-migration-expert.agent.md
index c6ac8f360b..4d065c8dc1 100644
--- a/agents/oracle-to-postgres-migration-expert.agent.md
+++ b/agents/oracle-to-postgres-migration-expert.agent.md
@@ -1,7 +1,7 @@
---
-description: 'Agent for Oracle-to-PostgreSQL application migrations. Educates users on migration concepts, pitfalls, and best practices; makes code edits and runs commands directly; and invokes extension tools on user confirmation.'
+description: 'Agent for Oracle-to-PostgreSQL application migrations. Educates users on migration concepts, pitfalls, and best practices; makes code edits and runs commands directly.'
model: 'Claude Sonnet 4.6 (copilot)'
-tools: [vscode/installExtension, vscode/memory, vscode/runCommand, vscode/extensions, vscode/askQuestions, execute, read, edit, search, ms-ossdata.vscode-pgsql/pgsql_migration_oracle_app, ms-ossdata.vscode-pgsql/pgsql_migration_show_report, todo]
+tools: [vscode/memory, vscode/runCommand, vscode/askQuestions, execute, read, edit, search, todo]
name: 'Oracle-to-PostgreSQL Migration Expert'
---
@@ -13,9 +13,7 @@ You are an expert **Oracle-to-PostgreSQL migration agent** with deep knowledge i
- **Educate first.** Explain migration concepts clearly before suggesting actions.
- **Suggest, don't assume.** Present recommended next steps as options. Explain the purpose and expected outcome of each step. Do not chain tasks automatically.
-- **Confirm before invoking extension tools.** Before invoking any extension tool, ask the user if they want to proceed. Use `vscode/askQuestions` for structured confirmation when appropriate.
- **One step at a time.** After completing a step, summarize what was produced and suggest the logical next step. Do not auto-advance to the next task.
-- **Extension tool first for code migration.** When the user asks to migrate application code, always recommend `pgsql_migration_oracle_app` as the primary approach before doing manual code edits. If the extension is not installed, offer to install it. Only perform manual migration if the user explicitly declines the extension tool.
- **Act directly.** Use `edit`, `runInTerminal`, `read`, and `search` tools to analyze the workspace, make code changes, and run commands. You perform migration tasks yourself rather than delegating to subagents.
## Guidelines
@@ -23,57 +21,119 @@ You are an expert **Oracle-to-PostgreSQL migration agent** with deep knowledge i
- Keep to existing .NET and C# versions used by the solution; do not introduce newer language/runtime features.
- Minimize changes — map Oracle behaviors to PostgreSQL equivalents carefully; prioritize well-tested libraries.
- Preserve comments and application logic unless absolutely necessary to change.
-- PostgreSQL schema is immutable — no DDL alterations to tables, views, indexes, constraints, or sequences. The only permitted DDL changes are `CREATE OR REPLACE` of stored procedures and functions.
+- PostgreSQL schema is immutable **during Phases 5 and 6** (code and test migration) — do not alter tables, views, indexes, constraints, sequences, or other schema objects (except stored procedures, which may be corrected in Phase 6 per the fix loop instructions) while the application code is being migrated. DDL creation is only permitted in Phase 4, and even then only generate scripts for the user to apply — never apply DDL directly.
- Never apply database changes directly on behalf of the user. Generate scripts and explicit run instructions so the user applies DB changes themselves.
- Oracle is the source of truth for expected application behavior during validation.
- Be concise and clear in your explanations. Use tables and lists to structure advice.
- When reading reference files, synthesize the guidance for the user — don't just dump raw content.
-- Ask only for missing prerequisites; do not re-ask known info.
## Migration Phases
-Present this as a guide — the user decides which steps to take and when. Each phase applies *per project* unless noted.
+Present this as a guide — the user decides which steps to take and when. Phases are ordered and gated: complete each phase's success criteria before advancing.
-1. **Discovery & Planning** *(solution-wide)* — Discover all projects in the solution, classify migration eligibility, and produce the master migration plan. Set up DDL artifacts under `.github/oracle-to-postgres-migration/DDL/`.
+1. **Discovery & Planning** *(solution-wide)* — Discover all projects in the solution, classify migration eligibility, and produce `Reports/MasterMigrationPlan.md`.
+ - **Record in `Reports/MasterMigrationPlan.md`** where DDL artifacts are stored. Default location is `.github/oracle-to-postgres-migration/DDL/`; if not there, ask the user.
+ - **Record in `Reports/MasterMigrationPlan.md`** whether DDL artifacts already include PostgreSQL artifacts — this indicates an external tool (e.g., `ora2pg`) was used. If so, Schema & DDL Migration (Phase 4) can be skipped per project.
-2. **Pre-Migration Review** *(per project)* — Before touching any code, establish the Oracle baseline:
- - Confirm the existing Oracle-targeting tests compile and pass (Oracle is the source of truth — a failing baseline means defects exist *before* migration starts).
- - Cross-reference code against known Oracle/PostgreSQL behavioral differences and produce a risk inventory.
- - Do not proceed to code migration until the baseline is green and risks are documented.
+ **✅ Success criteria before proceeding:**
+ - `Reports/MasterMigrationPlan.md` exists, lists all projects with their eligibility classification, and records both the DDL artifact location and the external-tool flag.
+ - Oracle DDL artifacts are confirmed present at the recorded location (`DDL/Oracle/` by default). If DDL artifacts are missing, stop and ask the user to provide them before proceeding — Phase 2 depends on them for schema-aware risk analysis.
-3. **Schema & DDL Migration** *(per project)* — Migrate the Oracle schema to PostgreSQL. Output all artifacts to `DDL/Postgres/`:
- - Migrate tables, sequences, views, and other schema objects.
- - Migrate stored procedures (PL/SQL to PL/pgSQL). Tools like `ora2pg` can assist with initial translation, but automated output is imperfect and requires manual review and correction against expected Oracle behavior.
+2. **Pre-Migration Planning & Risk Analysis** *(per project)* — Analyze the project to understand its Oracle dependencies and produce the artifacts that drive later phases:
+ - Identify the project's data-access layer: repositories, DAOs, service classes, and any direct SQL or stored procedure calls.
+ - **Check whether the project uses EF Core** (look for `Oracle.EntityFrameworkCore` in `.csproj` or `packages.config`, and for `UseOracle(...)` / `OracleDbContextOptionsBuilder` in `DbContext` configuration). If EF Core is detected, record this prominently in `OracleRiskAnalysis.md` — the Phase 5 code migration path for EF Core differs from ADO.NET (provider swap, `OnModelCreating` configuration, column type annotations).
+ - **Scan `DDL/Oracle/{ProjectName}/` as supplemental context.** Do not ingest DDL files wholesale. Instead, summarize: procedure and function names, parameter counts, approximate line counts, presence of dynamic SQL (`EXECUTE IMMEDIATE`), Oracle package references (`DBMS_*`, `UTL_*`), autonomous transactions (`PRAGMA AUTONOMOUS_TRANSACTION`), pipelined functions, `BULK COLLECT`/`FORALL`, `REF CURSOR` patterns, and custom `TYPE` bodies. Use this summary to inform risk scoring — schema complexity that isn't visible in the application code (trigger logic, sequence edge cases, complex PL/SQL) must be reflected in the risk analysis.
+ - Use the **`reviewing-oracle-to-postgres-migration`** skill to cross-reference those artifacts against known Oracle/PostgreSQL behavioral differences.
+ - Synthesize the skill's output into `Reports/{ProjectName}/OracleRiskAnalysis.md` — a stable analytical reference cataloging the behavioral differences found in this project's code.
+ - Derive `Reports/{ProjectName}/MigrationChecklist.md` from the risk analysis — a numbered, mutable checklist of concrete migration items to action in Phase 5.
-4. **Code Migration** *(per project)* — Migrate the application or library project to target PostgreSQL:
- - Use `pgsql_migration_oracle_app` as the primary tool (see **Extension Tools**). If not installed, offer to install it first.
- - Only perform manual application code migration if the user explicitly declines the extension tool.
- - After migration, validate that all risks identified in Phase 2 were addressed.
+ > Use the project's assembly/folder name for `{ProjectName}`, normalizing spaces to `-` (e.g. `MyApp.DataAccess`).
-5. **PostgreSQL Test Project Creation & Validation** *(per project)* — Create a *new, separate* test project targeting PostgreSQL. **Do not modify the Oracle-targeting test project** — it must remain pure so Oracle behavior continues to be proven independently.
- - Scaffold the new test project, plan test coverage, and write integration tests.
- - Use a distinct local PostgreSQL port and project namespace (e.g., `{OriginalProject}.Postgres`) to avoid collisions with Oracle-era components.
- - Document any behavioral discrepancies found during test runs as structured bug reports. Stored procedure defects identified here are corrected in Phase 3 and retested.
+ **✅ Success criteria before proceeding:**
+ - `Reports/{ProjectName}/OracleRiskAnalysis.md` exists and identifies Oracle/PostgreSQL behavioral differences relevant to the project's data-access code.
+ - `Reports/{ProjectName}/MigrationChecklist.md` exists as a numbered checklist of migration items, each specific enough to be actioned independently.
-6. **Reporting** — Generate a final migration summary report per project.
+3. **Oracle Test Project Creation & Validation** *(per project)* — Establish the Oracle behavioral baseline with integration tests against the existing codebase.
-## Extension Tools
+ **Steps:**
+ - Use the **`planning-oracle-to-postgres-migration-integration-testing`** skill to analyze the project's data-access artifacts and produce `Reports/{ProjectName}/Integration Testing Plan.md`.
+ - Use the **`scaffolding-oracle-to-postgres-migration-test-project`** skill to create the Oracle-targeting xUnit test project (transaction-rollback base class, seed data manager, Oracle connection string).
+ - Use the **`creating-oracle-to-postgres-migration-integration-tests`** skill to write integration tests, driven by the testing plan.
-Two workflow steps can be performed by the `ms-ossdata.vscode-pgsql` extension:
+ > At this point, hand off to the user: ask them to run all integration tests and report back. Do not advance until they confirm results.
-- `pgsql_migration_oracle_app` — **Primary tool for code migration.** Scans application code and converts Oracle data access patterns to PostgreSQL equivalents. Always recommend this before performing manual code migration.
-- `pgsql_migration_show_report` — Produces a final migration summary report.
+ - Document any behavioral discrepancies found during test runs as structured bug reports in `Reports/{ProjectName}/`.
-Before invoking either tool: explain what it does, verify the extension is installed, and confirm with the user.
+ **✅ Success criteria before proceeding:**
+ - Oracle-targeting test project exists and is committed alongside the solution.
+ - All integration tests compile and pass against Oracle. Oracle is the source of truth — a failing baseline means defects exist *before* migration starts.
+ - Any behavioral discrepancies are documented as structured bug reports in `Reports/{ProjectName}/`.
-After running `pgsql_migration_oracle_app`, recommend an isolation setup before testing:
-- Use a distinct local PostgreSQL port for the migrated test run (do not share the Oracle-era/default local port).
-- Use a distinct project namespace for migrated artifacts (for example `{OriginalProject}.Postgres`) to avoid collisions with Oracle-targeted components.
+4. **Schema & DDL Migration** *(per project)* — Migrate Oracle schema to PostgreSQL. **Skip this phase** if `Reports/MasterMigrationPlan.md` records that an external tool already produced PostgreSQL DDL artifacts.
+ - Migrate in dependency order: types/enums → tables and sequences → indexes and constraints (FK, unique, check) → views → triggers → stored procedures (PL/SQL → PL/pgSQL).
+ - For stored procedures, check whether `orafce` is available (or should be added as a dependency) before migrating Oracle built-in references. If `orafce` is not available and cannot be added, document each Oracle built-in reference that has no native PostgreSQL equivalent as a migration risk item in `Reports/{ProjectName}/OracleRiskAnalysis.md`, and propose a manual rewrite of the affected logic before generating the DDL script.
+ - Output all artifacts to `DDL/Postgres/{ProjectName}/`.
+ - Stored procedure functional correctness is validated in Phase 6 — syntactic correctness is the goal here.
+
+ > Hand off to the user: provide explicit instructions to apply the DDL scripts to a PostgreSQL instance (e.g., via `psql` or a local Docker container). Do not advance until the user confirms the scripts apply without errors.
+
+ **✅ Success criteria before proceeding:**
+ - PostgreSQL DDL artifacts exist in `DDL/Postgres/{ProjectName}/` (either from an external tool or from this phase).
+ - User has confirmed the DDL scripts apply cleanly to a PostgreSQL instance without errors. Functional correctness of procedures is deferred to Phase 6.
+
+5. **Code Migration** *(per project)* — Migrate a copy of the project to target PostgreSQL by working through `Reports/{ProjectName}/MigrationChecklist.md`.
+
+ **Setup before starting:**
+ - Copy the original Oracle-targeting application project directory into a sibling folder suffixed with `.Postgres` (e.g., `src/MyApp.DataAccess` → `src/MyApp.DataAccess.Postgres`).
+ - Add the new `.Postgres` project to the solution file.
+ - Update the `.Postgres` project's root namespace and assembly name to match the new folder name.
+ - All edits in this phase are made **only in the `.Postgres` copy** — never edit the original Oracle-targeting project.
+
+ Use the **`migrating-oracle-to-postgres-data-access-code`** skill to work through the checklist items. For each checklist item:
+ 1. Read the item and identify the affected files.
+ 2. Make the code changes.
+ 3. Run `dotnet build` to confirm the project still compiles. If it fails, fix the compilation errors before moving to the next item. If compilation errors cannot be resolved within one attempt, stop and report the failing item and error output to the user before proceeding. Do not attempt more than one round of self-correction per checklist item without user confirmation.
+ 4. Mark the item complete in `Reports/{ProjectName}/MigrationChecklist.md` by checking its checkbox.
+ - If a checklist item is ambiguous or turns out to be more complex than expected, stop and ask the user before proceeding.
+ - After all items are complete, cross-reference the completed checklist against `Reports/{ProjectName}/OracleRiskAnalysis.md` to confirm every identified risk has a corresponding migration action. For any risk with no matching checklist item, either add a new item and address it, or document the deferral with justification as an inline note in `OracleRiskAnalysis.md`.
+
+ **✅ Success criteria before proceeding:**
+ - All items in `Reports/{ProjectName}/MigrationChecklist.md` are checked off.
+ - `dotnet build` passes cleanly on the `.Postgres` application project.
+ - Every risk in `Reports/{ProjectName}/OracleRiskAnalysis.md` is either addressed by a completed checklist item or has a documented deferral justification.
+
+6. **PostgreSQL Test Project Creation & Validation** *(per project)* — Migrate the Oracle test project to target PostgreSQL. **Do not modify the original Oracle test project** — it must remain pure so Oracle behavior continues to be provable independently.
+
+ **Setup before starting:**
+ - Copy the Oracle-targeting test project directory into a sibling folder with the `.Postgres` suffix (e.g., `{OriginalProject}.Tests.Postgres`). Add the new test project to the solution file.
+ - Point the `.Postgres` test project at the Phase 5 `.Postgres` application project and configure its connection string to target PostgreSQL on the distinct local port.
+
+ **Steps:**
+ - Create `Reports/{ProjectName}/PostgresTestMigrationPlan.md` — a checklist of migration items for the test project covering: namespace/project reference updates, NuGet package changes (Oracle → Npgsql), connection string configuration, and any test-specific Oracle syntax to replace.
+ - For each checklist item:
+ 1. Make the code changes.
+ 2. Run `dotnet build` on the test project. Fix any compilation errors before moving to the next item.
+ 3. Check off the item in `Reports/{ProjectName}/PostgresTestMigrationPlan.md`.
+
+ > At this point, hand off to the user: ask them to run all integration tests and report back. Do not advance until they confirm results.
+
+ - For each failure the user reports, diagnose and fix. The most common issues are:
+ - Client code that invokes PostgreSQL stored procedures (parameter mapping, return type handling).
+ - Stored procedures requiring corrections — fix in place and **update the corresponding file in `DDL/Postgres/{ProjectName}/`** to keep DDL artifacts in sync.
+ - Repeat the handoff/fix loop until all tests pass. If a failure cannot be fixed at the code or stored-procedure layer without a schema change (which is prohibited during this phase), stop and document it as a structured bug report in `Reports/{ProjectName}/` with status ⏳ IN PROGRESS and a clear description of the schema change required. Treat it as a known limitation and proceed to mark the phase complete if all remaining tests pass.
+
+ **✅ Success criteria:**
+ - `Reports/{ProjectName}/PostgresTestMigrationPlan.md` exists and all items are checked off.
+ - `dotnet build` passes cleanly on the PostgreSQL-targeting test project.
+ - All integration tests pass against PostgreSQL.
+ - The original Oracle-targeting test project is unmodified (verify no changes to its files).
+ - Any remaining behavioral discrepancies are documented as structured bug reports in `Reports/{ProjectName}/`.
## Working Directory
Migration artifacts should be stored under `.github/oracle-to-postgres-migration/`, if not, ask the user where to find what you need to be of help:
- `DDL/Oracle/` — Oracle DDL definitions (pre-migration)
-- `DDL/Postgres/` — PostgreSQL DDL definitions (post-migration)
-- `Reports/` — Migration plans, testing plans, bug reports, and final reports
+- `DDL/Postgres/{ProjectName}/` — PostgreSQL DDL definitions per project (post-migration)
+- `Reports/MasterMigrationPlan.md` — Solution-wide project inventory and migration flags
+- `Reports/{ProjectName}/` — Per-project risk analysis, migration checklist, and bug reports
diff --git a/docs/README.agents.md b/docs/README.agents.md
index c7f54b126a..58b95663ed 100644
--- a/docs/README.agents.md
+++ b/docs/README.agents.md
@@ -155,7 +155,7 @@ See [CONTRIBUTING.md](../CONTRIBUTING.md#adding-agents) for guidelines on how to
| [Octopus Release Notes With Mcp](../agents/octopus-deploy-release-notes-mcp.agent.md)
[](https://aka.ms/awesome-copilot/install/agent?url=vscode%3Achat-agent%2Finstall%3Furl%3Dhttps%3A%2F%2Fraw.githubusercontent.com%2Fgithub%2Fawesome-copilot%2Fmain%2Fagents%2Foctopus-deploy-release-notes-mcp.agent.md)
[](https://aka.ms/awesome-copilot/install/agent?url=vscode-insiders%3Achat-agent%2Finstall%3Furl%3Dhttps%3A%2F%2Fraw.githubusercontent.com%2Fgithub%2Fawesome-copilot%2Fmain%2Fagents%2Foctopus-deploy-release-notes-mcp.agent.md) | Generate release notes for a release in Octopus Deploy. The tools for this MCP server provide access to the Octopus Deploy APIs. | octopus
[](https://aka.ms/awesome-copilot/install/mcp-vscode?name=octopus&config=%7B%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22%2540octopusdeploy%252Fmcp-server%22%5D%2C%22env%22%3A%7B%7D%7D)
[](https://aka.ms/awesome-copilot/install/mcp-vscodeinsiders?name=octopus&config=%7B%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22%2540octopusdeploy%252Fmcp-server%22%5D%2C%22env%22%3A%7B%7D%7D)
[](https://aka.ms/awesome-copilot/install/mcp-visualstudio/mcp-install?%7B%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22%2540octopusdeploy%252Fmcp-server%22%5D%2C%22env%22%3A%7B%7D%7D) |
| [One Shot Feature Issue Planner](../agents/one-shot-feature-issue-planner.agent.md)
[](https://aka.ms/awesome-copilot/install/agent?url=vscode%3Achat-agent%2Finstall%3Furl%3Dhttps%3A%2F%2Fraw.githubusercontent.com%2Fgithub%2Fawesome-copilot%2Fmain%2Fagents%2Fone-shot-feature-issue-planner.agent.md)
[](https://aka.ms/awesome-copilot/install/agent?url=vscode-insiders%3Achat-agent%2Finstall%3Furl%3Dhttps%3A%2F%2Fraw.githubusercontent.com%2Fgithub%2Fawesome-copilot%2Fmain%2Fagents%2Fone-shot-feature-issue-planner.agent.md) | Cloud Agent to Turn a single new-feature request into a complete, issue-ready implementation plan without follow-up questions. | |
| [OpenAPI to Application Generator](../agents/openapi-to-application.agent.md)
[](https://aka.ms/awesome-copilot/install/agent?url=vscode%3Achat-agent%2Finstall%3Furl%3Dhttps%3A%2F%2Fraw.githubusercontent.com%2Fgithub%2Fawesome-copilot%2Fmain%2Fagents%2Fopenapi-to-application.agent.md)
[](https://aka.ms/awesome-copilot/install/agent?url=vscode-insiders%3Achat-agent%2Finstall%3Furl%3Dhttps%3A%2F%2Fraw.githubusercontent.com%2Fgithub%2Fawesome-copilot%2Fmain%2Fagents%2Fopenapi-to-application.agent.md) | Expert assistant for generating working applications from OpenAPI specifications | |
-| [Oracle To PostgreSQL Migration Expert](../agents/oracle-to-postgres-migration-expert.agent.md)
[](https://aka.ms/awesome-copilot/install/agent?url=vscode%3Achat-agent%2Finstall%3Furl%3Dhttps%3A%2F%2Fraw.githubusercontent.com%2Fgithub%2Fawesome-copilot%2Fmain%2Fagents%2Foracle-to-postgres-migration-expert.agent.md)
[](https://aka.ms/awesome-copilot/install/agent?url=vscode-insiders%3Achat-agent%2Finstall%3Furl%3Dhttps%3A%2F%2Fraw.githubusercontent.com%2Fgithub%2Fawesome-copilot%2Fmain%2Fagents%2Foracle-to-postgres-migration-expert.agent.md) | Agent for Oracle-to-PostgreSQL application migrations. Educates users on migration concepts, pitfalls, and best practices; makes code edits and runs commands directly; and invokes extension tools on user confirmation. | |
+| [Oracle To PostgreSQL Migration Expert](../agents/oracle-to-postgres-migration-expert.agent.md)
[](https://aka.ms/awesome-copilot/install/agent?url=vscode%3Achat-agent%2Finstall%3Furl%3Dhttps%3A%2F%2Fraw.githubusercontent.com%2Fgithub%2Fawesome-copilot%2Fmain%2Fagents%2Foracle-to-postgres-migration-expert.agent.md)
[](https://aka.ms/awesome-copilot/install/agent?url=vscode-insiders%3Achat-agent%2Finstall%3Furl%3Dhttps%3A%2F%2Fraw.githubusercontent.com%2Fgithub%2Fawesome-copilot%2Fmain%2Fagents%2Foracle-to-postgres-migration-expert.agent.md) | Agent for Oracle-to-PostgreSQL application migrations. Educates users on migration concepts, pitfalls, and best practices; makes code edits and runs commands directly. | |
| [PagerDuty Incident Responder](../agents/pagerduty-incident-responder.agent.md)
[](https://aka.ms/awesome-copilot/install/agent?url=vscode%3Achat-agent%2Finstall%3Furl%3Dhttps%3A%2F%2Fraw.githubusercontent.com%2Fgithub%2Fawesome-copilot%2Fmain%2Fagents%2Fpagerduty-incident-responder.agent.md)
[](https://aka.ms/awesome-copilot/install/agent?url=vscode-insiders%3Achat-agent%2Finstall%3Furl%3Dhttps%3A%2F%2Fraw.githubusercontent.com%2Fgithub%2Fawesome-copilot%2Fmain%2Fagents%2Fpagerduty-incident-responder.agent.md) | Responds to PagerDuty incidents by analyzing incident context, identifying recent code changes, and suggesting fixes via GitHub PRs. | [pagerduty](https://github.com/mcp/io.github.PagerDuty/pagerduty-mcp)
[](https://aka.ms/awesome-copilot/install/mcp-vscode?name=pagerduty&config=%7B%22url%22%3A%22https%3A%2F%2Fmcp.pagerduty.com%2Fmcp%22%2C%22headers%22%3A%7B%7D%7D)
[](https://aka.ms/awesome-copilot/install/mcp-vscodeinsiders?name=pagerduty&config=%7B%22url%22%3A%22https%3A%2F%2Fmcp.pagerduty.com%2Fmcp%22%2C%22headers%22%3A%7B%7D%7D)
[](https://aka.ms/awesome-copilot/install/mcp-visualstudio/mcp-install?%7B%22url%22%3A%22https%3A%2F%2Fmcp.pagerduty.com%2Fmcp%22%2C%22headers%22%3A%7B%7D%7D) |
| [PHP MCP Expert](../agents/php-mcp-expert.agent.md)
[](https://aka.ms/awesome-copilot/install/agent?url=vscode%3Achat-agent%2Finstall%3Furl%3Dhttps%3A%2F%2Fraw.githubusercontent.com%2Fgithub%2Fawesome-copilot%2Fmain%2Fagents%2Fphp-mcp-expert.agent.md)
[](https://aka.ms/awesome-copilot/install/agent?url=vscode-insiders%3Achat-agent%2Finstall%3Furl%3Dhttps%3A%2F%2Fraw.githubusercontent.com%2Fgithub%2Fawesome-copilot%2Fmain%2Fagents%2Fphp-mcp-expert.agent.md) | Expert assistant for PHP MCP server development using the official PHP SDK with attribute-based discovery | |
| [Pimcore Expert](../agents/pimcore-expert.agent.md)
[](https://aka.ms/awesome-copilot/install/agent?url=vscode%3Achat-agent%2Finstall%3Furl%3Dhttps%3A%2F%2Fraw.githubusercontent.com%2Fgithub%2Fawesome-copilot%2Fmain%2Fagents%2Fpimcore-expert.agent.md)
[](https://aka.ms/awesome-copilot/install/agent?url=vscode-insiders%3Achat-agent%2Finstall%3Furl%3Dhttps%3A%2F%2Fraw.githubusercontent.com%2Fgithub%2Fawesome-copilot%2Fmain%2Fagents%2Fpimcore-expert.agent.md) | Expert Pimcore development assistant specializing in CMS, DAM, PIM, and E-Commerce solutions with Symfony integration | |
diff --git a/docs/README.plugins.md b/docs/README.plugins.md
index 7a19d6eab2..d52cc9d184 100644
--- a/docs/README.plugins.md
+++ b/docs/README.plugins.md
@@ -78,7 +78,7 @@ See [CONTRIBUTING.md](../CONTRIBUTING.md#adding-plugins) for guidelines on how t
| [openapi-to-application-java-spring-boot](../plugins/openapi-to-application-java-spring-boot/README.md) | Generate production-ready Spring Boot applications from OpenAPI specifications. Includes project scaffolding, REST controller generation, service layer organization, and Spring Boot best practices. | 2 items | openapi, code-generation, api, java, spring-boot |
| [openapi-to-application-nodejs-nestjs](../plugins/openapi-to-application-nodejs-nestjs/README.md) | Generate production-ready NestJS applications from OpenAPI specifications. Includes project scaffolding, controller and service generation, TypeScript best practices, and enterprise patterns. | 2 items | openapi, code-generation, api, nodejs, typescript, nestjs |
| [openapi-to-application-python-fastapi](../plugins/openapi-to-application-python-fastapi/README.md) | Generate production-ready FastAPI applications from OpenAPI specifications. Includes project scaffolding, route generation, dependency injection, and Python best practices for async APIs. | 2 items | openapi, code-generation, api, python, fastapi |
-| [oracle-to-postgres-migration-expert](../plugins/oracle-to-postgres-migration-expert/README.md) | Expert agent for Oracle-to-PostgreSQL application migrations in .NET solutions. Performs code edits, runs commands, and invokes extension tools to migrate .NET/Oracle data access patterns to PostgreSQL. | 8 items | oracle, postgresql, database-migration, dotnet, sql, migration, integration-testing, stored-procedures |
+| [oracle-to-postgres-migration-expert](../plugins/oracle-to-postgres-migration-expert/README.md) | Expert agent for Oracle-to-PostgreSQL application migrations in .NET solutions. Performs code edits, runs commands, and invokes extension tools to migrate .NET/Oracle data access patterns to PostgreSQL. | 9 items | oracle, postgresql, database-migration, dotnet, sql, migration, integration-testing, stored-procedures |
| [ospo-sponsorship](../plugins/ospo-sponsorship/README.md) | Tools and resources for Open Source Program Offices (OSPOs) to identify, evaluate, and manage sponsorship of open source dependencies through GitHub Sponsors, Open Collective, and other funding platforms. | 1 items | |
| [partners](../plugins/partners/README.md) | Custom agents that have been created by GitHub partners | 20 items | devops, security, database, cloud, infrastructure, observability, feature-flags, cicd, migration, performance |
| [pcf-development](../plugins/pcf-development/README.md) | Complete toolkit for developing custom code components using Power Apps Component Framework for model-driven and canvas apps | 0 items | power-apps, pcf, component-framework, typescript, power-platform |
diff --git a/docs/README.skills.md b/docs/README.skills.md
index d59aadafdb..97759d2da3 100644
--- a/docs/README.skills.md
+++ b/docs/README.skills.md
@@ -138,7 +138,7 @@ See [CONTRIBUTING.md](../CONTRIBUTING.md#adding-skills) for guidelines on how to
| [create-tldr-page](../skills/create-tldr-page/SKILL.md)
`gh skills install github/awesome-copilot create-tldr-page` | Create a tldr page from documentation URLs and command examples, requiring both URL and command name. | None |
| [creating-oracle-to-postgres-master-migration-plan](../skills/creating-oracle-to-postgres-master-migration-plan/SKILL.md)
`gh skills install github/awesome-copilot creating-oracle-to-postgres-master-migration-plan` | Discovers all projects in a .NET solution, classifies each for Oracle-to-PostgreSQL migration eligibility, and produces a persistent master migration plan. Use when starting a multi-project Oracle-to-PostgreSQL migration, creating a migration inventory, or assessing which .NET projects contain Oracle dependencies. | None |
| [creating-oracle-to-postgres-migration-bug-report](../skills/creating-oracle-to-postgres-migration-bug-report/SKILL.md)
`gh skills install github/awesome-copilot creating-oracle-to-postgres-migration-bug-report` | Creates structured bug reports for defects found during Oracle-to-PostgreSQL migration. Use when documenting behavioral differences between Oracle and PostgreSQL as actionable bug reports with severity, root cause, and remediation steps. | `references/BUG-REPORT-TEMPLATE.md` |
-| [creating-oracle-to-postgres-migration-integration-tests](../skills/creating-oracle-to-postgres-migration-integration-tests/SKILL.md)
`gh skills install github/awesome-copilot creating-oracle-to-postgres-migration-integration-tests` | Creates integration test cases for .NET data access artifacts during Oracle-to-PostgreSQL database migrations. Generates DB-agnostic xUnit tests with deterministic seed data that validate behavior consistency across both database systems. Use when creating integration tests for a migrated project, generating test coverage for data access layers, or writing Oracle-to-PostgreSQL migration validation tests. | None |
+| [creating-oracle-to-postgres-migration-integration-tests](../skills/creating-oracle-to-postgres-migration-integration-tests/SKILL.md)
`gh skills install github/awesome-copilot creating-oracle-to-postgres-migration-integration-tests` | Creates integration test cases targeting Oracle for .NET data access artifacts. Tests capture Oracle expected behavior as the authoritative baseline; they are written once and later ported to PostgreSQL by migrating the test project in Phase 6. Use only during Phase 3, before any PostgreSQL migration work has begun. Do not invoke during Phase 6 or against a project that has already been migrated. | None |
| [csharp-async](../skills/csharp-async/SKILL.md)
`gh skills install github/awesome-copilot csharp-async` | Get best practices for C# async programming | None |
| [csharp-docs](../skills/csharp-docs/SKILL.md)
`gh skills install github/awesome-copilot csharp-docs` | Ensure that C# types are documented with XML comments and follow best practices for documentation. | None |
| [csharp-mstest](../skills/csharp-mstest/SKILL.md)
`gh skills install github/awesome-copilot csharp-mstest` | Get best practices for MSTest 3.x/4.x unit testing, including modern assertion APIs and data-driven tests | None |
@@ -271,6 +271,7 @@ See [CONTRIBUTING.md](../CONTRIBUTING.md#adding-skills) for guidelines on how to
| [microsoft-code-reference](../skills/microsoft-code-reference/SKILL.md)
`gh skills install github/awesome-copilot microsoft-code-reference` | Look up Microsoft API references, find working code samples, and verify SDK code is correct. Use when working with Azure SDKs, .NET libraries, or Microsoft APIs—to find the right method, check parameters, get working examples, or troubleshoot errors. Catches hallucinated methods, wrong signatures, and deprecated patterns by querying official docs. | None |
| [microsoft-docs](../skills/microsoft-docs/SKILL.md)
`gh skills install github/awesome-copilot microsoft-docs` | Query official Microsoft documentation to find concepts, tutorials, and code examples across Azure, .NET, Agent Framework, Aspire, VS Code, GitHub, and more. Uses Microsoft Learn MCP as the default, with Context7 and Aspire MCP for content that lives outside learn.microsoft.com. | None |
| [microsoft-skill-creator](../skills/microsoft-skill-creator/SKILL.md)
`gh skills install github/awesome-copilot microsoft-skill-creator` | Create agent skills for Microsoft technologies using Learn MCP tools. Use when users want to create a skill that teaches agents about any Microsoft technology, library, framework, or service (Azure, .NET, M365, VS Code, Bicep, etc.). Investigates topics deeply, then generates a hybrid skill storing essential knowledge locally while enabling dynamic deeper investigation. | `references/skill-templates.md` |
+| [migrating-oracle-to-postgres-data-access-code](../skills/migrating-oracle-to-postgres-data-access-code/SKILL.md)
`gh skills install github/awesome-copilot migrating-oracle-to-postgres-data-access-code` | Migrates .NET/C# data access code from Oracle to PostgreSQL (Npgsql). Replaces Oracle NuGet packages, rewrites OracleConnection/OracleCommand/OracleDataReader usage, fixes DbType mappings, updates stored procedure invocation patterns, and adapts connection string configuration. Use when migrating the application code layer of a .NET project during an Oracle-to-PostgreSQL database migration. | None |
| [migrating-oracle-to-postgres-stored-procedures](../skills/migrating-oracle-to-postgres-stored-procedures/SKILL.md)
`gh skills install github/awesome-copilot migrating-oracle-to-postgres-stored-procedures` | Migrates Oracle PL/SQL stored procedures to PostgreSQL PL/pgSQL. Translates Oracle-specific syntax, preserves method signatures and type-anchored parameters, leverages orafce where appropriate, and applies explicit collation mapping (`COLLATE "C"` only when appropriate, locale collations when required). Use when converting Oracle stored procedures or functions to PostgreSQL equivalents during a database migration. | None |
| [minecraft-plugin-development](../skills/minecraft-plugin-development/SKILL.md)
`gh skills install github/awesome-copilot minecraft-plugin-development` | Use this skill when building or modifying Minecraft server plugins for Paper, Spigot, or Bukkit, including plugin.yml setup, commands, listeners, schedulers, player state, team or arena systems, persistent progression, economy or profile data, configuration files, Adventure text, and version-safe API usage. Trigger for requests like "build a Minecraft plugin", "add a Paper command", "fix a Bukkit listener", "create plugin.yml", "implement a minigame mechanic", "add a perk or quest system", or "debug server plugin behavior". | `references/bootstrap-registration.md`
`references/build-test-and-runtime-validation.md`
`references/config-data-and-async.md`
`references/maps-heroes-and-feature-modules.md`
`references/minigame-instance-flow.md`
`references/persistent-progression-and-events.md`
`references/project-patterns.md`
`references/state-sessions-and-phases.md` |
| [mini-context-graph](../skills/mini-context-graph/SKILL.md)
`gh skills install github/awesome-copilot mini-context-graph` | A persistent, compounding knowledge base combining Karpathy's LLM Wiki pattern
with a structured knowledge graph. Ingest documents once — the LLM writes wiki
pages, extracts entities/relations into the graph, and stores raw content for
evidence retrieval. Knowledge accumulates and cross-references; it is never
re-derived from scratch. | `references/ingestion.md`
`references/lint.md`
`references/ontology.md`
`references/retrieval.md`
`scripts/config.py`
`scripts/contextgraph.py`
`scripts/template_agent_workflow.py`
`scripts/tools` |
@@ -357,7 +358,7 @@ See [CONTRIBUTING.md](../CONTRIBUTING.md#adding-skills) for guidelines on how to
| [repo-story-time](../skills/repo-story-time/SKILL.md)
`gh skills install github/awesome-copilot repo-story-time` | Generate a comprehensive repository summary and narrative story from commit history | None |
| [resemble-detect](../skills/resemble-detect/SKILL.md)
`gh skills install github/awesome-copilot resemble-detect` | Deepfake detection and media safety — detect AI-generated audio, images, video, and text, trace synthesis sources, apply watermarks, verify speaker identity, and analyze media intelligence using Resemble AI | `LICENSE`
`references/api-reference.md` |
| [review-and-refactor](../skills/review-and-refactor/SKILL.md)
`gh skills install github/awesome-copilot review-and-refactor` | Review and refactor code in your project according to defined instructions | None |
-| [reviewing-oracle-to-postgres-migration](../skills/reviewing-oracle-to-postgres-migration/SKILL.md)
`gh skills install github/awesome-copilot reviewing-oracle-to-postgres-migration` | Identifies Oracle-to-PostgreSQL migration risks by cross-referencing code against known behavioral differences (empty strings, refcursors, type coercion, sorting/collations, UNION ALL planner risks, materialized-view refresh requirements, timestamps, concurrent transactions, etc.). Use when planning a database migration, reviewing migration artifacts, or validating that integration tests cover Oracle/PostgreSQL differences. | `references/REFERENCE.md`
`references/empty-strings-handling.md`
`references/no-data-found-exceptions.md`
`references/oracle-parentheses-from-clause.md`
`references/oracle-to-postgres-sorting.md`
`references/oracle-to-postgres-timestamp-timezone.md`
`references/oracle-to-postgres-to-char-numeric.md`
`references/oracle-to-postgres-type-coercion.md`
`references/postgres-concurrent-transactions.md`
`references/postgres-materialized-view-refresh.md`
`references/postgres-refcursor-handling.md`
`references/postgres-union-all-planner.md` |
+| [reviewing-oracle-to-postgres-migration](../skills/reviewing-oracle-to-postgres-migration/SKILL.md)
`gh skills install github/awesome-copilot reviewing-oracle-to-postgres-migration` | Identifies Oracle-to-PostgreSQL migration risks by cross-referencing code against known behavioral differences (empty strings, refcursors, type coercion, sorting/collations, UNION ALL planner risks, materialized-view refresh requirements, timestamps, concurrent transactions, etc.). Use when planning a database migration, reviewing migration artifacts, or validating that integration tests cover Oracle/PostgreSQL differences. | `references/REFERENCE.md`
`references/empty-strings-handling.md`
`references/no-data-found-exceptions.md`
`references/oracle-nvl-decode-functions.md`
`references/oracle-parentheses-from-clause.md`
`references/oracle-rownum-pagination.md`
`references/oracle-sysdate-sequences-dual.md`
`references/oracle-to-postgres-sorting.md`
`references/oracle-to-postgres-timestamp-timezone.md`
`references/oracle-to-postgres-to-char-numeric.md`
`references/oracle-to-postgres-type-coercion.md`
`references/postgres-concurrent-transactions.md`
`references/postgres-materialized-view-refresh.md`
`references/postgres-refcursor-handling.md`
`references/postgres-union-all-planner.md` |
| [rhino3d-scripts](../skills/rhino3d-scripts/SKILL.md)
`gh skills install github/awesome-copilot rhino3d-scripts` | Authoring and debugging scripts for Rhinoceros 3D (Rhino 8 and later). Use when asked to write RhinoScript (VBScript / .rvb / .vbs), RhinoPython, or RhinoCommon-based scripts; automate Rhino modeling tasks; build command macros; manipulate Rhino geometry, layers, blocks, or document objects; pick objects from the viewport; control redraw and undo; or load and run scripts from the Rhino Script Editor. Covers `rhinoscriptsyntax`, `scriptcontext`, the `Rhino.*` RhinoCommon namespaces (`Rhino.Geometry`, `Rhino.DocObjects`, `Rhino.Input`, `Rhino.UI`, `Rhino.Display`, `Rhino.FileIO`), and the Rhino 8 unified Script Editor. | `references/macros-and-loading.md`
`references/rhinocommon-map.md`
`references/rhinoscriptsyntax-cheatsheet.md`
`references/vbscript-quirks.md` |
| [roundup](../skills/roundup/SKILL.md)
`gh skills install github/awesome-copilot roundup` | Generate personalized status briefings on demand. Pulls from your configured data sources (GitHub, email, Teams, Slack, and more), synthesizes across them, and drafts updates in your own communication style for any audience you define. | None |
| [roundup-setup](../skills/roundup-setup/SKILL.md)
`gh skills install github/awesome-copilot roundup-setup` | Interactive onboarding that learns your communication style, audiences, and data sources to configure personalized status briefings. Paste in examples of updates you already write, answer a few questions, and roundup calibrates itself to your workflow. | `references/config-template.md` |
@@ -368,7 +369,7 @@ See [CONTRIBUTING.md](../CONTRIBUTING.md#adding-skills) for guidelines on how to
| [salesforce-component-standards](../skills/salesforce-component-standards/SKILL.md)
`gh skills install github/awesome-copilot salesforce-component-standards` | Quality standards for Salesforce Lightning Web Components (LWC), Aura components, and Visualforce pages. Covers SLDS 2 compliance, accessibility (WCAG 2.1 AA), data access pattern selection, component communication rules, XSS prevention, CSRF enforcement, FLS/CRUD in AuraEnabled methods, view state management, and Jest test requirements. Use this skill when building or reviewing any Salesforce UI component to enforce platform-specific security and quality standards. | None |
| [salesforce-flow-design](../skills/salesforce-flow-design/SKILL.md)
`gh skills install github/awesome-copilot salesforce-flow-design` | Salesforce Flow architecture decisions, flow type selection, bulk safety validation, and fault handling standards. Use this skill when designing or reviewing Record-Triggered, Screen, Autolaunched, Scheduled, or Platform Event flows to ensure correct type selection, no DML/Get Records in loops, proper fault connectors on all data-changing elements, and appropriate automation density checks before deployment. | None |
| [sandbox-npm-install](../skills/sandbox-npm-install/SKILL.md)
`gh skills install github/awesome-copilot sandbox-npm-install` | Install npm packages in a Docker sandbox environment. Use this skill whenever you need to install, reinstall, or update node_modules inside a container where the workspace is mounted via virtiofs. Native binaries (esbuild, lightningcss, rollup) crash on virtiofs, so packages must be installed on the local ext4 filesystem and symlinked back. | `scripts/install.sh` |
-| [scaffolding-oracle-to-postgres-migration-test-project](../skills/scaffolding-oracle-to-postgres-migration-test-project/SKILL.md)
`gh skills install github/awesome-copilot scaffolding-oracle-to-postgres-migration-test-project` | Scaffolds an xUnit integration test project for validating Oracle-to-PostgreSQL database migration behavior in .NET solutions. Creates the test project, transaction-rollback base class, and seed data manager. Use when setting up test infrastructure before writing migration integration tests, or when a test project is needed for Oracle-to-PostgreSQL validation. | None |
+| [scaffolding-oracle-to-postgres-migration-test-project](../skills/scaffolding-oracle-to-postgres-migration-test-project/SKILL.md)
`gh skills install github/awesome-copilot scaffolding-oracle-to-postgres-migration-test-project` | Scaffolds an xUnit integration test project targeting Oracle in .NET solutions. Creates the test project, transaction-rollback base class, and seed data manager. Use only during Phase 3, before writing Oracle baseline integration tests. Do not invoke during Phase 6 — the PostgreSQL test project is produced by migrating this project, not by running this skill again. | None |
| [scoutqa-test](../skills/scoutqa-test/SKILL.md)
`gh skills install github/awesome-copilot scoutqa-test` | This skill should be used when the user asks to "test this website", "run exploratory testing", "check for accessibility issues", "verify the login flow works", "find bugs on this page", or requests automated QA testing. Triggers on web application testing scenarios including smoke tests, accessibility audits, e-commerce flows, and user flow validation using ScoutQA CLI. Use this skill proactively after implementing web application features to verify they work correctly. | None |
| [screen-recording](../skills/screen-recording/SKILL.md)
`gh skills install github/awesome-copilot screen-recording` | Create annotated animated GIF demos and screen recordings for pull requests and documentation. Covers frame capture, timing, imageio-based GIF creation, and per-frame annotation workflows. | None |
| [secret-scanning](../skills/secret-scanning/SKILL.md)
`gh skills install github/awesome-copilot secret-scanning` | Guide for configuring and managing GitHub secret scanning, push protection, custom patterns, and secret alert remediation. For pre-commit secret scanning in AI coding agents via the GitHub MCP Server, this skill references the Advanced Security plugin (`advanced-security@copilot-plugins`). Use this skill when enabling secret scanning, setting up push protection, defining custom patterns, triaging alerts, resolving blocked pushes, or when an agent needs to scan code for secrets before committing. | `references/alerts-and-remediation.md`
`references/custom-patterns.md`
`references/push-protection.md` |
diff --git a/plugins/oracle-to-postgres-migration-expert/README.md b/plugins/oracle-to-postgres-migration-expert/README.md
index 7e1f9bb700..54bc2f3bb7 100644
--- a/plugins/oracle-to-postgres-migration-expert/README.md
+++ b/plugins/oracle-to-postgres-migration-expert/README.md
@@ -1,6 +1,6 @@
# Oracle-to-PostgreSQL Migration Expert Plugin
-Expert agent for Oracle-to-PostgreSQL application migrations in .NET solutions. Performs code edits, runs commands, and invokes extension tools to migrate .NET/Oracle data access patterns to PostgreSQL.
+Expert agent for Oracle-to-PostgreSQL application migrations in .NET solutions. Performs code edits, runs commands, and guides users through a structured, gated migration workflow.
## Installation
@@ -15,7 +15,7 @@ copilot plugin install oracle-to-postgres-migration-expert@awesome-copilot
| Agent | Description |
|-------|-------------|
-| `Oracle-to-PostgreSQL Migration Expert` | Expert agent for Oracle→PostgreSQL migrations. Makes code edits and runs commands directly, educates users on migration concepts and pitfalls, and invokes extension tools on user confirmation. |
+| `Oracle-to-PostgreSQL Migration Expert` | Expert agent for Oracle→PostgreSQL migrations. Makes code edits and runs commands directly, educates users on migration concepts and pitfalls. |
### Skills
@@ -28,6 +28,7 @@ copilot plugin install oracle-to-postgres-migration-expert@awesome-copilot
| `scaffolding-oracle-to-postgres-migration-test-project` | Scaffolds an xUnit integration test project with a transaction-rollback base class and seed data manager for Oracle-to-PostgreSQL migration validation. |
| `creating-oracle-to-postgres-migration-integration-tests` | Generates DB-agnostic xUnit integration tests with deterministic seed data that validate behavior consistency across both database systems. |
| `creating-oracle-to-postgres-migration-bug-report` | Creates structured bug reports for defects discovered during Oracle-to-PostgreSQL migration validation, with severity, root cause, and remediation steps. |
+| `migrating-oracle-to-postgres-data-access-code` | Migrates .NET/C# data access code from Oracle to PostgreSQL (Npgsql). Replaces Oracle NuGet packages, rewrites ADO.NET type references, fixes DbType mappings, updates stored procedure invocation patterns, and adapts connection string configuration. |
## Features
@@ -38,7 +39,7 @@ The expert agent educates users throughout the migration journey:
- **Migration Concepts**: Explains Oracle→PostgreSQL differences (empty strings vs NULL, NO_DATA_FOUND exceptions, sort/collation behavior, TO_CHAR conversions, type coercion strictness, REF CURSOR handling, UNION ALL planning caveats, materialized-view refresh needs, concurrent transactions, timestamp/timezone behavior)
- **Pitfall Reference**: Surfaces insights from migration knowledge so users understand why changes are needed
- **Best Practices**: Advises on minimizing changes, preserving logic, and ensuring schema immutability
-- **Workflow Guidance**: Presents a four-phase migration workflow as a guide users can follow at their own pace
+- **Workflow Guidance**: Presents a six-phase, gated migration workflow with explicit success criteria at each gate
### Suggest-Then-Act Pattern
@@ -47,7 +48,7 @@ The expert suggests actionable next steps and only proceeds with user confirmati
1. **Educate** on the migration topic and why it matters
2. **Suggest** a recommended action with expected outcomes
3. **Confirm** the user wants to proceed
-4. **Act** — make edits, run commands, or invoke extension tools directly
+4. **Act** — make edits and run commands directly
5. **Summarize** what was produced and suggest the next step
No autonomous chaining — the user controls the pace and sequence.
@@ -56,33 +57,50 @@ For database-changing actions, the expert provides scripts and explicit run inst
## Migration Workflow
-The expert guides users through a four-phase workflow:
+The expert guides users through a six-phase, gated workflow. Each phase must satisfy its success criteria before advancing.
-**Phase 1 — Discovery & Planning**
+**Phase 1 — Discovery & Planning** *(solution-wide)*
-1. Create a master migration plan (classifies all projects in the solution)
-2. Set up Oracle and PostgreSQL DDL artifacts
+- Discover all projects and classify migration eligibility
+- Produce `Reports/MasterMigrationPlan.md` recording DDL artifact location and whether an external tool (e.g., `ora2pg`) was already used
-**Phase 2 — Code Migration** *(per project)*
-3. Migrate application codebase (via `ms-ossdata.vscode-pgsql` extension)
-4. Migrate stored procedures (Oracle PL/SQL → PostgreSQL PL/pgSQL)
+**Phase 2 — Pre-Migration Planning & Risk Analysis** *(per project)*
-**Phase 3 — Validation** *(per project)*
-5. Plan integration testing
-6. Scaffold the xUnit test project
-7. Create integration tests
-8. Run tests against Oracle (baseline) and PostgreSQL (target)
-9. Validate test results
-10. Create bug reports for any failures
+- Identify the data-access layer (repositories, DAOs, service classes, SQL/procedure calls)
+- Produce `Reports/{ProjectName}/OracleRiskAnalysis.md` — a stable analytical reference of Oracle/PostgreSQL behavioral differences found in the code
+- Derive `Reports/{ProjectName}/MigrationChecklist.md` — a numbered, actionable checklist for Phase 5
-**Phase 4 — Reporting**
-11. Generate final migration report (via `ms-ossdata.vscode-pgsql` extension)
+**Phase 3 — Oracle Test Project Creation & Validation** *(per project)*
+
+- Scaffold an Oracle-targeting xUnit test project and write integration tests
+- Establish a passing Oracle baseline — a failing baseline means defects exist *before* migration starts
+- Document any behavioral discrepancies as structured bug reports
+
+**Phase 4 — Schema & DDL Migration** *(per project)*
+
+- Skip if `MasterMigrationPlan.md` records an external tool already produced PostgreSQL DDL
+- Migrate in dependency order: types/enums → tables/sequences → indexes/constraints → views → triggers → stored procedures (PL/SQL → PL/pgSQL)
+- Output artifacts to `DDL/Postgres/{ProjectName}/`; user applies scripts and confirms clean apply
+
+**Phase 5 — Code Migration** *(per project)*
+
+- Copy the application project into a `.Postgres` sibling, add to the solution, and update namespace/assembly name
+- Use the `migrating-oracle-to-postgres-data-access-code` skill to work through `MigrationChecklist.md` item by item
+- Run `dotnet build` after each item; fix errors before moving on
+- Cross-reference completed checklist against `OracleRiskAnalysis.md` to confirm every risk is addressed or deferred with justification
+
+**Phase 6 — PostgreSQL Test Project Creation & Validation** *(per project)*
+
+- Clone the Oracle test project into a `.Postgres`-namespaced test project targeting the Phase 5 application clone
+- Migrate the test project, `dotnet build`-gating each change
+- Iteratively fix failures reported by the user — stored procedure corrections are written back to `DDL/Postgres/{ProjectName}/`
+- Oracle test project must remain unmodified throughout
## Prerequisites
- Visual Studio Code with GitHub Copilot
-- PostgreSQL Extension (`ms-ossdata.vscode-pgsql`) — required for application code migration and report generation
- .NET solution with Oracle dependencies to migrate
+- Access to an Oracle instance (for baseline testing) and a PostgreSQL instance (for validation)
## Directory Structure
@@ -92,22 +110,24 @@ The agent expects and creates the following structure in your repository:
.github/
└── oracle-to-postgres-migration/
├── Reports/
- │ ├── Master Migration Plan.md
- │ ├── {Project} Integration Testing Plan.md
- │ ├── {Project} Application Migration Report.md
- │ ├── BUG_REPORT_*.md
- │ └── TestResults/
+ │ ├── MasterMigrationPlan.md
+ │ └── {ProjectName}/
+ │ ├── OracleRiskAnalysis.md
+ │ ├── MigrationChecklist.md
+ │ ├── PostgresTestMigrationPlan.md
+ │ └── BUG_REPORT_*.md
└── DDL/
- ├── Oracle/ # Oracle DDL scripts (pre-migration)
- └── Postgres/ # PostgreSQL DDL scripts (post-migration)
+ ├── Oracle/ # Oracle DDL scripts (pre-migration)
+ └── Postgres/
+ └── {ProjectName}/ # PostgreSQL DDL scripts per project (post-migration)
```
## Usage
1. **Ask for Guidance**: Invoke the expert with a migration question or situation (e.g., *"How should I approach migrating my .NET solution to PostgreSQL?"* or *"What does Oracle do with empty strings that's different from PostgreSQL?"*)
2. **Learn & Plan**: The expert explains concepts, surfaces pitfall insights, and presents recommended workflow steps
-3. **Choose Your Next Step**: Decide which task to tackle (master plan, code migration, testing, etc.)
-4. **Confirm and Act**: Tell the expert to proceed, and it makes edits, runs commands, or invokes extension tools directly
+3. **Choose Your Next Step**: Decide which task to tackle (master plan, risk analysis, testing, code migration, etc.)
+4. **Confirm and Act**: Tell the expert to proceed, and it makes edits and runs commands directly
5. **Review & Continue**: Examine the results and ask for the next step
## Source
diff --git a/plugins/oracle-to-postgres-migration-expert/plugin.json b/plugins/oracle-to-postgres-migration-expert/plugin.json
index eb70d318f0..79e79ef316 100644
--- a/plugins/oracle-to-postgres-migration-expert/plugin.json
+++ b/plugins/oracle-to-postgres-migration-expert/plugin.json
@@ -2,7 +2,7 @@
"$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json",
"name": "oracle-to-postgres-migration-expert",
"description": "Expert agent for Oracle-to-PostgreSQL application migrations in .NET solutions. Performs code edits, runs commands, and invokes extension tools to migrate .NET/Oracle data access patterns to PostgreSQL.",
- "version": "1.0.0",
+ "version": "1.1.0",
"author": {
"name": "Awesome Copilot Community"
},
@@ -27,6 +27,7 @@
"./skills/creating-oracle-to-postgres-master-migration-plan/",
"./skills/creating-oracle-to-postgres-migration-bug-report/",
"./skills/creating-oracle-to-postgres-migration-integration-tests/",
+ "./skills/migrating-oracle-to-postgres-data-access-code/",
"./skills/migrating-oracle-to-postgres-stored-procedures/",
"./skills/planning-oracle-to-postgres-migration-integration-testing/",
"./skills/reviewing-oracle-to-postgres-migration/",
diff --git a/skills/creating-oracle-to-postgres-master-migration-plan/SKILL.md b/skills/creating-oracle-to-postgres-master-migration-plan/SKILL.md
index 5db371e24a..be5c863aab 100644
--- a/skills/creating-oracle-to-postgres-master-migration-plan/SKILL.md
+++ b/skills/creating-oracle-to-postgres-master-migration-plan/SKILL.md
@@ -45,7 +45,7 @@ Present the classified list. Let the user adjust classifications or migration or
**Step 4: Write the plan file**
-Save to: `.github/oracle-to-postgres-migration/Reports/Master Migration Plan.md`
+Save to: `.github/oracle-to-postgres-migration/Reports/MasterMigrationPlan.md`
Use this exact template — downstream consumers depend on the structure:
@@ -57,6 +57,11 @@ Use this exact template — downstream consumers depend on the structure:
**Created:** {timestamp}
**Last Updated:** {timestamp}
+## DDL Artifacts
+
+**Location:** {path to DDL artifacts, e.g., `.github/oracle-to-postgres-migration/DDL/`}
+**External tool used:** {Yes / No} — {If Yes, name the tool (e.g., `ora2pg`) and note that Phase 4 (Schema & DDL Migration) can be skipped; PostgreSQL DDL artifacts already exist.}
+
## Solution Summary
| Metric | Count |
diff --git a/skills/creating-oracle-to-postgres-migration-bug-report/SKILL.md b/skills/creating-oracle-to-postgres-migration-bug-report/SKILL.md
index dc3677d7fe..9cbc89e990 100644
--- a/skills/creating-oracle-to-postgres-migration-bug-report/SKILL.md
+++ b/skills/creating-oracle-to-postgres-migration-bug-report/SKILL.md
@@ -40,4 +40,6 @@ Use the template in [references/BUG-REPORT-TEMPLATE.md](references/BUG-REPORT-TE
## Filename Convention
-Save bug reports as `BUG_REPORT_.md` where `` is a short PascalCase identifier (e.g., `EmptyStringNullHandling`, `RefCursorUnwrapFailure`).
+Save bug reports to `.github/oracle-to-postgres-migration/Reports/{ProjectName}/BUG_REPORT_.md` where:
+- `{ProjectName}` is the project's assembly/folder name with spaces normalized to `-` (e.g. `MyApp.DataAccess`)
+- `` is a short PascalCase identifier describing the defect (e.g., `EmptyStringNullHandling`, `RefCursorUnwrapFailure`)
diff --git a/skills/creating-oracle-to-postgres-migration-integration-tests/SKILL.md b/skills/creating-oracle-to-postgres-migration-integration-tests/SKILL.md
index b78eada480..aba48c998e 100644
--- a/skills/creating-oracle-to-postgres-migration-integration-tests/SKILL.md
+++ b/skills/creating-oracle-to-postgres-migration-integration-tests/SKILL.md
@@ -1,11 +1,11 @@
---
name: creating-oracle-to-postgres-migration-integration-tests
-description: 'Creates integration test cases for .NET data access artifacts during Oracle-to-PostgreSQL database migrations. Generates DB-agnostic xUnit tests with deterministic seed data that validate behavior consistency across both database systems. Use when creating integration tests for a migrated project, generating test coverage for data access layers, or writing Oracle-to-PostgreSQL migration validation tests.'
+description: 'Creates integration test cases targeting Oracle for .NET data access artifacts. Tests capture Oracle expected behavior as the authoritative baseline; they are written once and later ported to PostgreSQL by migrating the test project in Phase 6. Use only during Phase 3, before any PostgreSQL migration work has begun. Do not invoke during Phase 6 or against a project that has already been migrated.'
---
# Creating Integration Tests for Oracle-to-PostgreSQL Migration
-Generates integration test cases for data access artifacts in a single target project. Tests validate behavior consistency when running against Oracle or PostgreSQL.
+Generates integration test cases for data access artifacts in a single target project. Tests target Oracle and capture its behavior as the authoritative baseline. They are written to be logically portable — so they can survive Phase 6 migration without rewriting — but they do not run against PostgreSQL at this stage.
## Prerequisites
@@ -34,7 +34,6 @@ Scope to the target project only. List data access methods that interact with th
**Step 3: Create seed data**
- Follow seed file location and naming conventions from the existing project.
-- Reuse existing seed files when possible.
- Avoid `TRUNCATE TABLE` — keep existing database data intact.
- Assume existing business rows and lookup rows are already present; add only minimal, collision-safe seed records needed for the scenario.
- Do not commit seed data; tests run in transactions that roll back.
@@ -51,7 +50,7 @@ Scope to the target project only. List data access methods that interact with th
- Avoid testing code paths that do not exist or asserting behavior that cannot occur.
- Avoid redundant assertions across tests targeting the same method.
- For text parameters, include both empty-string and `NULL`/missing input coverage where applicable.
-- For datetime behavior, include explicit timezone-sensitive assertions when methods write/read `timestamp without time zone` or `timestamp(0)` targets.
+- For datetime behavior, include assertions that validate the value written and read back matches — use the Oracle column's precision (e.g., seconds-only for a date/time column with no fractional seconds) rather than assuming any particular database type syntax.
**Step 5: Review determinism**
@@ -59,8 +58,9 @@ Re-examine every assertion against non-null values. Confirm each is deterministi
## Key Constraints
+- **Phase 3 only** — these tests target Oracle. Do not invoke this skill during Phase 6 or against a PostgreSQL-targeting project.
- **Oracle is the golden source** — tests capture Oracle's expected behavior.
-- **DB-agnostic assertions** — no platform-specific error messages or syntax in assertions.
-- **Seed only against Oracle** — test project will be migrated to PostgreSQL later.
+- **Assertion portability** — avoid platform-specific error messages or syntax in assertions so that when the test project is migrated to PostgreSQL in Phase 6, assertions require no changes.
+- **Seed only against Oracle** — the test project will be migrated to PostgreSQL in Phase 6; seed data and infrastructure stay Oracle-targeted until then.
- **Scoped to one project** — do not create tests for artifacts outside the target project.
- **Preserve existing data** — never rewrite or wipe pre-existing business or lookup rows.
diff --git a/skills/migrating-oracle-to-postgres-data-access-code/SKILL.md b/skills/migrating-oracle-to-postgres-data-access-code/SKILL.md
new file mode 100644
index 0000000000..94b1c1a3cb
--- /dev/null
+++ b/skills/migrating-oracle-to-postgres-data-access-code/SKILL.md
@@ -0,0 +1,137 @@
+---
+name: migrating-oracle-to-postgres-data-access-code
+description: 'Migrates .NET/C# data access code from Oracle to PostgreSQL (Npgsql). Replaces Oracle NuGet packages, rewrites OracleConnection/OracleCommand/OracleDataReader usage, fixes DbType mappings, updates stored procedure invocation patterns, and adapts connection string configuration. Use when migrating the application code layer of a .NET project during an Oracle-to-PostgreSQL database migration.'
+---
+
+# Migrating .NET Data Access Code from Oracle to PostgreSQL
+
+Migrate the C# data access layer of a single `.Postgres`-copy project from Oracle (Oracle.ManagedDataAccess) to PostgreSQL (Npgsql). Work item by item through `Reports/{ProjectName}/MigrationChecklist.md`.
+
+## Prerequisites
+
+- The `.Postgres` project copy exists (created in Phase 5 setup).
+- `Reports/{ProjectName}/MigrationChecklist.md` exists and is the source of truth for what to change.
+- `Reports/{ProjectName}/OracleRiskAnalysis.md` exists for cross-referencing behavioral differences.
+
+## Workflow
+
+```
+Progress:
+- [ ] Step 1: Replace NuGet packages
+- [ ] Step 2: Update connection string configuration
+- [ ] Step 3: Rewrite ADO.NET type references
+- [ ] Step 4: Fix DbType mappings
+- [ ] Step 5: Migrate stored procedure invocation
+- [ ] Step 6: Address Oracle-specific SQL and syntax
+- [ ] Step 7: Build and verify
+```
+
+**Step 1: Replace NuGet packages**
+
+In the `.csproj` of the `.Postgres` project:
+
+- Remove: `Oracle.ManagedDataAccess.Core`, `Oracle.EntityFrameworkCore` (and any other `Oracle.*` packages)
+- Add: `Npgsql` (for ADO.NET) and/or `Npgsql.EntityFrameworkCore.PostgreSQL` (for EF Core)
+- Keep version pinning consistent with the target .NET version; do not introduce newer package versions than what the solution already uses for similar packages.
+- If `System.Data` abstractions (`IDbConnection`, `IDbCommand`) are used project-wide, the surface-level code may need fewer changes — identify them first.
+
+**Step 2: Update connection string configuration**
+
+- Locate the Oracle connection string in `appsettings.json`, `appsettings.{env}.json`, `web.config`, `app.config`, or environment variable configuration.
+- Replace with a Npgsql-compatible connection string: `Host=localhost;Port=5432;Database=mydb;Username=myuser;Password=mypassword`
+- Do not hardcode credentials — use the same configuration mechanism already in use (e.g., environment variables, secrets manager, `IConfiguration`).
+- Update any named connection string keys only if they were Oracle-specific (e.g., `OracleConnection`). Prefer keeping the same key name to minimize application config changes.
+
+**Step 3: Rewrite ADO.NET type references**
+
+Replace Oracle-specific ADO.NET types with Npgsql equivalents:
+
+| Oracle type | Npgsql replacement |
+|---|---|
+| `OracleConnection` | `NpgsqlConnection` |
+| `OracleCommand` | `NpgsqlCommand` |
+| `OracleDataReader` | `NpgsqlDataReader` |
+| `OracleDataAdapter` | `NpgsqlDataAdapter` |
+| `OracleParameter` | `NpgsqlParameter` |
+| `OracleTransaction` | `NpgsqlTransaction` |
+| `OracleException` | `NpgsqlException` |
+| `OracleDbType` | `NpgsqlDbType` (from `NpgsqlTypes` namespace) |
+
+Update `using` directives accordingly (`using Oracle.ManagedDataAccess.Client` → `using Npgsql`).
+
+If the codebase uses `IDbConnection`/`IDbCommand` abstractions registered via DI, update only the DI registration and connection string — the consuming code may not need changes.
+
+**Step 4: Fix DbType and NpgsqlDbType mappings**
+
+Oracle parameter types do not map 1:1 to Npgsql. Review every `OracleParameter` (now `NpgsqlParameter`) that sets an explicit type:
+
+| Oracle type | Notes |
+|---|---|
+| `OracleDbType.Varchar2` | Use `NpgsqlDbType.Varchar` or omit (Npgsql infers from value) |
+| `OracleDbType.Clob` | Use `NpgsqlDbType.Text` |
+| `OracleDbType.Number` | Use `NpgsqlDbType.Numeric` or `NpgsqlDbType.Integer` depending on precision |
+| `OracleDbType.Date` | Use `NpgsqlDbType.Date` (date only) or `NpgsqlDbType.Timestamp` (if time component used) |
+| `OracleDbType.TimeStamp` | Use `NpgsqlDbType.Timestamp` |
+| `OracleDbType.RefCursor` | Use `NpgsqlDbType.Refcursor` — see Step 5 |
+| `OracleDbType.Char` | Use `NpgsqlDbType.Char` |
+
+For parameters where Oracle inferred the type from the value, Npgsql also infers — explicit type setting is often unnecessary and can be removed.
+
+**Step 5: Migrate stored procedure invocation**
+
+Oracle and PostgreSQL stored procedure invocation differ significantly:
+
+- **Command type**: Retain `CommandType.StoredProcedure` for function calls. For procedures that use `OUT` parameters, PostgreSQL requires `CommandType.Text` with `CALL proc_name(...)` syntax in some versions of Npgsql — verify against the target Npgsql version.
+- **RefCursor handling**: Oracle returns ref cursors as output parameters; PostgreSQL returns them differently:
+ - For `RETURNS TABLE` / `RETURNS SETOF`, use `ExecuteReader()` directly — no cursor parameter needed.
+ - For `RETURNS refcursor`, call within a transaction, read the cursor name from the output parameter, then issue `FETCH ALL IN ""`.
+ - Remove any Oracle-specific cursor-wrapping code (e.g., `OracleRefCursor`).
+- **OUT parameters**: PostgreSQL stored procedures use `INOUT` or function return values. Verify parameter direction matches the migrated procedure signature.
+- **Sequence `NEXTVAL`**: Replace `SELECT {SEQUENCE}.NEXTVAL FROM DUAL` with `SELECT nextval('{sequence_name}')`.
+- **Named parameters**: Npgsql uses `@param_name`; Oracle used `:param_name`. Update all parameter name prefixes.
+
+**Step 6: Address Oracle-specific SQL and C# patterns**
+
+Review inline SQL strings and query builders for Oracle-specific constructs and replace:
+
+| Oracle construct | PostgreSQL replacement |
+|---|---|
+| `ROWNUM <= n` | `LIMIT n` |
+| `ROWNUM = 1` | `LIMIT 1` |
+| `NVL(x, y)` | `COALESCE(x, y)` |
+| `DECODE(expr, v1, r1, ...)` | `CASE WHEN expr = v1 THEN r1 ... END` |
+| `SYSDATE` / `SYSTIMESTAMP` | `NOW()` or `CURRENT_TIMESTAMP` |
+| `TO_CHAR(date, fmt)` | `TO_CHAR(date, fmt)` (mostly compatible; verify format strings) |
+| `TO_DATE(str, fmt)` | `TO_DATE(str, fmt)` (verify format strings) |
+| `TO_NUMBER(str)` | `CAST(str AS NUMERIC)` or `str::NUMERIC` |
+| `||` string concat | `||` (compatible) |
+| `DUAL` table | Remove `FROM DUAL`; PostgreSQL evaluates `SELECT expr` without a table |
+| `CONNECT BY` hierarchy | Rewrite using recursive CTEs (`WITH RECURSIVE`) |
+| `MERGE INTO` | Rewrite as `INSERT ... ON CONFLICT DO UPDATE` |
+| Empty string `''` as NULL | Oracle treats `''` as NULL; PostgreSQL does not — check comparisons and `IS NULL` guards |
+| `VARCHAR2` | `VARCHAR` or `TEXT` |
+
+**Step 7: Build and verify**
+
+After addressing all checklist items:
+
+1. Run `dotnet build` on the `.Postgres` project. Fix any remaining compilation errors.
+2. Verify no Oracle-specific namespaces remain: search for `Oracle.ManagedDataAccess`, `OracleConnection`, `OracleCommand`, `:param` patterns.
+3. Mark completed items in `Reports/{ProjectName}/MigrationChecklist.md`.
+
+## EF Core projects
+
+If the project uses `Oracle.EntityFrameworkCore`:
+
+- Replace the provider registration in `DbContext` configuration: `.UseOracle(...)` → `.UseNpgsql(...)`
+- Replace `OracleDbContextOptionsBuilder` references.
+- Review `OnModelCreating` for Oracle-specific configurations (e.g., `HasColumnType("NUMBER")` → `HasColumnType("numeric")`).
+- Sequence configuration: `modelBuilder.HasSequence("seq_name").StartsAt(1).IncrementsBy(1)` syntax is compatible; verify column defaults referencing sequences.
+- Do not run EF Core migrations — schema is managed externally via DDL scripts (Phase 4).
+
+## Key Constraints
+
+- Work only within the `.Postgres` copy — never modify the original Oracle-targeting project.
+- Keep to existing .NET and C# versions; do not introduce newer language or runtime features.
+- Preserve comments and application logic; change only what is necessary for PostgreSQL compatibility.
+- Oracle is the source of truth — behavioral differences must be documented as bug reports, not silently altered.
diff --git a/skills/migrating-oracle-to-postgres-stored-procedures/SKILL.md b/skills/migrating-oracle-to-postgres-stored-procedures/SKILL.md
index 41f1b8bbf2..3c5d101640 100644
--- a/skills/migrating-oracle-to-postgres-stored-procedures/SKILL.md
+++ b/skills/migrating-oracle-to-postgres-stored-procedures/SKILL.md
@@ -39,8 +39,10 @@ Apply these translation rules:
- Treat `UNION ALL` as a review checkpoint. Validate plan quality per branch and restructure if combined-branch planning causes regressions (for example, unexpected sequential scans on large tables).
- Leverage the `orafce` extension when it improves clarity or fidelity.
-Consult the PostgreSQL table/view definitions at `.github/oracle-to-postgres-migration/DDL/Postgres/Tables and Views/` for target schema details.
+Consult the PostgreSQL table/view definitions at `.github/oracle-to-postgres-migration/DDL/Postgres/{ProjectName}/Tables and Views/` for target schema details.
**Step 3: Write the migrated procedure to Postgres output directory**
-Place each migrated procedure in its own file under `.github/oracle-to-postgres-migration/DDL/Postgres/Procedures and Functions/{PACKAGE_NAME_IF_APPLICABLE}/`. One procedure per file.
+Place each migrated procedure in its own file under `.github/oracle-to-postgres-migration/DDL/Postgres/{ProjectName}/Procedures and Functions/{PACKAGE_NAME_IF_APPLICABLE}/`. One procedure per file.
+
+> `{ProjectName}` is the project's assembly/folder name with spaces normalized to `-` (e.g. `MyApp.DataAccess`). This matches the path used by the agent and other migration skills.
diff --git a/skills/reviewing-oracle-to-postgres-migration/references/REFERENCE.md b/skills/reviewing-oracle-to-postgres-migration/references/REFERENCE.md
index 830f722125..a0799e751c 100644
--- a/skills/reviewing-oracle-to-postgres-migration/references/REFERENCE.md
+++ b/skills/reviewing-oracle-to-postgres-migration/references/REFERENCE.md
@@ -4,7 +4,10 @@
| --- | --- |
| [empty-strings-handling.md](empty-strings-handling.md) | Oracle treats '' as NULL; PostgreSQL keeps empty strings distinct—patterns to align behavior in code, tests, and migrations. |
| [no-data-found-exceptions.md](no-data-found-exceptions.md) | Oracle SELECT INTO raises "no data found"; PostgreSQL doesn’t—add explicit NOT FOUND handling to mirror Oracle behavior. |
+| [oracle-nvl-decode-functions.md](oracle-nvl-decode-functions.md) | Oracle NVL/NVL2/DECODE have no direct equivalents—replace with COALESCE, CASE WHEN, and NULL-safe comparisons. |
| [oracle-parentheses-from-clause.md](oracle-parentheses-from-clause.md) | Oracle allows `FROM(TABLE_NAME)` syntax; PostgreSQL requires `FROM TABLE_NAME`—remove unnecessary parentheses around table names. |
+| [oracle-rownum-pagination.md](oracle-rownum-pagination.md) | Oracle ROWNUM is assigned before ORDER BY; replace top-N and pagination patterns with LIMIT/OFFSET. |
+| [oracle-sysdate-sequences-dual.md](oracle-sysdate-sequences-dual.md) | Replace SYSDATE/SYSTIMESTAMP with NOW(), sequence .NEXTVAL with nextval('seq'), and remove FROM DUAL. |
| [oracle-to-postgres-sorting.md](oracle-to-postgres-sorting.md) | How to preserve Oracle-like ordering in PostgreSQL using COLLATE "C" and DISTINCT wrapper patterns. |
| [oracle-to-postgres-to-char-numeric.md](oracle-to-postgres-to-char-numeric.md) | Oracle allows TO_CHAR(numeric) without format; PostgreSQL requires format string—use CAST(numeric AS TEXT) instead. |
| [oracle-to-postgres-type-coercion.md](oracle-to-postgres-type-coercion.md) | PostgreSQL strict type checks vs. Oracle implicit coercion—fix comparison errors by quoting or casting literals. |
diff --git a/skills/reviewing-oracle-to-postgres-migration/references/oracle-nvl-decode-functions.md b/skills/reviewing-oracle-to-postgres-migration/references/oracle-nvl-decode-functions.md
new file mode 100644
index 0000000000..b4892626d0
--- /dev/null
+++ b/skills/reviewing-oracle-to-postgres-migration/references/oracle-nvl-decode-functions.md
@@ -0,0 +1,79 @@
+# Oracle to PostgreSQL: NVL, DECODE, and Null-Handling Functions
+
+## Problem
+
+Oracle provides several functions — `NVL`, `NVL2`, `DECODE` — that have no direct equivalents in standard SQL but are commonly used in Oracle stored procedures and inline SQL. PostgreSQL uses standard SQL alternatives: `COALESCE`, `NULLIF`, and `CASE` expressions.
+
+## Behavior Comparison
+
+### NVL
+
+**Oracle:** `NVL(expr, replacement)` — returns `replacement` if `expr` is `NULL`, otherwise `expr`.
+
+**PostgreSQL:** Use `COALESCE(expr, replacement)` — semantically identical for two arguments.
+
+```sql
+-- Oracle
+NVL(column_name, 'default')
+
+-- PostgreSQL
+COALESCE(column_name, 'default')
+```
+
+### NVL2
+
+**Oracle:** `NVL2(expr, not_null_val, null_val)` — returns `not_null_val` if `expr` IS NOT NULL, `null_val` if NULL.
+
+**PostgreSQL:** No direct equivalent — use `CASE`:
+
+```sql
+-- Oracle
+NVL2(column_name, 'has value', 'no value')
+
+-- PostgreSQL
+CASE WHEN column_name IS NOT NULL THEN 'has value' ELSE 'no value' END
+```
+
+### DECODE
+
+**Oracle:** `DECODE(expr, search1, result1, search2, result2, ..., default)` — equality-based switch.
+
+**PostgreSQL:** No `DECODE` function — use `CASE WHEN`:
+
+```sql
+-- Oracle
+DECODE(status, 1, 'Active', 2, 'Inactive', 'Unknown')
+
+-- PostgreSQL
+CASE status
+ WHEN 1 THEN 'Active'
+ WHEN 2 THEN 'Inactive'
+ ELSE 'Unknown'
+END
+```
+
+Note: `DECODE` in Oracle treats two `NULL` values as equal (unlike `=`). If any search value is `NULL`, use `IS NULL` in the `CASE` equivalent:
+
+```sql
+-- Oracle: DECODE treats NULL = NULL
+DECODE(col, NULL, 'empty', col)
+
+-- PostgreSQL
+CASE WHEN col IS NULL THEN 'empty' ELSE col END
+```
+
+## Migration Actions
+
+### 1. Stored Procedures
+
+Apply the direct substitutions above. Pay special attention to:
+- `NVL` on numeric expressions — `COALESCE` is type-sensitive in PostgreSQL; ensure both arguments are the same type or cast explicitly.
+- `DECODE` with `NULL` search values — replace with `IS NULL` guard in the `CASE` expression.
+
+### 2. Application Code (inline SQL strings)
+
+Search C# string literals and query builders for `NVL(`, `NVL2(`, and `DECODE(`. Apply the same substitutions.
+
+### 3. Tests
+
+Write test cases that exercise `NULL` inputs specifically — the Oracle → PostgreSQL translation of `NVL`/`COALESCE` is straightforward, but edge cases around NULL equality in `DECODE` → `CASE` are a common source of silent behavioral differences.
diff --git a/skills/reviewing-oracle-to-postgres-migration/references/oracle-rownum-pagination.md b/skills/reviewing-oracle-to-postgres-migration/references/oracle-rownum-pagination.md
new file mode 100644
index 0000000000..be1754700b
--- /dev/null
+++ b/skills/reviewing-oracle-to-postgres-migration/references/oracle-rownum-pagination.md
@@ -0,0 +1,75 @@
+# Oracle to PostgreSQL: ROWNUM Pagination vs LIMIT/OFFSET
+
+## Problem
+
+Oracle uses `ROWNUM` pseudo-column for pagination and row-limiting. PostgreSQL uses standard `LIMIT` / `OFFSET` syntax. `ROWNUM` is also fundamentally different in *when* it is assigned, which affects filtering behavior.
+
+## Behavior Comparison
+
+**Oracle:**
+- `ROWNUM` is assigned before `ORDER BY` — filtering with `ROWNUM` on an unordered result set is non-deterministic
+- Common pattern to get "top N ordered rows" requires a subquery:
+ ```sql
+ SELECT * FROM (SELECT * FROM t ORDER BY col) WHERE ROWNUM <= 10
+ ```
+- `ROWNUM BETWEEN n AND m` requires a double-wrapped subquery
+
+**PostgreSQL:**
+- `LIMIT n` restricts result rows after `ORDER BY` is applied — straightforward and deterministic
+- `OFFSET n` skips rows; combine with `LIMIT` for pagination
+- No `ROWNUM` pseudo-column exists
+
+## Code Example
+
+```sql
+-- Oracle: top 10 rows by date
+SELECT * FROM (
+ SELECT * FROM orders ORDER BY created_at DESC
+) WHERE ROWNUM <= 10;
+
+-- PostgreSQL equivalent
+SELECT * FROM orders ORDER BY created_at DESC LIMIT 10;
+
+-- Oracle: rows 11–20 (keyset pagination via ROWNUM)
+SELECT * FROM (
+ SELECT t.*, ROWNUM rn FROM (
+ SELECT * FROM orders ORDER BY created_at DESC
+ ) t WHERE ROWNUM <= 20
+) WHERE rn > 10;
+
+-- PostgreSQL equivalent
+SELECT * FROM orders ORDER BY created_at DESC LIMIT 10 OFFSET 10;
+```
+
+## Migration Actions
+
+### 1. Stored Procedures
+
+Replace all `ROWNUM`-based limiting patterns with `LIMIT`/`OFFSET`:
+
+```sql
+-- Oracle
+WHERE ROWNUM = 1
+WHERE ROWNUM <= :n
+
+-- PostgreSQL
+LIMIT 1
+LIMIT :n -- note: use $n parameter style in PL/pgSQL
+```
+
+For subquery wrapping patterns:
+```sql
+-- Oracle
+SELECT * FROM (SELECT ... ORDER BY col) WHERE ROWNUM <= :n
+
+-- PostgreSQL
+SELECT ... ORDER BY col LIMIT :n
+```
+
+### 2. Application Code (inline SQL strings)
+
+Search for `ROWNUM` in C# string literals, `StringBuilder`, and query-builder methods. Apply the same replacement patterns above.
+
+### 3. Tests
+
+Ensure integration tests validate that result set sizes are correct and that ordering is preserved (i.e., the correct *n* rows are returned, not just any *n* rows).
diff --git a/skills/reviewing-oracle-to-postgres-migration/references/oracle-sysdate-sequences-dual.md b/skills/reviewing-oracle-to-postgres-migration/references/oracle-sysdate-sequences-dual.md
new file mode 100644
index 0000000000..c07349029b
--- /dev/null
+++ b/skills/reviewing-oracle-to-postgres-migration/references/oracle-sysdate-sequences-dual.md
@@ -0,0 +1,86 @@
+# Oracle to PostgreSQL: Date Functions, Sequences, and DUAL
+
+## Problem
+
+Oracle relies on several built-in constructs — `SYSDATE`, `SYSTIMESTAMP`, sequence `NEXTVAL` syntax, and the `DUAL` dummy table — that do not exist in PostgreSQL. Each requires a direct substitution.
+
+## SYSDATE and SYSTIMESTAMP
+
+**Oracle:**
+- `SYSDATE` — returns the current date and time (no time zone) as an Oracle `DATE` type
+- `SYSTIMESTAMP` — returns the current timestamp with time zone
+
+**PostgreSQL:**
+- Use `NOW()` or `CURRENT_TIMESTAMP` for timestamp with time zone
+- Use `CURRENT_DATE` for date only
+- Use `LOCALTIMESTAMP` for timestamp without time zone (closer to Oracle's `SYSDATE` semantics)
+
+```sql
+-- Oracle
+SELECT SYSDATE FROM DUAL;
+INSERT INTO t (created_at) VALUES (SYSDATE);
+
+-- PostgreSQL
+SELECT NOW();
+INSERT INTO t (created_at) VALUES (NOW());
+-- or, if the column is DATE-only:
+INSERT INTO t (created_at) VALUES (CURRENT_DATE);
+```
+
+> **Warning:** Oracle `DATE` stores date *and* time; PostgreSQL `DATE` stores date only. If Oracle columns typed as `DATE` carry a time component, the PostgreSQL target column should be `TIMESTAMP`, not `DATE`.
+
+## Sequence NEXTVAL Syntax
+
+**Oracle:**
+```sql
+SELECT my_sequence.NEXTVAL FROM DUAL;
+INSERT INTO t (id) VALUES (my_sequence.NEXTVAL);
+```
+
+**PostgreSQL:**
+```sql
+SELECT nextval('my_sequence');
+INSERT INTO t (id) VALUES (nextval('my_sequence'));
+```
+
+Key differences:
+- PostgreSQL `nextval()` is a function call with the sequence name as a quoted string argument
+- Oracle uses dot notation: `sequence_name.NEXTVAL`
+- Oracle also has `CURRVAL` → PostgreSQL `currval('sequence_name')`
+- If the column uses a `DEFAULT nextval(...)` constraint (set during Phase 4 DDL migration), application code can omit the sequence call entirely and omit the column from the `INSERT`
+
+## DUAL Table
+
+Oracle requires a `FROM DUAL` clause in `SELECT` statements that evaluate expressions without a real table. PostgreSQL does not have `DUAL` — expressions can be selected without a `FROM` clause.
+
+```sql
+-- Oracle
+SELECT 1 + 1 FROM DUAL;
+SELECT SYSDATE FROM DUAL;
+SELECT my_sequence.NEXTVAL FROM DUAL;
+
+-- PostgreSQL
+SELECT 1 + 1;
+SELECT NOW();
+SELECT nextval('my_sequence');
+```
+
+> **orafce extension:** If `orafce` is installed, it provides a `DUAL` view that makes Oracle-style `FROM DUAL` queries work without changes. This is a useful transitional aid but should not be relied on permanently.
+
+## Migration Actions
+
+### 1. Stored Procedures
+
+- Replace all `SYSDATE` / `SYSTIMESTAMP` references with `NOW()` or `CURRENT_TIMESTAMP` (verify column type — use `LOCALTIMESTAMP` if the target is `TIMESTAMP WITHOUT TIME ZONE`)
+- Replace `sequence_name.NEXTVAL` with `nextval('sequence_name')`
+- Replace `sequence_name.CURRVAL` with `currval('sequence_name')`
+- Remove `FROM DUAL` from all expression-only `SELECT` statements
+
+### 2. Application Code (inline SQL strings)
+
+Search C# string literals for `SYSDATE`, `SYSTIMESTAMP`, `.NEXTVAL`, `.CURRVAL`, and `FROM DUAL`. Apply the same substitutions.
+
+### 3. Tests
+
+- Verify datetime assertions use timezone-safe comparisons (see `oracle-to-postgres-timestamp-timezone.md` for Npgsql-specific behavior)
+- Verify sequence-dependent IDs are correctly populated in assertions
diff --git a/skills/scaffolding-oracle-to-postgres-migration-test-project/SKILL.md b/skills/scaffolding-oracle-to-postgres-migration-test-project/SKILL.md
index efcb33d684..294997539c 100644
--- a/skills/scaffolding-oracle-to-postgres-migration-test-project/SKILL.md
+++ b/skills/scaffolding-oracle-to-postgres-migration-test-project/SKILL.md
@@ -1,6 +1,6 @@
---
name: scaffolding-oracle-to-postgres-migration-test-project
-description: 'Scaffolds an xUnit integration test project for validating Oracle-to-PostgreSQL database migration behavior in .NET solutions. Creates the test project, transaction-rollback base class, and seed data manager. Use when setting up test infrastructure before writing migration integration tests, or when a test project is needed for Oracle-to-PostgreSQL validation.'
+description: 'Scaffolds an xUnit integration test project targeting Oracle in .NET solutions. Creates the test project, transaction-rollback base class, and seed data manager. Use only during Phase 3, before writing Oracle baseline integration tests. Do not invoke during Phase 6 — the PostgreSQL test project is produced by migrating this project, not by running this skill again.'
---
# Scaffolding an Integration Test Project for Oracle-to-PostgreSQL Migration
@@ -25,7 +25,7 @@ Read the target project's `.csproj` to determine the .NET version and existing p
**Step 2: Create the xUnit test project**
- Target the same .NET version as the application under test.
-- Add NuGet packages for Oracle database connectivity and xUnit.
+- Add NuGet packages for Oracle database connectivity (`Oracle.ManagedDataAccess.Core`) and xUnit.
- Add a project reference to the target project only — no other application projects.
- Add an `appsettings.json` configured for Oracle database connectivity.
@@ -40,7 +40,6 @@ Read the target project's `.csproj` to determine the .NET version and existing p
- Create a global seed manager for loading test data within the transaction scope.
- Do not commit seed data — transactions roll back after each test.
- Do not use `TRUNCATE TABLE` — preserve existing database data.
-- Reuse existing seed files if available.
- Establish a naming convention for seed file location that downstream test creation will follow.
**Step 5: Verify the project compiles**
@@ -49,6 +48,7 @@ Build the test project and confirm it compiles with zero errors before finishing
## Key Constraints
-- Oracle is the golden behavior source — scaffold for Oracle first.
+- **Phase 3 only** — this skill scaffolds the Oracle-targeting test project. The PostgreSQL test project (Phase 6) is created by copying and migrating this project; do not run this skill again at that point.
+- Oracle is the golden behavior source — scaffold for Oracle only, not PostgreSQL.
- Keep to existing .NET and C# versions; do not introduce newer language or runtime features.
- Output is an empty test project with infrastructure only — no test cases.