edit-offline-profile

Utiliser lorsque l'utilisateur souhaite modifier UN aspect d'un profil hors ligne existant (portée des lignes pour une table, liste des colonnes, fréquence de synchronisation) sans réexécuter l'intégralité…

npx skills add https://github.com/microsoft/power-platform-skills --skill edit-offline-profile

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 <working_dir>/offline-profile.json or --profile-id); edits at the table-item granularity. To ADD a new table return to the owner for /add-table-to-offline-profile; deleting an entire profile is outside this helper's scope, not an automatic recovery.

Invocation context and root binding

This internal helper is always a child invocation. Before any project read or command, execute app-working-directory.md. Require the owner's absolute working_dir; --working-dir, when supplied, must identify that same native-canonical root. Missing, relative, or conflicting root context returns NEEDS_CONTEXT before project access; an inaccessible directory is BLOCKED. Never use the launch cwd or introduce another root resolver.

Receive MOBILE_APP_ORCHESTRATING=1, orchestrator, working_dir, phase, approved_scope, and supplied answers from the owner. Preserve the selected environment ID/URL/tenant, profile ID, table allowlist, item IDs, and exact scope/column/sync/name/description changes. Missing or conflicting scope returns NEEDS_CONTEXT, not another environment/profile/table selection. The marker is not approval: schema approval alone does not authorize profile edits, publication, deletion, or membership edits. Retain Step 3's single confirm unless supplied answers already approve that same current offline change. For --plan-only or a planning-phase handoff, return the current/proposed diff after read-only discovery and STOP before Apply, PATCH, publication, or artifact writes. A gate response cannot lift proposal-only mode.

Apply the canonical contract to every shell call and file tool, including version/auth checks, manifest/screen reads, commands copied from references, verification, recovery, and retries. Re-supply the absolute PLUGIN_ROOT and required context on each call; no prior cd, export, or shell variable persists. Use the canonical Bash guard below or its PowerShell equivalent. Replace placeholders with validated, shell-quoted invocation values; missing values return NEEDS_CONTEXT, never execute an unresolved placeholder. File tools use absolute <working_dir>/... paths; plugin reads/scripts use ${PLUGIN_ROOT}/.... Never search another app when a file is absent.

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

cd -- '<working_dir>' || { echo "BLOCKED: cannot enter working_dir" >&2; exit 1; }
if [ ! -f power.config.json ] || [ ! -f app.config.js ]; then
  echo "BLOCKED: working_dir is not an initialized app" >&2
  exit 1
fi

Read <working_dir>/power.config.json and require a nonempty environmentId matching the owner's selected environment. Reuse matching complete environment context, or perform this non-persisting lookup from the bound root:

cd -- '<working_dir>' || { echo "BLOCKED: cannot enter working_dir" >&2; exit 1; }
environment_id=$(node -p "require('./power.config.json').environmentId || ''") || {
  echo "BLOCKED: unreadable power.config.json" >&2; exit 1;
}
if [ -z "$environment_id" ] || [ "$environment_id" != "<selected-environment-id>" ]; then
  echo "NEEDS_CONTEXT: selected environment does not match working_dir" >&2
  exit 1
fi
node "${PLUGIN_ROOT}/scripts/resolve-environment.js" "$environment_id" --no-cache --require-tenant

Require the returned environment ID, HTTPS URL, and tenant to match the owner; incomplete or conflicting context returns NEEDS_CONTEXT. Never drop --no-cache --require-tenant, change configuration, or switch auth/environment to recover a failure. Use that exact <envUrl> and <tenantId> for every request.

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

SourceUsed when
$ARGUMENTS --profile-id <guid>Explicit selection matching the owner's profile context
<working_dir>/offline-profile.json top-level profileIdDefault for /setup-offline-profile-created projects, matching the owner's profile context
OtherwiseReturn NEEDS_CONTEXT to the owner to select the intended profile; never pick another profile silently

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

Verify the selected live profile belongs to the selected environment. A conflicting snapshot/argument returns NEEDS_CONTEXT; a 404 or permission failure is BLOCKED, not permission to discover a substitute. Resolve each <itemId> only within this profile and verify its table matches the exact requested logical name.

<working_dir>/power.config.json is intentionally NOT consulted for the profile ID. That file is owned by pa app init. The local profile ID lives in <working_dir>/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

Restrict the picker and explicit flags to the owner's exact current scope. --columns reset reads the selected table from <working_dir>/.datamodel-manifest.json or <working_dir>/docs/plan-artifacts/.datamodel-manifest.json and greps only absolute <working_dir>/app/ and <working_dir>/src/ paths. Keep the chosen absolute manifest path for the whole invocation; no other-app fallback. Changing the table, profile, or operation requires returning NEEDS_CONTEXT to the owner, not expanding an existing approval.

Step 3 — Show current vs proposed (single gate)

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

cd -- '<working_dir>' || { echo "BLOCKED: cannot enter working_dir" >&2; exit 1; }
node "${PLUGIN_ROOT}/scripts/dataverse-request.js" "<envUrl>" GET \
  "mobileofflineprofileitems(<itemId>)?\$select=name,recorddistributioncriteria,recordsownedbyme,recordsownedbymyteam,recordsownedbymybusinessunit,syncintervalinminutes,selectedcolumns" \
  --tenant-id "<tenantId>"

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:

cd -- '<working_dir>' || { echo "BLOCKED: cannot enter working_dir" >&2; exit 1; }
node "${PLUGIN_ROOT}/scripts/dataverse-request.js" "<envUrl>" PATCH \
  "mobileofflineprofileitems(<itemId>)" --tenant-id "<tenantId>" \
  --body '{
    "recorddistributioncriteria": <new>,
    "recordsownedbyme": <new-bool>,
    "syncintervalinminutes": <new>,
    "selectedcolumns": "{\"Columns\":[...]}"
  }'

For profile-level edits (name / description):

cd -- '<working_dir>' || { echo "BLOCKED: cannot enter working_dir" >&2; exit 1; }
node "${PLUGIN_ROOT}/scripts/dataverse-request.js" "<envUrl>" PATCH \
  "mobileofflineprofiles(<profileId>)" --tenant-id "<tenantId>" \
  --body '{"name": "...", "description": "..."}'

Check returned HTTP statuses as well as process exit. A 403/PrivilegeCheckFailed is BLOCKED; do not change identity or profile to bypass permissions. Preserve every field and table outside the approved delta.

Step 5 — Publish

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

cd -- '<working_dir>' || { echo "BLOCKED: cannot enter working_dir" >&2; exit 1; }
node "${PLUGIN_ROOT}/scripts/dataverse-request.js" "<envUrl>" POST \
  "PublishXml" --tenant-id "<tenantId>" --body '{
    "ParameterXml": "<publish><mobileofflineprofiles><mobileofflineprofile><profileId></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 and the owner/user approves that broader publication; a profile-scoped approval does not cover it.

All linked recovery commands, re-GET verification, and retries must bind the same root and pass the same environment/tenant/profile/table/item context. Never retry on a different profile or bypass a permission failure. Confirm publication before Step 6.

If a linked recipe requires another offline helper, return the proposed change to the owner for approval first, then read the helper at its absolute ${PLUGIN_ROOT}/skills/<helper>/SKILL.md path. Forward:

Arguments: --working-dir '<working_dir>' --profile-id "<profileId>" --table "<table>" <exact-approved-change-flags>
Context: MOBILE_APP_ORCHESTRATING=1, orchestrator, working_dir, phase, approved_scope,
         selected environment ID/URL/tenant, profile ID, table allowlist, item ID,
         supplied answers, --plan-only (if present)

The recipient must enforce the same canonical root contract. Missing context returns NEEDS_CONTEXT; do not fall back to direct invocation or rediscovery.

Step 6 — Update artifacts

Re-read the changed item(s) in the same profile/environment and rewrite the matching entry in <working_dir>/offline-profile.json. When the edit changed a table's columns (--columns add:/remove:/reset), also refresh that entry's schemaColumns to the table's current full column set from the bound absolute manifest. This re-baselines the schema-reconciliation marker for the next ${PLUGIN_ROOT}/scripts/offline-profile-delta.js run; leave schemaColumns untouched for scope/sync/rename-only edits. Any delta check uses --project-root '<working_dir>' in its own guarded call. See offline-profile-reconciliation.md.

Append a one-line entry to <working_dir>/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)

Plus de skills de microsoft

oss-growth
microsoft
Persona de growth hacker OSS
agent-framework-azure-ai-py
microsoft
Créez des agents Azure AI Foundry à l’aide du SDK Python Microsoft Agent Framework (agent-framework-azure-ai). À utiliser lors de la création d’agents persistants avec AzureAIAgentsProvider, de l’utilisation d’outils hébergés (interpréteur de code, recherche de fichiers, recherche web), de l’intégration de serveurs MCP, de la gestion de fils de conversation ou de l’implémentation de réponses en streaming. Couvre les outils de fonction, les sorties structurées et les agents multi-outils.
development
airunway-aks-setup
microsoft
Configurez AI Runway sur AKS — du cluster nu au modèle en cours d'exécution. Couvre la vérification du cluster, l'installation du contrôleur, l'évaluation GPU, la configuration du fournisseur et le premier déploiement. QUAND : « configurer AI Runway », « intégrer un cluster AKS », « installer AI Runway », « configuration airunway », « déployer un modèle sur AKS », « inférence GPU sur AKS », « configuration KAITO sur AKS », « exécuter LLM sur AKS », « vLLM sur AKS », « configurer le service de modèles sur AKS », « contrôleur AI Runway ».
devops
appinsights-instrumentation
microsoft
Conseils pour instrumenter les applications web avec Azure Application Insights. Fournit des modèles de télémétrie, la configuration du SDK et des références de configuration. QUAND : comment instrumenter une application, SDK App Insights, modèles de télémétrie, qu'est-ce qu'App Insights, conseils sur Application Insights, exemples d'instrumentation, bonnes pratiques APM.
devops
applicationinsights-web-ts
microsoft
Instrumentez les applications navigateur/web avec le SDK JavaScript Application Insights (@microsoft/applicationinsights-web). Utilisez-le pour la surveillance des utilisateurs réels (RUM) — vues de page, clics, dépendances AJAX/fetch, exceptions, événements personnalisés et traces d’agents GenAI côté navigateur corrélées aux traces OpenTelemetry backend. Couvre le script de chargement du SDK et la configuration npm, les extensions de framework (React, React Native, Angular), Click Analytics, les initialiseurs de télémétrie et les conventions sémantiques OTel GenAI pour les spans d’agents/outils/modèles émises depuis le navigateur.
devops
azure-ai-anomalydetector-java
microsoft
Créez des applications de détection d'anomalies avec le SDK Azure AI Anomaly Detector pour Java. Utilisez-le lors de l'implémentation de la détection d'anomalies univariées/multivariées, de l'analyse de séries temporelles ou de la surveillance basée sur l'IA.
development
azure-ai-language-conversations-py
microsoft
Implémentez la compréhension du langage conversationnel (CLU) à l’aide du SDK Python azure-ai-language-conversations. Utilisez-le lorsque vous travaillez avec ConversationAnalysisClient pour analyser l’intention et les entités d’une conversation, créer des fonctionnalités de NLP ou intégrer la compréhension du langage dans des applications.
development
azure-ai-ml-py
microsoft
SDK v2 d’Azure Machine Learning pour Python. Utiliser pour les espaces de travail ML, les tâches, les modèles, les jeux de données, le calcul et les pipelines. Déclencheurs : « azure-ai-ml », « MLClient », « espace de travail », « registre de modèles », « tâches d’entraînement », « jeux de données ».
development