Skip to content
Merged
Show file tree
Hide file tree
Changes from 39 commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
124c6bd
plan-alm: convert to strict plan-only planner (execution skills self-…
tyaginidhi Jun 17, 2026
4d50c9e
Address Copilot review on #191
tyaginidhi Jun 17, 2026
2fd9aa6
Self-review fixes: PP-path activate step, manual steps[], EDM error rule
tyaginidhi Jun 17, 2026
298fcf0
Address Copilot second-pass review on #191
tyaginidhi Jun 17, 2026
9f66e35
Fix step-sync stage matching: marker "Deploy to {label}" vs plan step…
tyaginidhi Jun 17, 2026
16f3d32
Address Copilot third-pass: stable reconcile() nextStep contract
tyaginidhi Jun 17, 2026
be368a6
Harden stage matching: shared normalizeStageLabel for keys too
tyaginidhi Jun 17, 2026
776356d
Potential fix for pull request finding
tyaginidhi Jun 17, 2026
e59db35
Address Copilot fourth-pass on #191
tyaginidhi Jun 17, 2026
ed2ad59
EDM (enhanced/standard data-model) Power Pages site support in ALM di…
tyaginidhi Jun 17, 2026
c5db654
Site-referenced table discovery + dependency-aware solution splitting
tyaginidhi Jun 17, 2026
56b996f
Fix FFD bin-packing under-allocation that overflowed the schema-attr cap
tyaginidhi Jun 17, 2026
5e3d1ab
Wire --projectRoot into the remaining discover-site-components consumers
tyaginidhi Jun 17, 2026
696d41c
Enforce ALM plan refresh via PostToolUse reconcile backstop (auto-heal)
tyaginidhi Jun 17, 2026
e74e4b7
Surface reconcile failures in the hook + document failed[] contract
tyaginidhi Jun 17, 2026
a5e20e7
Fix stale "plan-alm Phases 6/7/8" reference in AGENTS.md
tyaginidhi Jun 17, 2026
dfb672a
Activate the PLAN_STATUS lifecycle: Approved -> In Execution -> Compl…
tyaginidhi Jun 17, 2026
3db879d
Surface COMPLETED_AT in the ALM plan footer
tyaginidhi Jun 17, 2026
f5ca2bb
Site-referenced table discovery + dependency-aware solution splitting
tyaginidhi Jun 17, 2026
be4a70d
Fix FFD bin-packing under-allocation that overflowed the schema-attr cap
tyaginidhi Jun 17, 2026
e55e06d
Wire --projectRoot into the remaining discover-site-components consumers
tyaginidhi Jun 17, 2026
bb6f7f7
Address #193 review: attr-cap overflow warning + componentCount proxy…
tyaginidhi Jun 18, 2026
6e8b081
Resolve merge conflicts with origin/users/nityagi/table-discovery-fix
Copilot Jun 18, 2026
91be9fd
Resolve merge conflicts with origin/users/nityagi/table-discovery-fix…
Copilot Jun 18, 2026
525405a
Merge main into branch: resolve conflicts after stacked PRs landed
Copilot Jun 19, 2026
673ae86
Fix incomplete Open Plugins resolution in the merge (#194)
tyaginidhi Jun 19, 2026
1f5ddd2
Address #194 review: DRY plan path + hook smoke test + completion-edg…
tyaginidhi Jun 22, 2026
f27128f
Address #194 Copilot review comments (3)
tyaginidhi Jun 22, 2026
af087e7
plan-alm: move PLAN_STATUS badge next to the "Generated" line
tyaginidhi Jun 22, 2026
356f63f
plan-alm: deterministic Draft/Approved status write + consistency gua…
tyaginidhi Jun 22, 2026
dd7bb4e
Merge origin/main into users/nityagi/plan-status-tag-fix (resolve con…
Copilot Jun 22, 2026
d2caebb
Sync legacy JSON mirrors to power-pages v2.6.0 (mirror drift after me…
tyaginidhi Jun 22, 2026
8bc302c
Merge remote-tracking branch 'origin/main' into users/nityagi/plan-st…
tyaginidhi Jun 22, 2026
1df51b3
plan-alm: address #202 review — robust approver coercion + runnable r…
tyaginidhi Jun 22, 2026
cb68f86
plan-alm: fix 5 issues surfaced by an EDM-site end-to-end run
tyaginidhi Jun 22, 2026
6c3a048
plan-alm: rename siteType data-model → declarative + final-review fixes
tyaginidhi Jun 22, 2026
6367f1d
set-plan-status: make --render atomic across plan-data + HTML
tyaginidhi Jun 22, 2026
aa2cfa6
estimate-solution-size: fix resolveSiteType docstring (legacy alias i…
tyaginidhi Jun 22, 2026
6dcf7c3
deploy-pipeline: pin --envUrl from project config + re-refresh plan a…
tyaginidhi Jun 22, 2026
b814c62
ALM: env-drift guard, 400-vs-404 deploy path, stage reconciliation, e…
tyaginidhi Jun 22, 2026
25a35b6
Address #202 review: fix two inaccurate code comments
tyaginidhi Jun 22, 2026
df4265b
Final-review fixes: harden env-match assertion + SKILL.md coherence
tyaginidhi Jun 22, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .claude-plugin/marketplace.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
"source": "./plugins/power-pages",
"description": "Power Pages development and management plugin for Claude Code and GitHub Copilot",
"category": "development",
"version": "2.5.0",
"version": "2.6.0",
"license": "MIT",
"tags": [
"power platform",
Expand Down
2 changes: 1 addition & 1 deletion marketplace.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
"source": "./plugins/power-pages",
"description": "Power Pages development and management plugin for Claude Code and GitHub Copilot",
"category": "development",
"version": "2.5.0",
"version": "2.6.0",
"license": "MIT",
"tags": [
"power platform",
Expand Down
2 changes: 1 addition & 1 deletion plugins/power-pages/.claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "power-pages",
"version": "2.5.0",
"version": "2.6.0",
"description": "Create and deploy Power Pages sites using modern development approaches. Supports code sites (SPAs) with React, Angular, Vue, or Astro. Includes ALM orchestration (plan-alm) with a solution-splitting decision tree, per-solution pipelines, Azure Blob asset advisory, manifest schema v2 for multi-solution deployments, and force-link remediation for cross-host pipeline migrations.",
"author": {
"name": "Microsoft",
Expand Down
2 changes: 1 addition & 1 deletion plugins/power-pages/.plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "power-pages",
"version": "2.5.0",
"version": "2.6.0",
"description": "Create and deploy Power Pages sites using modern development approaches. Supports code sites (SPAs) with React, Angular, Vue, or Astro. Includes ALM orchestration (plan-alm) with a solution-splitting decision tree, per-solution pipelines, Azure Blob asset advisory, manifest schema v2 for multi-solution deployments, and force-link remediation for cross-host pipeline migrations.",
"author": {
"name": "Microsoft",
Expand Down
5 changes: 4 additions & 1 deletion plugins/power-pages/AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -198,9 +198,11 @@ Shared lib modules live at `scripts/lib/` and are imported by other scripts via
#### ALM Prerequisites & Context

- `scripts/lib/verify-alm-prerequisites.js`: Verifies all prerequisites for ALM skills — PAC CLI installed + authenticated (`pac env who`), Azure CLI installed + logged in, Dataverse API reachable (`WhoAmI`). Args: `--envUrl` (opt, overrides env from PAC CLI), `--require-manifest` (fails if `.solution-manifest.json` not found). Output: `{ envUrl, token, userId, organizationId, tenantId }`. Exit 0 on success, exit 1 on any failure. Used by `setup-solution`, `export-solution`, `import-solution`, `setup-pipeline`, `deploy-pipeline`, `plan-alm`.
- `scripts/lib/detect-project-context.js`: Reads Power Pages project context from the project root. The `siteType` discriminator is the **build axis** — code/SPA vs declarative (design-studio) site — NOT the Dataverse data-model axis (a declarative site can be on the standard OR enhanced data model; both download to a `.powerpages-site/` tree). `siteType: "data-model"` is the (compat-named) declarative bucket; a future pass may rename it `"declarative"`. Resolves identity in order: (1) `powerpages.config.json` → `siteType: "code"` (code/SPA sites); (2) `.powerpages-site/` → `siteType: "data-model"` (declarative design-studio sites — standard or enhanced data model — which have **no** `powerpages.config.json`). The **authoritative declarative marker is the `.powerpages-site/.portalconfig/` directory** (only declarative sites have it); `website.yml` is the identity source (`id`→`websiteRecordId`, `name`→`siteName`) but is NOT a reliable declarative signal alone because **both** site types carry it. `environmentUrl: null` for declarative sites (no env URL in the local files — callers re-confirm via `pac env who`). Also reads `.solution-manifest.json` and `.datamodel-manifest.json`. Args: `--projectRoot` (opt). Output: `{ projectRoot, siteType, siteName, websiteRecordId, environmentUrl, solutionManifest, datamodelManifest }`. Exit 0 on success, exit 1 only if neither `powerpages.config.json` nor a `.powerpages-site/` (`.portalconfig/`/`website.yml`) marker is found. Note: `findProjectRoot` (in `validation-helpers.js`) likewise treats a `.powerpages-site/` directory as a project-root marker.
- `scripts/lib/detect-project-context.js`: Reads Power Pages project context from the project root. The `siteType` discriminator is the **build axis** — code/SPA vs declarative (design-studio) site — NOT the Dataverse data-model axis (a declarative site can be on the standard OR enhanced data model; both download to a `.powerpages-site/` tree). `siteType: "declarative"` is the declarative bucket (it was historically labeled `"data-model"`; that value is now the legacy alias — nothing branches on the literal, so older plan-data carrying `"data-model"` stays equivalent). Resolves identity in order: (1) `powerpages.config.json` → `siteType: "code"` (code/SPA sites); (2) `.powerpages-site/` → `siteType: "declarative"` (declarative design-studio sites — standard or enhanced data model — which have **no** `powerpages.config.json`). The **authoritative declarative marker is the `.powerpages-site/.portalconfig/` directory** (only declarative sites have it); `website.yml` is the identity source (`id`→`websiteRecordId`, `name`→`siteName`) but is NOT a reliable declarative signal alone because **both** site types carry it. `environmentUrl: null` for declarative sites (no env URL in the local files — callers re-confirm via `pac env who`). Also reads `.solution-manifest.json` and `.datamodel-manifest.json`. Args: `--projectRoot` (opt). Output: `{ projectRoot, siteType, siteName, websiteRecordId, environmentUrl, solutionManifest, datamodelManifest }`. Exit 0 on success, exit 1 only if neither `powerpages.config.json` nor a `.powerpages-site/` (`.portalconfig/`/`website.yml`) marker is found. Note: `findProjectRoot` (in `validation-helpers.js`) likewise treats a `.powerpages-site/` directory as a project-root marker.
- `scripts/lib/alm-paths.js`: Single source of truth for ALM artifact paths. Exports `ALM_DIR` (always `docs/alm`), `FILE_NAMES` (frozen object mapping logical key → filename for all 14 ALM artifacts), `almDir(projectRoot) → path`, `almPath(projectRoot, key) → path`, `ensureAlmDir(projectRoot) → path` (mkdir -p idempotent). Every ALM-only state file (5 plan/decision JSONs + 9 `last-*.json` skill-run markers including `last-export.json`) writes under `<projectRoot>/docs/alm/`. **Always resolve through this helper** — never inline a raw `docs/alm/...` path in a script. Files intentionally NOT moved here (and not in `FILE_NAMES`): `.solution-manifest.json`, `.datamodel-manifest.json`, `.alm-config.json`, `.alm-deferred`, `deployment-settings.json`. Adding a new ALM marker means adding its key + filename to `FILE_NAMES` first; `almPath` throws on unknown keys to catch typos at call-site.
- `scripts/lib/check-alm-plan.js`: Phase 0 gate helper used by every ALM skill to detect (a) whether an ALM plan exists for this project, (b) whether the user has explicitly deferred ALM via the `.alm-deferred` marker, and (c) whether an existing plan is stale (the source solution was modified after the plan was generated). Args: `--projectRoot`, `--envUrl` (opt — required for staleness check), `--token` (opt), `--solutionId` (opt — required for staleness check). Output: `{ exists, deferred, deferral, planPath, htmlPath, stale, staleness: { reason, detail }, generatedAt, planStatus, solution: {...} }`. Without env/solution context the helper does an existence-only check; with them it queries Dataverse for `solutions(solutionId)?$select=modifiedon` and compares against `planData.generatedAt`. Used by `setup-solution`, `setup-pipeline`, `deploy-pipeline`, `export-solution`, `import-solution`, `configure-env-variables`, `ensure-pipelines-host`, `force-link-environment` Phase 0 gates — the "fail closed when no plan" pattern. **PLAN_STATUS lifecycle — promotes `Approved` → `In Execution`:** plan-alm is plan-only and leaves the plan `Approved`; this helper performs the `Approved` → `In Execution` transition (and writes the first heartbeat) the **first time an execution skill's Phase 0 runs** — it is the only thing that sets `In Execution`, so without it the heartbeat/active-chain machinery (multi-hour-deploy `stale-heartbeat` reclassification) never engages. Gated on heartbeat-write: read-only callers pass `--no-heartbeat` (plan-alm's own deferral check, audits, tests) and are never promoted. The terminal `In Execution` → `Completed` transition is owned by `refresh-alm-plan-data.js` (completion evaluator).
- `scripts/lib/set-plan-status.js`: **The single deterministic owner of the creation-time `Draft` / `Approved` write** — the one PLAN_STATUS transition that used to be done by hand-authored `Edit`s in plan-alm Phase 4 (to the HTML spans *and* the JSON), with no helper. Because the badge + `approved-by` / `approval-date` spans are re-derived from `docs/.alm-plan-data.json` on every render, the old manual HTML Edit was non-durable (reverted on the next refresh) and a partial write left the plan "approver recorded but PLAN_STATUS=Draft" — stuck forever, since `check-alm-plan.js` only promotes from `Approved`. This helper writes `PLAN_STATUS` + `PLAN_MODE` + `APPROVED_BY` + `APPROVAL_DATE` **together** (atomic temp+rename) and optionally re-renders (reuses `refresh-alm-plan-data.js → findRendererPath`/`invokeRenderer`). Enforced invariants: only `Draft` / `Approved` are settable here (`In Execution` is owned by `check-alm-plan.js`, `Completed` by `refresh-alm-plan-data.js`); `Approved` **requires** a non-empty `--approver`; `Draft` **clears** the approver fields; a plan already `In Execution` / `Completed` is **not** re-drafted without `--force`. Args: `--projectRoot`, `--status Draft|Approved`, `--approver`, `--approvalDate` (opt — defaults to now), `--force`, `--render`, `--rendererPath` (opt). Output: `{ ok, previousStatus, status, mode, approver, approvalDate, rendered }`. Called by plan-alm Phase 4 (both save options) and the Phase 1 step-0b in-place Draft→Approved fast-path. The `validate-plan-alm.js` consistency guard blocks the two half-written states (`Draft`+approver, `Approved`+no-approver) for plans created the old way or hand-edited.

- `scripts/lib/resolve-target-solution.js`: Resolves "which solution should this new Dataverse record land in?" Implements the strict 3-step order from the ALM-aware-by-default principle: (1) explicit `--solutionUniqueName` (or equivalent caller arg) wins; (2) `.solution-manifest.json` in the project root; (3) neither → throw `NoSolutionConfiguredError`. **The module NEVER auto-picks from Dataverse** — interactive prompt UX is the caller's responsibility (catch the error, present an `AskUserQuestion` list, re-invoke with `explicit` populated). Callers that need to confirm the solution still exists in Dataverse can pass `verifyExists: true`; the module then enriches the result with `{ solutionId, version, ismanaged }`. Component-creation scripts must require this helper and pass through `--solutionUniqueName` so records land in the user's solution instead of `Default`.

#### Solution Splitting Decision Tree (v1.3.0+)
Expand Down Expand Up @@ -231,6 +233,7 @@ Shared lib modules live at `scripts/lib/` and are imported by other scripts via

#### PP Pipelines

- `scripts/lib/list-environments.js`: Enumerates the Dataverse environments the signed-in PAC user can access, as JSON, for `ENV_LIST` pre-fill (plan-alm Phase 1 Step 5, setup-pipeline, ensure-pipelines-host "Other (paste URL)" prompts). **Why it exists:** the skills used to run `pac env list --output json`, which is INVALID on current PAC CLI (verified 2.8.1 — `pac env list` accepts only `--filter` and errors on `--output`), so the JSON pre-fill silently never worked. This helper runs the plain `pac env list` and parses its table (anchored on the env GUID + https URL + unique-name tokens, so display names with spaces survive). `pac admin list --json` was rejected as the source — it's admin-only and tenant-wide, the wrong scope for a per-user pre-fill. Exports `parseEnvList(stdout)` (pure, tested) + `listEnvironments()`. CLI prints a JSON array of `{ displayName, environmentId, environmentUrl, uniqueName, active }`; prints `[]` and exits 0 on any failure (unauthenticated PAC, parse miss) so callers degrade to manual entry. Match envs by `environmentUrl` origin.
- `scripts/lib/discover-pipelines-host.js`: Discovers the tenant-level default Power Platform Pipelines host environment URL by calling `RetrieveSetting('DefaultCustomPipelinesHostEnvForTenant')` on the dev/source environment. Args: `--envUrl`, `--token`, `--userId`. Output: `{ found, hostEnvUrl }`. Exit 0 (including when not found); exit 1 on error.
- `scripts/lib/create-deployment-environment.js`: Creates a `deploymentenvironments` record in the Pipelines host environment using the **unprefixed** field schema (`name`, `environmentid`, `environmenttype`), then polls `validationstatus` until Succeeded (`200000001`) or Failed (`200000002`). Args: `--hostEnvUrl`, `--token`, `--name`, `--bapEnvId`, `--environmentType` (`200000000` Dev / `200000001` Target), `--environmentUrl` (opt, only echoed in output marker). Idempotent: if a record already exists for the same `environmentid`, returns it with `reused: true`. Output: `{ deploymentEnvironmentId, name, bapEnvId, environmentUrl, environmentType, validationStatus, reused }`.
- `scripts/lib/create-deployment-pipeline.js`: Creates a `deploymentpipelines` record, associates the source environment via `$ref` (relative path + `@odata.context`), and creates `deploymentstages` records for each target environment. Args: `--hostEnvUrl`, `--token`, `--pipelineName`, `--description`, `--sourceDeploymentEnvironmentId`, `--stagesJson` (JSON array of `{ name, targetDeploymentEnvironmentId, order }`). Output: `{ pipelineId, pipelineName, stages[] }`.
Expand Down
4 changes: 3 additions & 1 deletion plugins/power-pages/references/approval-gates.md
Original file line number Diff line number Diff line change
Expand Up @@ -256,14 +256,16 @@ Each section lists every `AskUserQuestion` in that skill. Catalog rows are marke

---

### 6.1 `plan-alm` (15 calls; planner)
### 6.1 `plan-alm` (17 calls; planner)

> `plan-alm` is a **planner** — it produces an approved/draft HTML plan and never executes. The execution gates that used to live in Phases 5–8 (deploy-failure, post-deploy activation, manual export/import checkpoint) now belong to the individual ALM skills the user runs afterward; they are catalogued under those skills' sections, not here.

| ID | Kind | Category | Phase | Trigger / question | Cancel leaves |
|---|---|---|---|---|---|
| `plan-alm:1.deferral` | gate | progress | 1 | `.alm-deferred` marker present — *"Continue with deferral / remove and proceed / cancel"* | `deferral-marker` |
| `plan-alm:1.approve-draft` | gate | plan | 1 (0b) | Existing **Draft** plan found — *"Approve this draft now (no re-plan) / re-plan from scratch / cancel"*. Approve writes status via `set-plan-status.js` and exits | nothing |
| `plan-alm:1.completeness` | gate | progress | 1 | Completeness check found gaps — *"Sync first / plan with gaps / cancel"* | nothing |
| `plan-alm:1.env-match` | gate | progress | 1 (6b) | `pac env who` env ≠ project's (recorded-URL mismatch or `websiteRecordId` not found in connected env) — *"Switch PAC env & re-run / continue against connected env (degraded) / cancel"*. Only fires on a detected mismatch | nothing |
| `plan-alm:2.q1-existing` | gate | plan | 2 (Q1) | `SOLUTION_DONE=true` — *"Use existing solution **{name}**?"* | nothing |
| `plan-alm:2.q1-fresh` | gate | plan | 2 (Q1) | `SOLUTION_DONE=false` — *"Include solution setup in plan?"* | nothing |
| `plan-alm:2.q1b-split` | gate | plan | 2 (Q1b) | `RECOMMEND_SPLIT=true` — *"Follow recommended {strategy} split?"* | nothing |
Expand Down
6 changes: 3 additions & 3 deletions plugins/power-pages/references/cicd-pipeline-patterns.md
Original file line number Diff line number Diff line change
Expand Up @@ -513,13 +513,13 @@ Accept: application/json

Returns `{ "SettingValue": "{BAP-environment-GUID}" }` or empty/null if no default is configured.

Cross-reference the GUID with `pac env list` output to find the host environment URL:
Cross-reference the GUID with the environment list to find the host environment URL:

```bash
pac env list --output json 2>/dev/null
node "${PLUGIN_ROOT}/scripts/lib/list-environments.js"
```

Match on `EnvironmentId` field. If no match, probe each environment from `pac env list` with:
This emits a JSON array of `{ displayName, environmentId, environmentUrl, uniqueName, active }`. (It parses `pac env list`; the older `pac env list --output json` is invalid on current PAC CLI, which only accepts `--filter` on `env list`.) Match the GUID on the `environmentId` field. If no match, probe each environment from `pac env list` with:

```
GET {envUrl}/api/data/v9.1/deploymentpipelines?$top=0
Expand Down
2 changes: 1 addition & 1 deletion plugins/power-pages/scripts/check-activation-status.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ function output(obj) {
//
// Resolution order:
// 1. powerpages.config.json (code/SPA sites) — siteName + (optional) websiteRecordId.
// 2. .powerpages-site/website.yml (declarative "data-model" sites — standard or
// 2. .powerpages-site/website.yml (declarative sites — standard or
// enhanced data model — which have no powerpages.config.json) — `name` -> siteName,
// `id` -> websiteRecordId.
// 3. `pac pages list` — ONLY when the GUID is still unknown (e.g. a code site whose
Expand Down
18 changes: 10 additions & 8 deletions plugins/power-pages/scripts/lib/detect-project-context.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,22 @@

// Reads Power Pages project context files from the project root.
// Locates powerpages.config.json (code/SPA sites) OR a .powerpages-site/ config tree
// (declarative "data-model" sites — Power Pages design-studio sites), plus
// (declarative sites — Power Pages design-studio sites), plus
// .solution-manifest.json and .datamodel-manifest.json.
//
// NOTE on terminology: the discriminator here is the BUILD axis — code/SPA site vs
// declarative (design-studio) site — NOT the Dataverse data-model axis. A declarative
// site can be on the standard OR the enhanced data model ("EDM"); both download to a
// .powerpages-site/ tree via `pac pages download`. siteType "data-model" names that
// declarative bucket (kept for compatibility with plan-alm); a future pass may rename
// it to "declarative".
// .powerpages-site/ tree via `pac pages download`. siteType "declarative" names that
// bucket. (It was historically labeled "data-model"; that value is now the legacy
// alias. Nothing branches on the literal — it is a diagnostic label the agent reads
// and the estimator echoes — so the rename is safe, and any plan-data written before
// the rename that still carries "data-model" remains equivalent.)
//
// Site identity resolution order (first match wins):
// 1. powerpages.config.json -> siteType "code" (code/SPA sites; has siteName,
// websiteRecordId, environmentUrl)
// 2. .powerpages-site/ (.portalconfig/ + website.yml) -> siteType "data-model"
// 2. .powerpages-site/ (.portalconfig/ + website.yml) -> siteType "declarative"
// (declarative design-studio sites; standard or
// enhanced data model. website.yml carries `id` and
// `name` but no environment URL — callers re-confirm
Expand All @@ -31,7 +33,7 @@
// Output (JSON to stdout):
// {
// "projectRoot": "...",
// "siteType": "code" | "data-model",
// "siteType": "code" | "declarative", // "declarative" was formerly "data-model"
// "siteName": "...",
// "websiteRecordId": "...",
// "environmentUrl": "..." | null,
Expand Down Expand Up @@ -146,7 +148,7 @@ function detectProjectContext(options = {}) {
};
}

// 2. Declarative ("data-model") site — a Power Pages design-studio site
// 2. Declarative site (siteType "declarative", formerly "data-model") — a Power Pages design-studio site
// (`pac pages download`; standard or enhanced data model), as opposed to a
// code/SPA site. The authoritative positive marker is the
// `.powerpages-site/.portalconfig/` directory (only declarative sites have it).
Expand All @@ -167,7 +169,7 @@ function detectProjectContext(options = {}) {
}
return {
projectRoot,
siteType: 'data-model',
siteType: 'declarative',
siteName: site ? (site.name || null) : null,
websiteRecordId: site ? (site.id || null) : null,
environmentUrl: null,
Expand Down
Loading
Loading