edit-offline-profile について
Microsoft Dataverse のオフラインプロファイルを保守する人向けのスキルです。セットアップ全体をやり直さずに、テーブル範囲、列、同期頻度、プロファイル情報を編集し、適用前に差分を表示します。
主な機能
- 01テーブルのデータ範囲編集
- 02選択列の追加・削除
- 03同期頻度の変更
- 04プロファイル名・説明の変更
- 05適用前の変更差分表示
活用シーン
- 01テーブルのオフライン範囲変更
- 02プロファイルの列リスト更新
- 03テーブルの同期間隔調整
- 04プロファイル名や説明の変更
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ microsoft/ power-platform-skills --skill edit-offline-profileインストール後、Claude Code で/edit-offline-profileを入力して読み込まれたか確認します。
詳細
共通の指示:shared-instructions.md — 最初にお読みください。
参考資料:
- dataverse-offline-api.md §4 / §7 — POST item + PATCH selectedcolumns
- offline-profile-reconciliation.md — 列を編集した後に
schemaColumnsのベースラインを更新する方法
オフラインプロファイルを編集する
既存のプロファイルの一部を再実行します。1 つのテーブルの行スコープの変更、列リストの更新、同期頻度の調整、プロファイル名の変更ができます。1 行だけ変更するために、/setup-offline-profile ウィザード全体を進める認知的負荷を避けられます。
対象:既存のプロファイル(<working_dir>/offline-profile.json または
--profile-id から読み込みます)。編集の粒度はテーブル項目です。新しいテーブルを追加する場合は、所有者に戻って
/add-table-to-offline-profile を実行してください。プロファイル全体の削除はこのヘルパーの対象外であり、自動的な復旧処理でもありません。
呼び出しコンテキストとルートのバインド
この内部ヘルパーは常に子呼び出しです。プロジェクトの読み取りや
コマンドの実行に先立ち、app-working-directory.md を実行してください。
所有者の絶対パス working_dir が必要です。--working-dir が指定された場合は、
同じネイティブ形式の正規ルートを示している必要があります。ルートコンテキストがない、相対パスである、または競合している場合は、プロジェクトにアクセスする前に NEEDS_CONTEXT を返します。ディレクトリにアクセスできない場合は
BLOCKED です。起動時の cwd を使ったり、別のルート解決方法を導入したりしないでください。
所有者から MOBILE_APP_ORCHESTRATING=1、orchestrator、working_dir、phase、
approved_scope、および提供された回答を受け取ります。選択された
環境 ID/URL/テナント、プロファイル ID、テーブルの許可リスト、項目 ID、およびスコープ/列/同期/名前/説明に関する変更内容を正確に維持してください。スコープが欠落または競合している場合は、別の環境/プロファイル/テーブルを選択せず、NEEDS_CONTEXT を返します。このマーカーは承認を意味しません。スキーマの承認だけでは、プロファイルの編集、公開、削除、メンバーシップの編集は許可されません。提供された回答が同じ現在のオフライン変更をすでに承認している場合を除き、ステップ 3 の確認を 1 回行ってください。
--plan-only または計画フェーズの引き継ぎの場合は、読み取り専用の調査後に現在と提案の差分を返し、適用、PATCH、公開、成果物の書き込みを行う前に停止してください。ゲートの応答によって提案のみのモードを解除することはできません。
バージョン/認証チェック、マニフェスト/画面の読み取り、参考資料からコピーしたコマンド、検証、復旧、再試行を含め、すべてのシェル呼び出しとファイルツールに標準の契約を適用してください。各呼び出しで絶対パスの PLUGIN_ROOT と必要なコンテキストを再指定してください。以前の cd、export、シェル変数は引き継がれません。以下の標準 Bash ガード、またはその PowerShell 版を使ってください。プレースホルダーは検証済みのシェルクォート済み呼び出し値に置き換えてください。値が欠落している場合は、未解決のプレースホルダーを実行せず、NEEDS_CONTEXT を返します。
ファイルツールでは絶対パス <working_dir>/... を使用し、プラグインの読み取り/スクリプトでは ${PLUGIN_ROOT}/... を使用してください。ファイルが見つからない場合、別のアプリを検索しないでください。
ワークフロー
- プロジェクトを確認してプロファイルを特定 → 2. 対象を解決(どのテーブル/何を変更するか) → 3. 現在と提案を提示 → 1 回だけ確認 → 4. PATCH → 5. 公開 → 6. 成果物を更新 → 7. 要約
ステップ 1 — プロジェクトを確認してプロファイルを特定する
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
<working_dir>/power.config.json を読み込み、所有者が選択した環境と一致する、空でない environmentId を必須とします。一致する完全な環境コンテキストを再利用するか、バインドされたルートから次の永続化しない検索を実行します。
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
返された環境 ID、HTTPS URL、テナントが所有者の情報と一致することを必須とします。コンテキストが不完全または競合している場合は NEEDS_CONTEXT を返します。失敗から復旧するために --no-cache --require-tenant を削除したり、設定を変更したり、認証/環境を切り替えたりしてはいけません。すべてのリクエストで、同一の <envUrl> と <tenantId> を使用します。
プロファイル ID の解決(/assign-offline-profile のステップ 1 と同じ優先順位):
| ソース | 使用条件 |
|---|---|
$ARGUMENTS --profile-id <guid> | 所有者のプロファイルコンテキストと一致する明示的な選択 |
<working_dir>/offline-profile.json のトップレベル profileId | /setup-offline-profile で作成されたプロジェクトのデフォルト。所有者のプロファイルコンテキストと一致する場合 |
| それ以外 | 所有者に対象のプロファイルを選択するよう求めて NEEDS_CONTEXT を返します。別のプロファイルを黙って選択してはいけません |
プロファイルが見つからない場合は停止します:「最初に /setup-offline-profile を実行してください。」
選択したライブプロファイルが、選択した環境に属していることを確認します。スナップショット/引数が競合する場合は NEEDS_CONTEXT を返します。404 または権限エラーは BLOCKED であり、代替のプロファイルを検索する理由にはなりません。各 <itemId> はこのプロファイル内でのみ解決し、そのテーブルが要求された論理名と完全に一致することを確認します。
プロファイル ID の取得元として、
<working_dir>/power.config.jsonは意図的に参照しません。 このファイルはpa app initが管理します。ローカルのプロファイル ID は<working_dir>/offline-profile.jsonにのみ保存されています。
ステップ 2 — 対象を解決する(編集内容)
$ARGUMENTS を解析します。
| フラグのパターン | 効果 |
|---|---|
--rename <new-name> | プロファイルの name を更新します |
--describe <text> | プロファイルの description を更新します |
--table <logical-name> --scope <0|1|2> | 1 つのテーブルの recorddistributioncriteria を変更します。scope=2 の場合は、--me、--team、--bu と組み合わせてサブフラグを設定します。 |
--table <logical-name> --sync <minutes> | 1 つのテーブルの syncintervalinminutes を変更します(範囲:5~1440)。 |
--table <logical-name> --columns add:col1,col2 remove:col3 | selectedcolumns から論理名を追加または削除します。カンマ区切りで、add と remove はどちらも省略可能です。 |
--table <logical-name> --columns reset | 選択列を、常時含める列 + マニフェストの参照列 + 画面の grep で見つかった列の和集合に置き換えます(このテーブルについてアーキテクトのステップ 6 の和集合を再実行します)。 |
フラグが指定されていない場合は、対話型ピッカーを表示します。AskUserQuestion で、可能性の高い編集項目を最大 4 つ提示します。
- 「プロファイル名を変更」
- 「テーブルのスコープを変更」→ 次のメッセージでテーブルを尋ねる
- 「テーブルの同期頻度を変更」→ 次のメッセージでテーブルと値を尋ねる
- 「テーブルの列リストを編集」→ 次のメッセージでテーブルと追加/削除する列を尋ねる
ピッカーと明示的なフラグは、所有者の現在の正確なスコープに限定します。
--columns reset は、選択したテーブルを
<working_dir>/.datamodel-manifest.json または
<working_dir>/docs/plan-artifacts/.datamodel-manifest.json から読み込み、絶対パスの <working_dir>/app/ と <working_dir>/src/ のみを grep します。呼び出し全体を通して、選択した絶対パスのマニフェストを使用します。他のアプリへのフォールバックは禁止です。
テーブル、プロファイル、または操作を変更する場合は、既存の承認を拡張せず、所有者に NEEDS_CONTEXT を返す必要があります。
ステップ 3 — 現在の状態と変更案を提示する(単一の承認ゲート)
編集対象のテーブルについて、Dataverse から現在の項目状態を GET します。
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>"
現在の状態と変更案の差分を表示します。
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:「この変更を適用しますか?[適用/キャンセル]」
「適用」の場合は続行します。「キャンセル」の場合は停止します。
ステップ 4 — PATCH
変更されたフィールドのみを含む PATCH 本文を作成します。
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\":[...]}"
}'
プロファイルレベルの編集(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": "..."}'
プロセスの終了コードだけでなく、返された HTTP ステータスも確認します。403/PrivilegeCheckFailed は BLOCKED とします。権限を回避するために ID またはプロファイルを変更してはいけません。承認された変更範囲外のすべてのフィールドとテーブルを保持します。
ステップ 5 — 公開
shared/references/dataverse-offline-api.md §9 の対象を絞った PublishXml レシピを使用します。
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>"
}'
このプロファイルのみを公開し、組織全体のカスタマイズは公開しません。従来の PublishAllXml が共有環境で引き起こしていた、429 レート制限の集中発生を回避します。
400 / 0x80071141「循環参照」が発生した場合は、
/setup-offline-profile のステップ 8 と同じ方法で処理します(循環経路を解析し、ユーザーに関連付けを 1 つ削除するよう促してから再試行します)。PublishXml が循環参照以外の予期しないエラーを返した場合かつ、所有者/ユーザーがより広範な公開を承認した場合に限り、PublishAllXml にフォールバックします。プロファイルに限定した承認では、より広範な公開は許可されません。
関連するすべての復旧コマンド、再 GET による検証、および再試行では、同じルートに紐付け、同じ環境/テナント/プロファイル/テーブル/項目のコンテキストを渡す必要があります。別のプロファイルで再試行したり、権限エラーを回避したりしないでください。ステップ 6 の前に公開を確認します。
関連するレシピで別のオフラインヘルパーが必要な場合は、まず変更案を所有者に提出して承認を受けてから、絶対パス ${PLUGIN_ROOT}/skills/<helper>/SKILL.md にあるヘルパーを読み込みます。次の内容を渡します。
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)
受け取り側は、同じ正規ルートの契約を適用する必要があります。コンテキストが不足している場合は NEEDS_CONTEXT を返します。直接呼び出したり、再探索したりする方法にフォールバックしないでください。
ステップ 6 — 成果物を更新
同じプロファイル/環境で変更した項目を再読み込みし、<working_dir>/offline-profile.json の該当するエントリを書き換えます。編集によってテーブルの列(--columns add:/remove:/reset)が変更された場合は、紐付けられた絶対パスのマニフェストから取得した、テーブルの現在の全列セットでそのエントリの schemaColumns も更新します。これにより、次回の ${PLUGIN_ROOT}/scripts/offline-profile-delta.js 実行に備えてスキーマ調整マーカーを再ベースライン化します。スコープ/同期/名前変更のみの編集では、schemaColumns を変更しないでください。差分チェックを行う場合は、独立したガード付き呼び出しで --project-root '<working_dir>' を使用します。offline-profile-reconciliation.md を参照してください。
<working_dir>/memory-bank.md の ## Offline profile ブロックに、次の形式で 1 行追加します。
edits:
- { at: 2026-05-19T..., field: 'chnl_storevisit.syncintervalinminutes', from: 5, to: 10 }
ステップ 7 — 要約
✓ Edited profile.
Field : chnl_storevisit.syncintervalinminutes
From : 5 min
To : 10 min
Published: 2026-05-19T...
offline-profile.json + memory-bank.md updated.
ステータスコード(最終行)
DONE— 変更を適用して公開しましたDONE_WITH_CONCERNS: <list>— 注意事項はありますが、変更を適用しました(公開がタイムアウトした後に成功した場合など)NEEDS_CONTEXT: <missing>— 対象のテーブルまたはプロファイルを特定できませんでしたBLOCKED: <reason>— 認証または PATCH に失敗しました
このスキルで行わないこと
- プロファイルに新しいテーブルを追加する →
/add-table-to-offline-profileを使用します - 新しい関連付け(リレーションシップの組み込み)を追加する → v0.2 の
selectedrelationshipsschema作業が完了するまで対応できません。当面は Maker ポータルを使用してください - プロファイル全体を削除する → 手動で
DELETE /mobileofflineprofiles(<id>)を実行します(項目と関連付けも連鎖削除されます)。dataverse-offline-api.md §11 を参照してください - 環境間でプロファイルを移行する →
CloneMobileOfflineProfileアクションを使用します(v0.5 の作業)