Labsco
microsoft logo

edit-offline-profile

โœ“ Officialโ˜… 413

by microsoft ยท part of microsoft/power-platform-skills

Use when the user wants to change ONE aspect of an existing offline profile (row scope for a table, column list, sync frequency) without re-running the full /setup-offline-profile wizard. Mirrors the /edit-app gated edit pattern.

๐Ÿงฉ One of 7 skills in the microsoft/power-platform-skills package โ€” works on its own, and pairs well with its siblings.

This is the playbook your agent receives when the skill activates โ€” you don't need to read it to use the skill, but it's here to audit before installing.

Shared instructions: shared-instructions.md โ€” read first.

References:

Edit Offline Profile

Re-run a single piece of an existing profile โ€” change one table's row scope, update the column list, adjust sync frequency, or rename the profile. Avoids the cognitive cost of walking the full /setup-offline-profile wizard for a one-line change.

Scope: existing profile (read from offline-profile.json or --profile-id); edits at the table-item granularity. To ADD a new table see /add-table-to-offline-profile; to delete the entire profile see dataverse-offline-api.md ยง11.

Workflow

  1. Verify project + locate profile โ†’ 2. Resolve target (which table / what to change) โ†’ 3. Show current vs proposed โ†’ Single confirm โ†’ 4. PATCH โ†’ 5. Publish โ†’ 6. Update artifacts โ†’ 7. Summary

Step 1 โ€” Verify project + locate profile

test -f power.config.json
node "${PLUGIN_ROOT}/scripts/resolve-environment.js" "$(node -e \"console.log(require('./power.config.json').environmentId)\")"

Profile ID resolution (same priority as /assign-offline-profile Step 1):

SourceUsed when
$ARGUMENTS --profile-id <guid>Explicit override
offline-profile.json top-level profileId in cwdDefault for /setup-offline-profile-created projects
OtherwiseAskUserQuestion with list from GET /mobileofflineprofiles

STOP if no profile found: "Run /setup-offline-profile first."

power.config.json is intentionally NOT consulted here. That file is owned by npx power-apps init. The profile ID lives in offline-profile.json only.

Step 2 โ€” Resolve target (what to edit)

Parse $ARGUMENTS:

Flag patternEffect
--rename <new-name>Update profile name
--describe <text>Update profile description
--table <logical-name> --scope <0|1|2>Change one table's recorddistributioncriteria. Combine with --me, --team, --bu to set sub-flags when scope=2.
--table <logical-name> --sync <minutes>Change one table's syncintervalinminutes (range 5โ€“1440)
--table <logical-name> --columns add:col1,col2 remove:col3Add or remove logical names from selectedcolumns. Comma-separated, both add/remove optional.
--table <logical-name> --columns resetReplace selectedcolumns with union of always-include + manifest lookups + screen-grep'd (re-runs the architect's Step 6 union for this table)

If no flags โ†’ interactive picker. AskUserQuestion with up-to-4 most likely edits:

  • "Rename profile"
  • "Change a table's scope" โ†’ next message asks which table
  • "Change a table's sync frequency" โ†’ next message asks which table + value
  • "Edit a table's column list" โ†’ next message asks which table + add/remove

Step 3 โ€” Show current vs proposed (single gate)

GET the current item state from Dataverse for any tables being edited:

node "${PLUGIN_ROOT}/scripts/dataverse-request.js" <envUrl> GET \
  "mobileofflineprofileitems(<itemId>)?\$select=name,recorddistributioncriteria,recordsownedbyme,recordsownedbymyteam,recordsownedbymybusinessunit,syncintervalinminutes,selectedcolumns"

Render a current/proposed diff:

Profile  : <name> (<id>)
Editing  : <table-logical-name> item

                Current     โ†’    Proposed
Scope         : Org+me     โ†’    All records
Sync (min)    : 10         โ†’    30
Columns       : 14         โ†’    16  (add: chnl_notes, chnl_actual_visit_date)

AskUserQuestion: "Apply this change? [Apply / Cancel]"

If Apply โ†’ continue. If Cancel โ†’ STOP.

Step 4 โ€” PATCH

Build the PATCH body with only the fields that changed:

node "${PLUGIN_ROOT}/scripts/dataverse-request.js" <envUrl> PATCH \
  "mobileofflineprofileitems(<itemId>)" \
  --body '{
    "recorddistributioncriteria": <new>,
    "recordsownedbyme": <new-bool>,
    "syncintervalinminutes": <new>,
    "selectedcolumns": "{\"Columns\":[...]}"
  }'

For profile-level edits (name / description):

node "${PLUGIN_ROOT}/scripts/dataverse-request.js" <envUrl> PATCH \
  "mobileofflineprofiles(<profileId>)" \
  --body '{"name": "...", "description": "..."}'

Step 5 โ€” Publish

Use the targeted PublishXml recipe from shared/references/dataverse-offline-api.md ยง9:

node "${PLUGIN_ROOT}/scripts/dataverse-request.js" <envUrl> POST \
  "PublishXml" --body '{
    "ParameterXml": "<publish><mobileofflineprofiles><mobileofflineprofile>'"$PROFILE_ID"'</mobileofflineprofile></mobileofflineprofiles></publish>"
  }'

Publishes only this profile, not the entire org's customizations. Avoids the 429 rate-limit storms on shared envs that the legacy PublishAllXml triggered.

On 400 / 0x80071141 "circular relationship" โ€” same handling as /setup-offline-profile Step 8 (parse cycle path, prompt user to drop one association, retry). Fallback to PublishAllXml only if PublishXml returns an unexpected error other than the cycle case.

Step 6 โ€” Update artifacts

Re-read the changed item(s) and rewrite the matching entry in offline-profile.json. When the edit changed a table's columns (--columns add:/remove:/reset), also refresh that table entry's schemaColumns to the table's current full column set from .datamodel-manifest.json (root or docs/plan-artifacts/). This re-baselines the schema-reconciliation marker so a delta that was just reconciled clears on the next scripts/offline-profile-delta.js run; leave schemaColumns untouched for scope/sync/rename-only edits. See offline-profile-reconciliation.md.

Append a one-line entry to memory-bank.md ## Offline profile block:

edits:
  - { at: 2026-05-19T..., field: 'chnl_storevisit.syncintervalinminutes', from: 5, to: 10 }

Step 7 โ€” Summary

โœ“ Edited profile.

  Field : chnl_storevisit.syncintervalinminutes
  From  : 5 min
  To    : 10 min
  Published: 2026-05-19T...

offline-profile.json + memory-bank.md updated.

Status code (final line)

  • DONE โ€” change applied and published
  • DONE_WITH_CONCERNS: <list> โ€” change applied but with caveats (publish timeout-then-success, etc.)
  • NEEDS_CONTEXT: <missing> โ€” couldn't resolve target table or profile
  • BLOCKED: <reason> โ€” auth or PATCH failure

What this skill does NOT do

  • Add a NEW table to the profile โ†’ use /add-table-to-offline-profile
  • Add a new association (relationship inclusion) โ†’ blocked on v0.2 selectedrelationshipsschema work; use maker portal in the meantime
  • Delete the whole profile โ†’ manual DELETE /mobileofflineprofiles(<id>) (cascade-deletes items + associations); see dataverse-offline-api.md ยง11
  • Migrate the profile between environments โ†’ use CloneMobileOfflineProfile action (v0.5 work)