| name | powerplatform-st |
| description | Power Platform ST is Satrio Tsubasa's personal layered-repo overlay for Microsoft Power Platform and Dataverse development. Use when the work is in a layered enterprise Dataverse repo shaped as `<Prefix>.<Domain>.Business` / `.Data` / `.Plugins` with authored `WebResources/`, `*.PCF` wrapper solutions, `Word Templates/`, and `Dataverse/` metadata mirrors — where the folder prefix and namespace are chosen per project/client rather than fixed. It keeps generated `*.Data` generator-owned, treats `WebResources/` as authored source versus the packaged Dataverse mirror, and applies patch-solution delivery and stale-package guardrails. It is a thin overlay on top of the `powerplatform-core` plugin: it adds layered-repo house rules and defers all execution to Core. Requires the `powerplatform-core` plugin to be installed in the same agent. |
Power Platform ST Development
Power Platform ST is a personal, client-agnostic overlay for the layered enterprise Dataverse repo shape. It is for projects organized as:
<Prefix>.<Domain>.sln
<Prefix>.<Domain>.Business/
<Prefix>.<Domain>.Data/
<Prefix>.<Domain>.Plugins/
WebResources/
<Prefix>.<Domain>.PCF/ # optional
Word Templates/ # optional
Dataverse/ # optional local metadata reference
Tools/ # optional
Reference/ # optional
The prefix and namespace are not fixed — you choose them at the start of each project (per client, per solution). The overlay preserves the shape and the boundaries, while the names come from the project profile or from you.
Use $powerplatform-st when the repo follows this layered shape and preserving its boundaries matters. The overlay keeps the agent from flattening the layers, hand-editing generated *.Data, treating a packaged mirror as authored source, escalating a narrow ribbon change into a whole-solution import, or importing a stale package.
Requires the powerplatform-core plugin
This overlay is not a standalone runtime. It carries only the layered-repo house rules and this overlay's references. Every actual operation — repo discovery, authentication, the live-mutation preflight, the Dataverse SDK/Web API helpers, deployment, and verification — comes from the powerplatform-core plugin, which must be installed in the same agent.
How the two fit together:
- Core does the work. Open the matching Core skill to run the actual operation: the orchestrator
powerplatform-core for discovery, surface choice, and the preflight; then a domain skill (dataverse-schema, data-operations, power-automate-flows, plugins-server-extensions, pcf-and-web-resources, code-apps, solution-alm-delivery, security-roles, document-generation, custom-connectors, platform-administration).
- ST adds the house rules. Apply the layered-repo rules below on top of Core's generic workflow whenever they are stricter.
- If the
powerplatform-core plugin is not installed, stop and tell the user to install it first (/plugin install powerplatform-core@powerplatform-core in Claude Code, or the /plugins browser in Codex). Do not try to reimplement Core's helpers here.
Project bootstrap: establish the naming convention first
Because the prefix is per project, settle the convention before generating or moving code. Do this once at the start and record it so the rest of the project is consistent.
- Read the project profile. If the repo has
.codex/power-platform.project-profile.json or power-platform.project-profile.json, trust its namespaceRoot, publisherPrefix, mainSolutionUniqueName, and sourceAreas. See references/project-profile.example.json.
- Infer from existing artifacts. If there's no profile, infer the prefix from the existing
.sln/project names, builderSettings.json/early-bound generator config (publisher prefix), and the folder layout.
- Ask when ambiguous. If the repo is new or the convention can't be inferred, ask the user for: the namespace root / folder prefix (e.g.
Contoso.Sales), the Dataverse publisher prefix (e.g. contoso, which is separate from the code namespace), and the main solution unique name. Do not assume the publisher prefix matches the code namespace.
- Record it. Write the answers into
power-platform.project-profile.json so discovery and later sessions stay consistent, then apply the layered conventions using that prefix.
Throughout this skill, <Prefix> and <Domain> are placeholders for whatever you established here (examples use Contoso).
How it works
- Discover with Core. Ask the
powerplatform-core orchestrator to discover the repo (its discover_context helper); add live PAC auth only when live access matters.
- Establish/confirm the convention using the project bootstrap above.
- Run Core's workflow. Choose the surface, edit source, validate, run the live-mutation preflight, then deliver through the narrowest approved primitive — all via the matching Core skill.
- Apply the layered-repo overlay rules below whenever they are stricter than generic Core guidance.
Mandatory live mutation preflight
Before any live Dataverse mutation, run Core's live-mutation preflight (via the powerplatform-core / solution-alm-delivery skills, e.g. validate_delivery.py --preflight-spec ...) and include the overlay-specific fields below.
Required fields (Core's set, plus overlay additions):
- target environment URL and active PAC profile
- target solution unique name, patch status, and parent solution when selected
- mutation type and exact components touched
- delivery primitive and whether it is targeted
- artifact path, modified time, solution name/version, managed state, and component diff when any ZIP/package is used
- blast radius: targeted, component subset, patch package, or full solution
- rollback or recovery plan, timeout, and fallback path
- explicit confirmation when the primitive is not targeted
- consuming repo
CODEX_HANDOFF.md status
- whether any separately managed PCF package solution is excluded from the patch/package
If the primitive becomes solution import, stop before import and state that this is no longer a fast targeted deploy. Give the expected 10-30 minute window for import, publish, cache refresh, and read-back verification, then ask for explicit approval unless the user already approved that blast radius.
Do not import ZIPs from bin, Release, Downloads, old temp folders, stale hotfix/build output, or old package names unless the artifact was generated in the current session or explicitly selected by the user after path, timestamp, solution identity, version, managed state, and component diff are shown.
Layered-repo hard gates
- Treat the environment the user names as
DEV/working and a separate environment as validation. Do not touch production without explicit instruction.
- When an unmanaged patch or a specific working solution is selected, add or update only scoped components there.
- Treat a separately managed PCF package solution as out of scope for the app patch audit unless the repo profile says otherwise.
- Never merge, delete, clone, or retire Dataverse patches unless the user explicitly asks for that lifecycle action.
- If a same-version patch import fails, bump the patch version or use a supported targeted update path. Do not retry stale local packages.
- If the parent solution has patches, do not attempt parent export/import as a fallback.
- Do not silently escalate form, ribbon, or metadata changes to full solution import. Use Core's targeted metadata helpers (
patch_form_xml.py, patch_form_ribbon.py, direct metadata update) or a repo-owned wrapper; otherwise stop and ask.
- For subgrid command bars, keep RibbonDiffXml stable where possible and move selected-row visibility or enablement logic into JavaScript
CustomRule inside authored WebResources/. Avoid XML ValueRule for status or field logic unless that exact rule shape is already proven in the live grid.
- When a button depends on a status or derived value, check both the raw stored field and any display/calculated field the grid actually exposes before choosing the rule surface — subgrids often surface a derived column rather than the raw one.
- For new entity command-bar buttons, commands, action bindings, or display rules in a selected patch, do not try the form-ribbon helper first. Fresh-export the selected live patch, overlay only the scoped
Entities/<entity>/RibbonDiff.xml and authored web resource, bump the patch version before import, import, targeted publish, and read back the patch.
- Do not pack or import the local parent solution as a shortcut when the target is the selected live patch.
Managed promotion audit
Before promotion closeout (working environment → validation → production), apply Core's managed promotion audit (validate_delivery.py --promotion-audit-spec) and add these overlay checks:
- confirm
CODEX_HANDOFF.md and the release/issue list agree on expected components
- audit selected patch membership before export
- exclude separately managed PCF package solutions unless the repo profile says they are in scope
- compare authored
WebResources/ hashes or content markers against packaged mirror evidence and target live content
- read back selected-patch command-bar metadata after import, publish, and hard refresh
If target solution version updates but selected-patch ribbon or command metadata remains stale, do not keep importing new packages blindly. Run targeted publish/read-back first. If still stale, inspect solution layers. Use scoped remediation only after the validation environment confirms the approach.
Source boundaries
<Prefix>.<Domain>.Business: shared business logic and orchestration.
<Prefix>.<Domain>.Plugins: thin Dataverse entry points and custom API handlers. Delegate into *.Business.
<Prefix>.<Domain>.Data: generated early-bound entities, option sets, service context, and metadata helpers. Read or regenerate it, but do not hand-edit generated files.
WebResources/: authored JavaScript, HTML, CSS, JSON, and image source. This is the source of truth for browser assets.
Dataverse/.../WebResources: packaged/export mirror or drift evidence unless the project profile explicitly marks it as source. Do not edit it first when WebResources/ contains the authored asset.
Dataverse/: metadata reference or unpacked working source for forms, views, tables, relationships, ribbon, and solution XML.
Word Templates/: source-controlled .docx templates and document-generation inputs.
<Prefix>.<Domain>.PCF: PCF source and wrapper Solutions packaging.
Data/: optional supplemental JSON/config source used by migration or seed flows. Do not confuse it with the namespaced *.Data code project when both exist.
Reference/: human reference material, not deployment source.
Deployment fast paths
Each row maps a change to the Core skill that executes it, plus the overlay rule that constrains it.
| Change | Core skill | Overlay rule |
|---|
| authored JS/HTML/CSS web resource | pcf-and-web-resources (web resource sync / batch) | edit WebResources/ first; refresh the Dataverse/.../WebResources mirror only after live and authored source agree |
| plug-in code | plugins-server-extensions (build + push) | edit *.Business/*.Plugins, keep entry points thin, then verify step state |
generated *.Data needed | dataverse-schema / generator config | update generator settings or regenerate; do not hand-edit generated classes |
| form metadata | dataverse-schema (patch_form_xml.py, update_main_form.py, direct metadata update) | do not escalate to full solution import |
| subgrid command visibility | pcf-and-web-resources | prefer authored WebResources/ JavaScript CustomRule; deploy web-resource-only when metadata already points at the rule |
| form-level RibbonDiffXml | dataverse-schema (patch_form_ribbon.py, direct metadata update) | keep the diff scoped |
| entity command bar / new button / new command / new display rule | solution-alm-delivery (patch export/import) | fresh-export selected live patch, overlay scoped Entities/<entity>/RibbonDiff.xml, bump version before import, import, targeted publish, read back |
| PCF | pcf-and-web-resources (version_pcf_solution.py, deploy_pcf.py) | version the 3-part manifest and the 4-part wrapper solution together; deploy a fresh package |
| config data | data-operations (upsert_data.py) | produce dry-run/diff first, then keyed SDK/Web API; never delete rows unless requested |
| latest metadata reference | dataverse-schema (ensure_dataverse_reference.py) | hydrate or refresh Dataverse/<solution> from the selected live solution |
| promotion package | solution-alm-delivery | audit patch membership first, exclude separately managed PCF if configured, export/generate fresh only, then run the managed promotion read-back |
References
This overlay owns two local references:
- Open references/layered-conventions.md for the full layered-repo conventions: source ownership, generated
*.Data boundaries, authored/mirror web resources, classic namespaced JavaScript, PCF wrapper version alignment, and patch/package guardrails.
- Open references/project-profile.example.json as a template for the consuming repo's
power-platform.project-profile.json.
Everything else comes from the Core plugin. Open the matching Core references (via the powerplatform-core skills) for execution automation, solution patches, verification and recovery, Dataverse metadata, data operations, client customization, server extensions, PCF, flows, security roles, document generation, and XML/query work as needed.
Reporting
Report the established naming convention, what changed in source, what the live preflight showed, which environment and solution were targeted, which components were deployed or only prepared, whether any separately managed PCF package was excluded, what was validated, and which import, publish, registration, or promotion steps were intentionally not performed.