app-builder について
app-builder は、自然言語の要件からモデル駆動型アプリをデプロイするスキルです。レビュー可能な JSON App Spec を使い、データモデル、ビュー、フォーム、ページ、ナビゲーションを構築・変更します。同じ仕様を新規作成と編集の両方に使えます。
主な機能
- 01レビュー可能な JSON App Spec の作成
- 02テーブル、リレーション、ビュー、フォームの構築
- 03概要ページとダッシュボードページの生成
- 04アプリモジュールとサイトマップの作成
- 05デプロイ済みアプリの仕様への変換
- 06仕様の検証とビルド計画の確認
活用シーン
- 01自然言語の要件からアプリを計画
- 02データテーブルとフォームを備えたアプリの構築
- 03仕様を使ったデプロイ済みアプリの変更
- 04構築前に検査結果とドライラン計画を確認
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ microsoft/ power-platform-skills --skill app-builderインストール後、Claude Code で/app-builderを入力して読み込まれたか確認します。
詳細
翻訳後に原文が更新されています。最新の内容は原文をご確認ください。
プラグインの確認:
node "${PLUGIN_ROOT}/scripts/check-version.js"を実行します。メッセージが出力された場合は、先にユーザーに表示してから続行してください。
app-builder — インテントからモデル駆動型アプリへ
自然言語のインテントから、デプロイ済みのモデル駆動型アプリを作成します。ユーザーと確認を重ねながら、レビュー可能な App Spec
(JSON)を作成し、決定論的なエンジン(同梱の cds-maker-sdk)でビルドします。テーブル/列/リレーションシップ、サンプルデータ、ビュー、Choice 列のグラフ、サブグリッドを含むアダプティブフォーム、概要/ダッシュボード画面用の 生成ページ、アプリモジュールとサイトマップを作成します。
作成と編集には同じ仕様を使用します。デプロイ済みのアプリを仕様にダウンロードして変更し、ビルドを再実行できます(冪等です)。
重要 — 対話形式のフローはこの会話(メインループ)で実行してください
作成に関する質問とビルドの説明は、メインの会話で必ず自分で行ってください。対話形式のステップをサブエージェント(
Task)に委任しないでください。サブエージェントはヘッドレスです。サブエージェント内からは
AskUserQuestionとプランモードをユーザーに届けられません(最終メッセージしか出力できません)。このスキルの要点は、複数ターンにわたって提案し、確認を得ることです。そのため、AskUserQuestion、EnterPlanMode、ビルド状況のリアルタイム表示は、すべてメインループから行う必要があります。
重要 — ユーザーに表示されるのはあなたのチャットメッセージであり、ツールの出力ではありません
シェル/ツールの出力(
preview-app.jsの実行結果、ドライランの計画、lint の結果)は、UI ではデフォルトで折りたたまれています。ツールパネルを手動で展開しない限り、ユーザーには表示されません。そのため、コマンドを実行するだけではユーザーに見せたことにはなりません。ユーザーが読んだり、レビューしたり、承認したりする必要のある成果物、つまりアプリ全体のプレビュー用ワイヤーフレーム、ドライランのビルド計画、およびビルドを妨げるlint の指摘事項は、すべてフェンス付きの```コードブロックに入れて、チャットの返信にそのまま転載する必要があります。プレビューの内容を折りたたまれたパネルに埋もれさせたまま、「プレビューは問題なさそうです」と言ってはいけません。メッセージに貼り付けてください。「ワイヤーフレームが見えない」という問題の最大の原因は、プレビューを実行したものの、出力が隠れたままになっていることです。
機能 — 充実したツールボックス(要件に最適なものを選択)
単一画面用のツールではなく、包括的なモデル駆動型アプリビルダーです。以下のすべてを、1 つの App Spec と 1 回のビルドで提供します。ユーザーの要件に最適なものを選び、実用的で本番環境に対応できるアプリを作成してください。テーブルの一覧だけで済ませるような作り込み不足も、求められていない画面を作り込む過剰な対応も避けてください。
- データモデル — テーブル(カスタムテーブルにはそれぞれ、デフォルトで意味のある Fluent スタイルの SVG テーブルアイコンを付けます。グリフが何を描くのかを言葉で提案してください(Fluent トークン名は使わないでください)。SVG を描く前に
iconDescriptionとして記録してください。詳細はreferences/authoring-flow.md→ テーブルアイコン を参照)、列(すべての型)、リレーションシップ(1:N/N:N と中間テーブル)、サンプルデータ - レコード UI — フォーム(サブグリッド、クイック作成/クイック ビュー)、ビュー(充実した既定列を使用)、グラフ
- カスタム グリッド レンダリング(プレビュー) —
entities[].columns[].visualizationを使うと、列をプレーンテキストではなくRadialDial、LineChart、HeatMap、StarRatingとして、その列を表示するすべてのグリッドとビューでレンダリングできます。列が、正確に読み取る値ではなく、ユーザーがひと目で把握する大きさ(スコア、稼働率、評価、優先度など)を表す場合に活用してください。仕様を一行追加するだけで、一覧をひと目で把握しやすくなります。列ごとに設定するため、各ビューではなく列に一度だけ設定します。プレビュー: プロビジョニングされていない環境ではビルドがこの機能をスキップし、ほかのものはすべてデプロイされるため、いつでも安全に含められます。 - アクション — モダンなコマンドバーのボタン(フライアウト/分割メニューを含む)、Web リソース(フォーム JS/HTML/CSS)。JS を記述する際は、正常にデプロイされたのに何も起こらなかったボタンから学んだ、次の 2 つのルールを守ってください。コマンドハンドラーにはレコードが渡されるため(
function doThing(primaryControl))、ビルドがパラメーターを渡せるよう、このシグネチャで記述します。また、100000003のような Choice 値をハードコードしないでください。値は発行者ごとに割り当てられます。getOptions()でラベルから解決してください(references/app-spec-schema-advanced.md→ webResources を参照)。なお、コマンドと Web リソースの編集内容は再ビルド時に再デプロイされません。フェーズでは既存のものが再利用されるため、ボタンやスクリプトを変更する場合は、まず削除してください。 - コードを使わないフォームロジック —
businessRules[]:レコードの条件に基づく表示/非表示、ロック/ロック解除、必須設定、値の設定。要件がフィールドレベルで宣言的な場合は、フォーム JS より先にビジネスルールを活用してください。メーカーで確認でき、ソリューションのエクスポート後も保持され、Web リソースも不要です。実際の API 呼び出し、レコードをまたぐ処理、またはサポートされる 4 つのアクションを超えるロジックが必要な場合は、フォーム JS を使用してください。 - ガイド付きプロセス —
businessProcessFlows[]:レコード上部に表示される段階的なバー(順序付きのステージ。それぞれに、そのテーブルの列に関連付けられたステップがあります。すべてのステップでfieldを指定する必要があります。指定しないとプラットフォームに拒否されるため、手動確認には Boolean フラグを使用してください)。ユーザーが「トリアージ → 調査 → 解決」「リード → 適格性確認 → 成約」のように、作業がフェーズを移行すると説明した場合に活用してください。Active(既定値)で作成してください。そうしないとステージバーは表示されません。フローを実行できるユーザーはsecurityRoles: { "personas": [...] }で指定します(Active フローのみ)。v1 は単一エンティティで直線的な構成です。エンティティをまたぐステージ、分岐、ステージアクションは仕様ゲートで拒否されるため、仕様に記述するのではなく、そうした要件には Maker を提案してください。 - 画面 — 生成ページ(モダンなダッシュボード/概要/分析/ランディング。既定)、クラシック ダッシュボード(オプトイン)、外部 URL
- アプリシェル — アプリモジュールとサイトマップ(サブエリアごとのアイコンを含む)。ユーザーがクラシックを希望していない限り、
app.newLook: trueを指定してモダンシェルを有効にしてください。これはオプトインでベストエフォートのため、設定のないテナントでもアプリは動作します。app.headerNavigationRefreshはWave 2 ヘッダー/ナビゲーションの更新を制御します。これは独立した別の設定で、プラットフォームの既定値はオンです。ユーザーが明示的にクラシック ヘッダーを希望する場合に限り、falseに設定してください。 - セキュリティとアクセス — ペルソナごとにセキュリティロールを 1 つ設定し、そのペルソナのジョブに必要なエンティティアクセスをロールにまとめます。これにより、管理者以外のユーザーもアプリを開けるようになります。
- AI ファースト機能(管理者による有効化が必要)— フォーム入力アシスト、自然言語によるグリッド/ビュー検索、自然言語グラフ/AI データ可視化、M365 Copilot(オプトイン)、テーブルごとの Copilot 行要約(インサイトカード。候補に適したテーブルで自動選択し、プロンプトを調整)
依頼を完全に満たす最小限の仕様を作成し、ユーザーが後から調整できるようにします。以下のGenpage 優先ポリシーは、レコードとダッシュボードを区別するルールです。すべてのフィールドについては、
references/app-spec-schema.mdを参照してください。
Genpage 優先ポリシー(サーフェスの分類)
アプリの各サーフェスは、次の2種類のいずれかです。アプリのサーフェスをすべて列挙して分類してください。その場しのぎでページごとに判断しないでください。
- レコードサーフェス(テーブルの行の作成/読み取り/更新/一覧表示)→ モデル駆動型フォームとビュー。
- それ以外すべて — 概要/ランディング、ダッシュボード、KPI、分析、ガイド付きフローやウィザードフロー、複合画面や比較画面 → ジェネレーティブページ(
pages[])。従来型のダッシュボードではありません。
ルール:
- アプリの用途に概要、キュー、分析、ガイド付きフローが含まれているのに、ページを提案していない場合は、サーフェスを見落としています。本当にレコードの CRUD のみを行うアプリの場合は、ページを黙って省略せず、その旨を明示してください。
- 従来型の
dashboards[]を出力するのは、明示的に依頼された場合のみです(例:「従来型のダッシュボードを使う」)。 - ジェネレーティブページは、フェーズ 1 では設計意図(
source: { kind: "intent" }、schemaVersion: 2)として作成します。その.tsxは、計画の承認後、データの事前ビルドによってテーブルが作成され、genpage.js typesがRuntimeTypes.tsを生成できるようになった後のフェーズ 1.5 — ページの生成で記述します。references/authoring-flow.md→ Pages を参照してください。 - ビルドの
pagesフェーズは SDK を通じて各ページを書き込み、ページをサイトマップに直接追加することはありません — SDK が唯一のサイトマップ書き込み元です。そのため、ページのナビゲーション項目は、appShell内のpageサブエリア(ページのkeyを参照)から生成されます。references/app-spec-schema.md→pages[]を参照してください。 pages[]内のすべてのページをサイトマップに配置する必要があります — サイトマップにないページは検証で拒否されます。呼び出し元から渡される ID を受け取る「詳細」ページは通常のサイトマップページであり、pageInput?.data?.<field>から入力を読み取ります。ナビゲーション専用(ヘッドレス)ページはサポートされていません。pageInputを宣言するページは、必ずdirectEntryも宣言する必要があります。 すべてのページがサイトマップに配置されるため、詳細ページも、ユーザーがクリックして到達する入力なしの状態で、アプリのナビゲーションから直接開けます。その場合の動作を指定してください。{ "behavior": "selector" }は、ピッカーを表示してからレコードを表示します。{ "behavior": "emptyState" }は、状況を説明し、問題のある表示をせずに何も描画しません。テーブルを参照できる場合は、より便利なランディングとなるselectorを優先してください。pageInput.dataの各キーは、いずれかのページのnavigatesTo[].dataによっても生成される必要があります。そうしないと、生成されたページは一度も設定されないキーを読み取ることになります。- ページ ID を決める3つの基準(ビルド、ダウンロード、検証すべてで適用):(1) IDENTITY — 永続的な
<app>_pagemanifest(key → pageId)。再ビルドでは、ダウンロードした仕様に含まれるpages[].pageIdが優先されます。(2) EXISTENCE — SDK を通じて読み取る環境全体のページ一覧。ドラフトも含みます(クラッシュに安全であり、作成か再利用かを判断します)。(3) MEMBERSHIP — アプリのサイトマップに含まれるGenPageIdの集合(配置、ダウンロード時の列挙、検証時の網羅性に使用)。照合はすべて ID で行い、表示名では決して行いません。 - 複数ページ間のナビゲーションでは、安定した
pages[].keyを使ったPAGEREF_<key>をpageIdのプレースホルダーとして使用します。ビルド時に、実際のページ GUID へ変換するため、実行単位のステージングコピー内で解決されます(正規の.tsxは変更されません)。その後、すべてのナビゲーションエッジがデプロイ済みページのGenPageIdに解決されることを検証します。
ワークフロー
フェーズ 0 — 作業ディレクトリ
$ARGUMENTSから短いケバブケースのスラッグを導出します(例:「Project Tracker」→project-tracker)。- ディレクトリを作成し(bash/PowerShell では
mkdir -p <slug>、-pがなく既存ディレクトリがあるとエラーになる cmd ではmkdir <slug>)、絶対パスを解決します。このディレクトリにapp-spec.json、model-app-plan.md、workflow-log.mdを格納します。
フェーズ 1 — アプリ仕様の作成(対話型、メインループ)
references/authoring-flow.md の手順に従い、すべてのプロンプトを AskUserQuestion を使って自分で実行してください。概要は次のとおりです。
無人実行(Copilot の自動運転/自動化)
最初の作成に関する質問の前に、対話モードを一度決定してください。
node "${PLUGIN_ROOT}/scripts/resolve-interaction-mode.js" [--non-interactive]
POWER_PLATFORM_SKILLS_NONINTERACTIVE=1/true(または同等の --non-interactive 呼び出し)は、プロンプトを待つユーザーがいないことを意味します。このモードでは、次のようにします。
AskUserQuestion、EnterPlanMode、ExitPlanModeを呼び出さないでください。- 明示された要件と提供済みの既存仕様を正式な情報源として使用し、依頼で非破壊的な選択肢が未指定の場合に限り、文書化されたデフォルトを使用してください。
- スキップした各確認事項を、
workflow-log.mdにUnattended default: <question> → <answer> (<reason>)の形式で記録してください。 - 完了した lint、プレビュー、レンダリング済みの設計ドキュメント、ビルドのドライランを承認済みプランとして扱い、通常の承認済みフローを続行してください。
- 環境、アプリの識別情報、または破壊的な構造編集が曖昧な場合は、推測せずに停止してください。
対話を抑制しても、破壊的な作業が許可されるわけではありません。既存アプリを無人で適用する場合でも、通常のビルドで必要となる箇所では --allow-destructive が引き続き必要です。POWER_PLATFORM_SKILLS_NONINTERACTIVE が抑制するのはプロンプトのみです。
決定したモードをサブプロセスにも引き継いでください。無人モードの場合は、すべての build-model-app.js 呼び出し(ドライラン、データの事前ビルド、復旧の再実行、完全適用)に --non-interactive を追加してください。破壊的な操作の許可が別途与えられていない限り、--allow-destructive は追加しないでください。
- 前提条件 —
node --version、pac help(> 2.10.0。プラグインの最小バージョンです)。 - 環境(PAC) —
pac auth list。プロファイルが1つだけ、またはアクティブなプロファイルがある場合は、確認のために伝えるだけにして、質問しないでください。複数あり、アクティブなものがない場合は、どれを使うか尋ねてください。プロファイルがない場合は、ユーザーにpac auth createを実行するよう依頼します。組織の URL を取得します(pac org who)。 - 既存の項目を検出 —
scripts/list-tables.js --env <envUrl> --search … --exactとscripts/apps.js list --env <envUrl>(<envUrl>は手順2で取得した組織の URL)を使って、すでに存在するテーブル/アプリを確認し、それらを活用して設計します。--exactを使うと、検索語が論理名と一致するテーブルだけが残り、該当するものがない検索語はmissingに一覧表示されます。読み取りに失敗した場合(終了コード1)は、その旨を報告して手順を終了します。「何も存在しない」と判断してはいけません。 - 段階的な作成 — 正確な形式に従って作成できるよう、まず App Spec の形式を読みます(一度だけ実施し、スクリプトをあれこれ調べ回らないでください)。
references/app-spec-schema.mdと、詳しいサンプルであるsamples/app-spec.support-desk.jsonを読みます。このドキュメントには、アプリに常に含まれるすべての項目が記載されています。設計で条件付き機能が必要になった場合は、references/app-spec-schema-advanced.mdも読みます。対象となるのは、業務ルール、業務プロセスフロー、コマンドバーのボタン、Web リソース、グローバル選択肢、クラシックダッシュボード、roleGrants[]です。参照先の一覧表はメインのスキーマにあり、上記のツールボックスには各機能を使うタイミングが示されています。実際に使う機能の詳細だけを読み、読むのを避けるために機能を省略してはいけません。 フェーズ1は設計のみです。ここではページ.tsxを絶対に出力しないでください。各レベルを開始する前にAskUserQuestionで確認し、その後app-spec.jsonを保存します。完全なプロンプトはプレイブックを参照してください。- レベル(a0)— ペルソナと達成すべき作業(
personas[]):テーブルを提案する前に、アプリを使う人と、それぞれが何を達成する必要があるかを尋ねます。達成すべき作業が以降のすべてを決定します。作業に必要なデータがあるからテーブルが存在し、作業に必要な操作があるから画面が存在します。先にデータモデルを導き出すと、画面を確実に見落とします。権限は後で扱うため、ここでは作業内容を記録します。 - レベル(a)— データモデル:レベル(a0)で確認した作業からエンティティ/列/リレーションシップを導き出し、早期のデータモデル lint を実行します(フォームを作成する前に、リレーションシップとルックアップの衝突などを検出します)。
- 説明は作成時に含めるものであり、後から整えるものではありません。 テーブル、列、ビュー、グラフ、フォーム、ダッシュボード、業務ルールにはすべて任意の
descriptionを設定でき、アーティファクトの作成時に記述する必要があります。後から一括で追加してはいけません。名前は項目の呼び方を示し、説明は項目の目的を示します。また、アプリを作成していないエージェントが後からアプリを調べる際に読み取れる、アプリに保持される唯一の意図です。形状ではなく目的を説明してください。たとえば、「優先度列」ではなく、「重大度1~5。エスカレーションルールと SLA の計時に使用します」と記述します。 (commands[]とCustomer列にも設定できますが、SDK では書き込めないため警告が表示されます。personas[]には設定できません。その理由はスキーマのリファレンスを参照してください。) アプリ自体には2種類の説明があります。app.descriptionはタイルに表示する短いテキストで、app.aiDescriptionはオーケストレーターがアプリを選択するために読むルーティング用の説明です。対象ユーザー、対象範囲と対象外の範囲、同じテーブルを使う類似アプリとの見分け方を記述します。そのような類似アプリが存在する、または計画されている場合は、必ず記述してください。 - レベル(b)— アーティファクト+ページの意図+設計:各作業に必要なすべての画面を列挙し、上記の genpage 優先ポリシーに従って分類します。レコードの CRUD → フォーム+ビュー。それ以外(概要/ランディング、ダッシュボード、KPI、分析、ガイド付き/ウィザード形式のフロー、複合画面または比較画面)→ ページの意図(
source: { kind: "intent" })。分類を一つずつ明示してください。アプリにページが不要な場合も、黙って省略せず、不要な理由を説明します。次に、フォーム+ビュー+グラフ+サンプルデータと、任意のdesignコントラクトを作成し、jobs[].surfaces[]で各作業と画面を対応付けます。ここではページ.tsxを作成しないでください。dashboards[]は明示的に要求された場合にのみ使用します。 - レベル(c)— アクセス(
personas[].jobs[].privileges[]):ペルソナと作業はレベル(a0)で定義済みで、エンティティもすでに存在するため、各作業に必要な権限だけを追加します。ユーザーが誰かを再度尋ねないでください。ビルダーは権限をペルソナごとに1つのロールにまとめ、そのロールにアプリを付与します。そのため、アプリはシステム管理者だけでなく、そのペルソナも開けるようになります。チャットの返答では、ロールとエンティティごとのアクセス権を表にして表示してください(ユーザーは確認できないアクセスモデルを承認できません。上記の CRITICAL 注記を参照してください)。ロールを設定しない場合は、作業がpersonas[]に含まれるため、ロールを削除すると記録された作業も削除されることを伝え、記録を保持できるよう読み取り専用の権限を提案してください。(列レベルのセキュリティとアクセスチームはまだサポートされていません。注意事項と制限を参照してください。) - アプリ全体のプレビュー(レベル(b)の設計ゲート):
node "${PLUGIN_ROOT}/scripts/preview-app.js" --spec @<working-dir>/app-spec.jsonを実行すると、データモデル+サイトマップ+フォームのワイヤーフレーム+ページの意図+設計コントラクトが表示されます。表示された出力の全体をそのままチャットの返答に再掲し、フェンス付きの```コードブロックに入れてください。ツールの出力(折りたたまれていて見えない)に残したり、「プレビューは問題ありません」のように要約したりしてはいけません(上記の CRITICAL 注記を参照してください)。 ユーザーが承認する各フォーム、サイトマップ、ページの意図を確認できるようにする必要があります。フォームが1つだけの場合は、node "${PLUGIN_ROOT}/scripts/preview-form.js" --spec @<working-dir>/app-spec.jsonを実行します。 - テーブル/列を事前に作成しないでください。ビルド時に冪等に作成されます。
- レベル(a0)— ペルソナと達成すべき作業(
- ガードレール lint(必須ゲート) — 完全な spec に対してフル lint を実行します。エラーがあれば処理を止め、警告は改善に役立てます。エラーまたは警告がある場合は、検出内容をチャットの返答に貼り付けてください。ツールの出力は折りたたまれていてユーザーには見えないため、確認できない内容はユーザーが修正できません(上記の CRITICAL 注記を参照してください)。
これにより、移行とnode "${PLUGIN_ROOT}/scripts/lint-app-spec.js" --spec @<working-dir>/app-spec.json --jsonvalidateAppSpec(ビルド自体が読み込み時に実行するゲート)、およびlintAppSpecによる作成時のガードレール(ビルダーでは実行されません)が実行されます。エラーがあるとゼロ以外の終了コードになります。planプロファイルで検証します。このプロファイルでは、まだ生成されていない意図ページが許可され、手順6のドライランと一致します。 - プランモードでの承認(ビルドに対する唯一の承認) —
EnterPlanMode内でプランを提示します。プランには、ビルドのドライランでフェーズごとに分類された計画も含めます(--applyを付けずに、意図ページが許可されるplanプロファイルでbuild-model-app.jsを実行します)。その後、ExitPlanModeを使ってユーザーの承認を得ます。承認後は、まずフェーズ1.5(ページ生成)を実行し、続いてフェーズ2を直接適用します(2回目のドライラン/承認はありません)。設計ドキュメントは手書きせず、レンダリングしてください。node "${PLUGIN_ROOT}/scripts/write-app-spec-doc.js" --spec @<working-dir>/app-spec.json --env <envUrl><working-dir>/model-app-plan.mdに、作業から画面への対応関係、データモデル、すべての画面、ナビゲーション、アクセスモデル、サンプルデータを記載し、{ ok, docPath, bytes, warnings }を出力します。warningsをユーザーに提示してください。作業をカバーする画面がない、生成ページのないアプリ、ペルソナにもroleGrants[]の項目にも権限が付与されていない新しいテーブルなど、設計上の不足を示しています。--envを指定すると、spec で追加するテーブルの権限とは別に、アプリにすでに関連付けられているロールも読み取り専用でドキュメントに記載されます(アプリを開くこととテーブルを使用することは、別々に確認する事項です)。読み取りに失敗した場合は、コマンドを失敗させず、ドキュメントに「未確認」と記録します。ドキュメントの保存場所をユーザーに伝えてください。ユーザー自身で保持でき、spec の編集後に再生成できます。
フェーズ 1.5 — ページの生成(メインループ、ヘッドレスワーカー)
プランモードの承認後(フルビルドの前):
-
データの事前ビルド —
genpage.js typesが実際の列名を解決できるよう、スキーマのみをビルドします。node "${PLUGIN_ROOT}/scripts/build-model-app.js" \ --env <envUrl> --spec @<working-dir>/app-spec.json --stage data --apply--stage dataはソリューションとデータモデルのみを適用します。--sample-dataは指定しません(行はフルビルド時に一度だけ作成されます)。適用して安全なのは--stage dataのみです。それ以外の--stageセレクターと、従来の--from/--to/--only/--skipセレクターは、ドライランでの確認専用です。 -
型 — ページが読み取るエンティティの Dataverse 型バインディングを生成します。
node "${PLUGIN_ROOT}/scripts/genpage.js" types --env <envUrl> --data-sources "<entity1,entity2,…>" --output-file <working-dir>/RuntimeTypes.ts--data-sourcesには、すべてのインテントページのdataSourcesの和集合を指定します。すべてのインテントページがモックのみの場合は、この手順全体を省略します。Windows ではパスにスラッシュを使用してください。スクリプトは{ "ok": true, "outputFile", "dataSources", "detail", "bytes" }を出力します。失敗(終了コード 1、"ok": false)した場合は手順を停止し、その理由を報告してください。ページワーカーに列名を推測させてはいけません。 -
ページプラン(アダプター) — ページワーカーの入力契約は App Spec ではなく プランドキュメント なので、スペックを投影して作成します。ページごとのディスパッチパラメーターも出力します。
node "${PLUGIN_ROOT}/scripts/write-page-plan.js" \ --spec @<working-dir>/app-spec.json --working-dir <working-dir> --env <envUrl> \ --app "<app name>" --languages "<languages from the environment probe>"<working-dir>/app-builder-page-plan.mdに書き込み、{ ok, planPath, pages: [{ name, key, file, dataMode, intent }] }を出力します。環境プローブから--languagesを引き継いでください。省略すると、すべてのプランが暗黙的に英語のみとなり、ローカライズのパターンが失われます。プランに存在しないサンプルが指定される場合、またはワーカーが書き込むページが作業ディレクトリ内の安全なターゲットではない場合(そのパスにリンクがある、ディレクトリが作業ディレクトリ外を指している、または別の表記でページがすでに存在する場合)、あるいはプラン自体のパスにリンク、ハードリンク、またはディレクトリがすでにある場合、コマンドは書き込み前に失敗します。指摘された問題を解決してください。ワーカーをディスパッチしてはいけません。 -
生成 — 手順 3 で
intent: trueとなっている各ページについて、ヘッドレスのgenpage-page-builderワーカーをTask経由でディスパッチします。ドキュメントに記載された入力契約をそのまま使用してください。フィールドが欠けていると、ページが.tsxにならないままになることがあります。あなたは genpage-page-builder エージェントです。手順 3 の [name] ページを生成してください。
- ターゲットファイル:[手順 3 の [file] — すでに .tsx が含まれているため、追加してはいけません]
- プランドキュメント:[手順 3 で書き込まれた app-builder-page-plan.md の絶対パス]
- データモード:[手順 3 の dataMode —
dataverseまたはmock] - コネクター:なし
- テレメトリ:無効
- RuntimeTypes:[RuntimeTypes.ts の絶対パス] ← データモードが
mockの場合はこの行を省略します - 作業ディレクトリ:[working-dir の絶対パス]
- プラグインルート:${PLUGIN_ROOT}
エージェントファイルの指示に従ってください。[file] に書き込み、完了したら結果を返してください。
プランの
## EnvironmentにはMode: app-builderがあり、各ページ行には Key が含まれます。そのため、ワーカーはページ間のナビゲーションに"PAGEREF_<key>"を出力します(ファイルから導出したトークンは使用しません。ダウンロードしたページのcodeFileはパスであり、ページの識別子ではありません)。カスタムナビゲーション ID はdata:に指定し、recordIdは使用しません。ここではConnectors: noneとTelemetry: disabledは定数です。App Spec にコネクタバインディングの概念がないため、投影されたプランには常にNo connector bindings.と記載されます。また、/app-builderはフェーズ 4.7 のcustom-telemetryプローブを実行しません。どちらも省略せず、明示的に記載してください。ページビルダーは、行が欠けている場合も同じフェイルクローズの値として扱いますが、行を明示することでディスパッチ契約を確認できます。 -
スタイルを確認してから、検証して移行をコミットします(トランザクション方式) — ワーカーにはシェルがないため、まず、生成された各ページで、
makeStylesが実行時に削除する Griffel のショートハンドを確認します。1 ページにつき 1 コマンドを実行します(<file>はステップ 3 のページのファイルです)。node "${PLUGIN_ROOT}/scripts/check-griffel-styles.js" --file <working-dir>/<file>Griffel は 10 個の CSS ショートハンドをサポートしておらず、
makeStylesは実行時にそれらを削除します。そのため、ページは型チェック、トランスパイル、デプロイを通過しても、境界線、色、またはリセットが反映されないままレンダリングされます。対象はall、borderColor、borderStyle、borderWidth、borderBlock、borderBlockStart、borderBlockEnd、borderInline、borderInlineStart、borderInlineEndです。代わりにロングハンドを記述してください。borderColor、borderStyle、borderWidthは、それぞれ辺ごとのロングハンドにします。border+Top、Right、Bottom、Left+Color、Style、Widthの形式です(borderWidth→borderTopWidth、borderRightWidth、borderBottomWidth、borderLeftWidth)。borderBlock、borderInlineと、それらのStartおよびEnd形式は、対象となる辺のWidth、Style、Colorのロングハンドにします(borderBlockStart→borderBlockStartWidth、borderBlockStartStyle、borderBlockStartColor、borderBlock→ これらと、borderBlockEnd…の 3 つ)。allにはロングハンドがないため、必要なプロパティを個別に設定してください。その他のショートハンド(padding、margin、border、borderRadius、gap、outline)はサポートされており、インラインのstyle={{ … }}はそもそも Griffel ではありません。check-griffel-styles.jsは、検出した問題をそれぞれ出力します。makeStyles呼び出し内の任意の深さにある、Griffel が削除するキーについては行、列、ロングハンドを出力し、読み取れない呼び出しやスタイルオブジェクトについては変更内容を出力します。問題が残っている間は終了コード 3 で終了します。報告された内容を修正して再実行し、終了コードが 0 になるまでページをトランスパイルしたりアップロードしたりしないでください。このチェッカーが読み取るのは、呼び出し内にインラインで記述されたスタイルオブジェクト、つまりmakeStyles({ … })です。そのため、外部から渡されたオブジェクトやスプレッド(makeStyles(styles)、...base)はキーを確認できず、エラーとして報告されます。また、式から計算されるキー([key]: …)も名前を確認できないため報告されます(--、&、:、@で始まるテンプレートは読み取られます)。Fluent の...shorthands.*(…)と...typographyStyles.*はスプレッドしてかまいません。その後、移行を検証してコミットします。
sourceを手動で切り替えたり、ワーカーから戻るたびにページを 1 つずつ切り替えたりしないでください。次を実行します。node "${PLUGIN_ROOT}/scripts/promote-intent-pages.js" \ --spec @<working-dir>/app-spec.json --working-dir <working-dir>生成されたすべてのページを確認します(ファイルが書き込まれていること、構造上モジュールであること、
PAGEREF_トークンが正規形式で、仕様のnavigatesToエッジと完全に一致すること)。確認後にのみ、すべてのページをintent → { kind: "tsx", codeFile }に単一のアトミック書き込みで切り替えます。いずれかの検証に失敗すると、終了コード 3 で終了し、app-spec.jsonは変更されないまま、失敗したページと理由を出力します。そのページだけを再生成して再実行してください。意図的に全件成功か全件失敗の方式にしています。仕様が中途半端に切り替わると、書き込まれていない.tsxがあることになり、Phase 2 のdeployプロファイルは、source.kind === "intent"が残っていると即座に失敗するためです。 -
Phase 2(冪等な完全ビルド)に進みます。
⚠️ 対話型の作成処理は、決して
Taskサブエージェント内で実行しません。ここでディスパッチするのは、純粋なヘッドレスのコード生成ワーカーだけです。ユーザー向けのプロンプトはすべてメインループから発信されます。
Phase 2 — ビルド(メインループで進行を説明)
必ず
scripts/build-model-app.jsを使用してください。ビルダーを手書きしないでください。 冪等に動作し(既存のソリューション、テーブル、列、リレーションシップはスキップするため、新規、既存、混在のいずれの環境でもそのまま動作します)、事前に作成したり、既存テーブルを特別扱いしたりする必要はありません。
ビルド計画は、プランモードですでに提示され、承認されています(Phase 1 のステップ 6 で、エンジンの実際のドライラン計画を確認できます)。承認されたらそのまま適用してください。ビルドの承認は 1 回だけで、追加の承認は不要です。適用後にビルド自身で検証するよう、--verify を追加してください(Phase 3 を参照)。
node "${PLUGIN_ROOT}/scripts/build-model-app.js" \
--env <envUrl> --spec @<working-dir>/app-spec.json --apply --verify [--sample-data] [--publish]
各ステップでは、ステータスがリアルタイムでストリーミングされ([n/total] ✓ created / ⊘ skipped / ✗ failed — <error>)、最後に ✓ build complete — X created, Y skipped, Z failed というサマリーが表示されます。
ビルドの進行状況を表示したままにしてください。 フルビルドには数分かかります。出力をストリーミングさせてください。
Select-Object -First/-Last NやSelect-Stringの先頭行数制限を使ってパイプ処理しないでください。バッファリングされ、実行が終わるまで進行状況が表示されなくなります(実行中のパイプが途中で切断されることもあります)。ログを保存するには、Tee-Object -FilePath <log>を使ってください(先頭行数制限は使いません)。ビルドでは、<workspace>/.maker-workspace/build-status.jsonを指す▸ live progress:行も出力されます。これは各ステップで上書きされるスナップショット(state、steps、lastPhase、lastLabel)です。いつでもこれを読み取る(またはbuild-log.jsonlの末尾を確認する)ことで、標準出力がバッファリングされていても、時間のかかるビルドの進行状況を報告できます。
(新たにプランモードで承認を得ずにフェーズ 2 に進む場合――失敗したビルドの再開や、簡単な編集後の再実行など――は、最初にドライランを実行し(--apply を外す)、フェーズごとにまとめられたプランをそのままチャットの返信に貼り付けて(ツールの出力は折りたたまれています。上記の重要な注意を参照)、適用前に承認を得てください。)
ステージセレクター(--stage <data|ui|app|publish>) は、フェーズの範囲に対応します。--apply で受け付けるのは --stage data のみです(ソリューションとデータモデル。実行 1 では行を作成せず、実行 2 ではフルビルドを行います)。その他のステージや、従来の --from/--to/--only/--skip セレクターは、ドライランでの確認にのみ使用できます。これらのフェーズ範囲は依存関係が閉じておらず、--apply では拒否されます。
言語(--language-code / --languageCode <lcid>) は通常、指定する必要はありません。データモデルのラベルには、ビルドごとに一度読み取った、組織独自の基本言語が設定されます。別のプロビジョニング済み言語でラベルを作成する場合、またはビルドで基本言語を特定できず 1033 にフォールバックしたという警告が表示された場合にのみ指定してください。
組織でプロビジョニングされていない LCID を指定した場合、ビルドはデータモデルのフェーズで停止し、ラベルを書き込む前に、組織で利用できる言語の一覧を表示します。この確認が必要なのは、Dataverse の処理に一貫性がないためです。テーブルと選択肢のラベルは受け付けられて(HTTP 204)、組織の基本言語でひそかに保存される一方、DateTime 列と Memo 列は "The language code N is not a valid language for this organization" というエラーで拒否されます。この確認がなければ、ビルドは誤ったラベルでテーブルを作成した後、列の処理途中で停止します。原因となったフラグから数フェーズ離れた場所で停止するため、環境の問題のように見えてしまいます。プロビジョニング済みの言語一覧は、次のコマンドで取得できます。
node "${PLUGIN_ROOT}/scripts/dataverse-request.js" <envUrl> GET RetrieveProvisionedLanguages
この確認はベストエフォートです。読み取りに失敗した場合、ビルドは変更なしで続行します。
App Spec の languageCode フィールドを使うと、実行間で同じ値を固定できます。これはビルド全体に適用されるようになりました。データモデルのラベルに加え、フォーム、ダッシュボード、サイトマップのラベルにも適用されます。以前 1033 をハードコードしていた SDK シリアライザーでは、オーサリング言語をオプションとして指定できるようになりました。
同じフラグを指定して検証してください。 --language-code <lcid> を指定してビルドを実行すると、フォームのタブとセクションのキャプションがその言語で書き込まれます。そのため、スタンドアロンの検証ツールにも同じ --language-code <lcid> を指定する(またはスペックで languageCode を固定する)必要があります。指定しないと、--verify は組織の基本言語でキャプションを探すため、正しく公開されたフォームのキャプションを確認できず、未検証として一覧表示するか、見つからないと報告します。ビルド内の --verify には言語が自動的に渡されます。検証で言語を特定できない場合(組織を読み取れない場合)は、該当するキャプションを未検証として一覧表示します。合格でも失敗でもなく、その理由を示します。この場合はフラグを指定して再実行してください。
環境のフォーム読み取りで表示されない言語。 フォームの
FormXMLにどの言語のラベルを含めるかはプラットフォームが決定するため、フォームに保存されている数より少ない言語しか返されないことがあります。たとえば、スペイン語(3082)のキャプションを含めて作成されたフォームを英語の組織で読み取ると、スペイン語のキャプションが保存されていても、ラベルは英語のみで返されます。読み取り結果にほかの言語のラベルが含まれている限り、Verifyは読み取り結果に含まれない言語のキャプションが欠落しているとは判断しません。その代わりに、アプリのソリューションの翻訳エクスポートを1回だけ読み込み(キャプションが存在する場合に限り追加リクエストを1回実行します。テーブルが1つのソリューションでは7~11秒、ソリューションが大きくなるほど長くなります。公開済みレイヤーが表示されます)、正しいキャプションは合格し、古いキャプションや空のキャプションはほかと同様に不合格となります。また、{ "1033": …, "3082": … } のラベルマップも同様に言語ごとに比較されます。エクスポートに失敗した場合、または判定できない場合(リクエストの失敗、読み取れないアーカイブ、フォームの行がない場合)、Verifyはその言語で比較されるラベルを未検証(合格でも不合格でもありません。実行結果と終了ステータスは変わりません)として、理由と読み取り結果に含まれる言語とともに一覧表示します。その旨を伝え、Power Appsで該当する言語を選択してキャプションを確認するようユーザーに依頼してください。「修正」するために再構築してはいけません。読み取り結果に含まれる言語は、引き続き読み取り結果を使って厳密に比較され、古いキャプションがあれば不合格になります。読み取り結果にラベルがまったく含まれないフォームはこれに該当しません。そのフォームについて仕様で宣言されたキャプションは欠落しているため、不合格になります。
実行中は進行状況を逐次説明してください。一時的な環境エラー(429または503、カスタマイズロック、同時操作ガード、サービスがエラーコードで示すSQLタイムアウト、接続のタイムアウトまたはリセット)は、--apply で自動再試行されます(ビルドは冪等なので、再試行では作成済みのものが再利用されます)。スロットリングされたサービスについては、要求された時間だけ待機します(Retry-After)。スロットリングされた読み取りまたは公開のHTTPクライアントによる再送、ページ書き込み、ビルドによるフェーズの再実行を含め、スロットリングによるすべての待機時間に対して、1回の実行につき5分の予算が適用されます。次の待機時間が予算内に収まらない場合、ビルドは要求された待機時間を示すthrottle-budget-exhausted停止で終了します。後でもう一度実行すると続行できます。(5xx、接続のリセット、デッドロックはスロットリングではありません。これらにはそれぞれ独自の短い再試行スケジュールが適用され、スロットリングの予算には算入されません。)回復不能なエラーでビルドが停止(BuildHalt)した場合は、そのエラーを提示し、AskUserQuestionを使って次の対応(仕様の調整/キャンセル)をユーザーに尋ねてから、再実行してください。すべて専用のアンマネージドソリューション内で行われます。--publishは最後の一括公開を制御し、この公開には既存のビューとフォームへの編集も含まれます。これを指定しなくても、それらの編集と、既存アプリのサイトマップの再同期は、変更を反映するために対象の成果物を個別に公開します(注意事項と制限を参照)。
ビルドに失敗した、または停止した場合の復旧:ビルドを最初からやり直します。 ビルドは冪等です。各フェーズではすでに作成済みのものを再利用し、不足分のみを補います。SDK のメタデータは <working-dir>/.maker-workspace/ に保存されます(--workspace で変更できます)。安全に適用できる --from <phase> のショートカットはありません。最初からやり直すのが、正しく安全な復旧方法です。例外として、already-exists による停止は、ワークスペースのディレクトリを削除するまで再実行しても繰り返されます。表示されたメッセージに従ってください。もうひとつ、ワークスペースは最初に開いた環境に属します。ワークスペースを開くのは --apply のみです。ドライランは一時的なワークスペースで動作するため、何も紐付けず、どのフォルダーからでもプレビューでき、そのフォルダーで --apply を実行すると停止される場合は警告します。別の --env を指定したビルドは、その環境の読み取りや書き込みを一切行う前に停止し、両方の環境名を表示します。環境が自動的にクリアされたり紐付け直されたりすることはありません。そうすると、SDK が保存した別の環境の成果物のコピーや、プッシュされていない編集内容、さらにその環境の成果物とともに保存されたページ所有権の記録やベースラインが失われるためです。停止メッセージに表示された環境に対してビルドするか、新しいアプリフォルダー(app-spec.json と、そこに記載されたファイルをコピーします)または新しい --workspace を使用してください。その環境にあるアプリのコピーが不要になった場合に限り、停止メッセージに表示された --clear-workspace コマンドを使って、その環境で削除してください。ページ所有権の記録が残っている場合、フォルダーは保持されます。停止メッセージにはフォルダーが単独の行に表示され、そのコマンドではそれを --workspace として指定します。表示されたとおりに、シェルで引用符で囲んで渡してください(二重引用符で囲むと、PowerShell と bash はパス内の $ を展開します)。ビルドで保存されたものが何もないフォルダー(SDK の空のフォルダーのみで、以前のプレビューや開始時点で停止したビルドによって残されたもの)は、そのとおりに説明されます。その環境では何もビルドされていないため、戻すものも削除するものもありません。フォルダーはそのまま削除するか、別の場所に移動できます。manifest.json に使用可能な環境が記載されていない、または有効な JSON ではないフォルダーでも停止します。その場合はフォルダーを別の場所に移動し(削除ではなく名前を変更してください。ページ所有権の記録やベースラインが含まれている可能性があります)、再実行してください。同じ環境でも別のホスト名(<org>.api.crm… と <org>.crm…)を使うと停止します。停止メッセージに表示されたホストで再実行してください。スタンドアロンの検証ツールはこのワークスペースも開かないため、アプリがデプロイされている任意の環境を検証できます。
--publish を指定すると、ビルドが変更したテーブルと、アプリがフォームまたはチャートを保持している、あるいは保持しようとしているテーブルが、ビルドによるアプリの書き込みまたは公開の前に、1 回のリクエストで公開されます。対象となるのは、ビルドが既存のビューやフォームを編集したテーブル、ビルドが書き込んだチャートのテーブル、ビルドがアプリをプッシュするたびにナビゲーションに含まれるテーブルです(SDK はビルドが行うプッシュのたびに、それらのアクティブな Main フォームを追加します。そのため、ラベルを保存したものの未公開のフォームがあると、そのテーブルが公開される前にアプリと一緒に固定・公開されてしまいます。初回ビルドとフォームを固定するビルドは、どちらも同じ方法で対象になります。アプリが失ったデフォルトビューを固定する必要があるページの変更分のみを再アップロードする場合、ページのバックエンド経由でアプリをプッシュして公開します。このプッシュでは固定するビューが追加され、フォームは追加されないため、ナビゲーションのテーブルは指定されません)。また、既存のアプリについては、保存済みコンポーネントリストに名前があるフォームおよびチャートのコンポーネントのテーブルも対象です。スペックでそのテーブルが指定されているかどうかは問いません(たとえば、Maker が追加したフォームや、未公開のフォームも含まれます)。これらのテーブルのフォームに保存された未公開のラベルは、そうしなければアプリの公開後も未公開のままになります。アプリがフォームまたはチャートを保持していると認識されていないテーブルは、この処理では公開されません。そのため、Maker がそこで未完了のままにしたものは未完了のまま残ります。たとえば、entities で宣言されているだけのテーブル(検索列の参照先など)、ページから読み取られるだけのテーブル、または app.tables によって固定されているだけのテーブルです。アプリのコンポーネントを完全に読み取れない場合、または読み取り結果が曖昧な場合(コンポーネントリストの行を特定できない場合など)、ビルドは変更したテーブルとナビゲーションのテーブルだけを公開し、失敗した読み取りを通知します。原因を解消してから、もう一度実行してください。これは、既存のビューやフォームを編集しないビルド(初回ビルドを含む)でも、追加で 1 回公開を行うということです。最後の公開では、ビルドに成果物があるテーブルが対象になります。
このリクエストが拒否されても、ビルドは続行され、その旨を通知します。対象のテーブルで保存したもの、アプリがそこで保持しているフォーム、書き込みによって追加されたフォームのうち、他のユーザーがラベルを保存している可能性のあるものを示し、その結果、アプリの公開で何が反映されない可能性があるかを知らせます。
エラーで停止するビルドは、保留していたビューとフォームを可能な限り公開します。その後、公開フェーズより前に停止していた場合は、スペックに記載されたテーブル(ページが読み取るテーブルを含む)のうち、保存済みだが未公開のフォーム、ビュー、チャートを一覧表示します。そこにはビルドが作成したものと、誰かがそこで保存したものが含まれます。読み取れなかった場合はその旨を伝え、公開対象のテーブルを示します。この一覧には列やその他の種類の変更は含まれません。公開フェーズの後に停止した場合、この種の通知は行われません。
編集内容を保存した後、公開する前に強制終了された場合(Ctrl-C、クラッシュ、ターミナルを閉じた場合など)、公開できないため、それらは保存済みでもライブには反映されず、次のビルドまで残ります。同じ完全なビルドをもう一度実行してください。再度書き込むことなく、それらを公開します。
フェーズ 3 — 検証と反復
--apply --verify は、スペックをデプロイ済みの状態(フェーズ 2)とすでに照合しています。ビルドは
verify PASS / verify FAIL — N missing の行を追加し、一部だけがひそかに反映された場合はゼロ以外の終了コードを返します(成果物は作成されたものの接続されていない場合や、あるフェーズで何も生成されなかった場合など)。後で再確認する場合(たとえば、再ビルドせずに Maker が変更した後)は、スタンドアロンの読み取り専用検証ツールを実行してください。エンティティ、列、ビュー、チャート、フォーム、サイトマップのサブエリアとアイコンを検証し、終了コードがゼロ以外の場合は不足しているものを一覧表示します。
node "${PLUGIN_ROOT}/scripts/verify-model-app.js" --env <envUrl> --spec @<working-dir>/app-spec.json [--language-code <lcid>]
--language-code は、ビルド時に指定した場合にのみ渡してください。判定結果の下に ⊘ で始まる行がある場合、そのチェックは検証を判定できませんでした(JSON 結果の unverified リストに含まれています)。合格でも失敗でもないため、何が判定できなかったのか、また何を確認すれば決着するのかを伝えてください。字幕の言語は --language-code で指定できます。一方、環境のフォーム読み取り機能が扱えない言語の字幕については、翻訳エクスポートでは判定できず(行に理由が記されています)、Power Apps でのみ確認できます。未検証の項目が1つでもある場合、実行結果を「すべてデプロイ済み」と報告してはいけません。
stderr に WARNING: 行が出た場合、それぞれの行は JSON 結果の warnings リストにも繰り返し記載されます。警告がない場合、このリストは存在しません。警告は判定結果ではなく、注意事項です。以前のリリースでは受け入れられたものの、現在のビルドでは拒否される仕様(列またはリレーションシップと、次回のビルドでの修正方法が示されます)、または実行時に削除できなかったページワークスペース(手動で削除するフォルダーが示されます)のいずれかです。警告によって ok や終了ステータスが変わることはないため、実行が成功していても警告が付くことがあります。警告はそれぞれユーザーに伝えてください。予期しないエラーで停止した場合は、そのエラーが出力され、JSON は出力されません。
次に、ブラウザーでアプリを開きます。app-spec.json を調整し、Phase 2 を再実行して反復してください。
ティアダウン(クリーンアップ)。 App Spec がビルドしたもの(ライブ検証プローブやビルド失敗時の成果物など)をすべて削除するには、分類器に安全なティアダウンを実行します。削除されるのは、仕様で宣言された成果物のみです。依存関係の順序は次のとおりです(アプリモジュール → ダッシュボード → コマンドバー → フォーム → セキュリティロール → グラフ → ビュー → 親ルックアップを削除するための拡張既定ビューのリセット → リレーションシップ → AI 行の要約 → テーブル[子から先に] → Web リソース(生成されたアプリアイコン+ページマニフェスト+宣言済みのもの) → グローバル選択肢 → ソリューション)。フォーム/グラフ/ビュー/リレーションシップは、テーブルより先に明示的に削除されます(テーブルを削除しても、相互参照が確実に連鎖削除されるとは限りません。ただし、そのテーブル自身の列は削除されます)。フォームに割り当てられたロールはフォーム自身の formxml 内で名前が参照され、プラットフォームが依存関係として扱うため、セキュリティロールはフォームの後に削除されます。また、ロールがテーブルの権限を保持していると、そのテーブルの削除を妨げることがあるため、リレーションシップ/テーブルより前に削除されます。コマンドのティアダウンでは、仕様がコマンドを作成したエンティティのコマンドバー全体を削除します。ティアダウンで削除されるのは、このビルドで作成されたテーブルのみです。システム/標準テーブル(account、contact、…)は自動検出され、スキップされます。また、エンティティに "existing": true が設定された再利用済みカスタムテーブルもスキップされるため、既存のデータは保持されます。同じフラグはリレーションシップとグローバル選択肢も保護します。ダウンロード時には復元されたすべての項目にこのフラグが設定されるため、ダウンロードした仕様をティアダウンしても、保持されるテーブルのルックアップ列が削除されたり、共有のオプションセットが削除されたりすることはありません。ダッシュボードは名前で検索されるため、ティアダウンで削除されるのはアプリのソリューションが保持するもののみで、同じ名前を持つ別のアプリのダッシュボードは削除されません。また、問い合わせ先となる実際のソリューションが仕様にない場合(ダウンロードで残ることのある Default など)は、ダッシュボードは削除されません。いずれかの手順が失敗した場合、再実行時に判別できるようソリューションは保持されます。ジェネレーティブページの手順が失敗した場合、再実行時にアプリが作成したページを見つけられるようページマニフェストは保持されます。また、テーブル上のビジネスルールを削除できなかった場合は、そのルールの有効化済みコピーがテーブルの削除後には削除できなくなるため、テーブルも保持されます。これには、そのアイコンの Web リソース、列がバインドされておりテーブルが存在する間はプラットフォームが削除を拒否するグローバル選択肢、およびテーブル自身とのリレーションシップも含まれます。再実行時には、まずルールを削除し、次にテーブルと、それに伴って保持されていたものを削除します。既定ではドライランです。実際に削除するには --apply --allow-destructive を追加してください(--clear-workspace を指定すると .maker-workspace/ も整理されます)。teardown --apply には --allow-destructive が必須です。これを指定しない場合、ティアダウンは拒否され、何も変更されません。
node "${PLUGIN_ROOT}/scripts/teardown-model-app.js" \
--env <envUrl> --spec @<working-dir>/app-spec.json [--apply] [--allow-destructive] [--clear-workspace]
安全フラグ(ビルド+ティアダウン)。 適用処理では、破壊的な操作がフェイルクローズ方式で制御されます。
--allow-destructive— 破壊的な操作を許可します。build --applyの場合:無人モードで既存のアプリを上書きすること、明示的なレイアウトにおけるフォームフィールドの削除またはサイトマップのターゲットの削除を許可します。また、pages-removedページのナビゲーションサブエリアからの切り離しも許可します(ページレコードはデプロイされたまま残り、削除されません)。フォームとサイトマップの削除については、直近の拒否または承認済みの実行で記録された削除が許可対象です。ライブ状態でそれを超えるものが失われる場合、適用は停止し、新たに破壊的となる削除のみを一覧表示して、その新しい一覧をレビュー用に記録します。実行中に現れたフィールドやサイトマップのターゲットは保持されるか、プッシュ前に停止されます。確認されないまま削除されることはありません。この記録は、削除フェーズを実行し、何も保持せずにビルドが完全に成功した場合にのみ消費されます。失敗、一部のみの実行、変更分のみの実行、読み取り不能な記録、検出の失敗時には保持されます。teardown --applyの場合:必須です。削除はすべて本質的に破壊的であるため、このフラグなしでの teardown は何も変更する前に停止します。- Pages フェーズの安全性 HALT。 誤った状態で処理を続行する可能性がある場合、ビルドは続行せずに停止します。HALT の理由を確認し、復旧のヒントに従ってください。
pages-identity-conflict— 仕様のpageIdとマニフェストでキーが一致しない、または重複した ID が 2 つのキーにまたがっています。手動で競合を解決してください(再ダウンロードするか、マニフェストを削除します)。pages-manifest-corrupt— マニフェストを解析できません(2 つのキーが同じ ID に対応しています)。マニフェストの Web リソースを削除し、最初からビルドし直してください。pages-removed— ライブページが仕様から削除されました。再追加するか、--allow-destructiveを渡してナビゲーションから切り離してください(ページレコードはデプロイされたまま残り、ビルドによってサイトマップが最終化されます)。pages-shared-across-apps— ページが別のアプリのサイトマップに存在します。公開済みの場合も、保存されているだけで未公開の場合も該当します(公開されたことのないアプリも含みます)。そのアプリから切り離してください。別のアプリに変更を加えるため、先にユーザーに確認してください。HALT にはアプリ名が表示され、アプリのidが埋め込まれたコマンドが出力されます(ID を読み取れなかった場合は<id of app …>が表示されます。ID はscripts/apps.js list --env <envUrl> --search <name>で確認できます)。node "${PLUGIN_ROOT}/scripts/genpage.js" remove-from-app --env <envUrl> --app-id <that app's id> --page-id <page id>を実行すると、そのアプリのナビゲーションからページが削除され、そのアプリが公開されます(保存されている内容はすべて同時に公開されますが、ページ自体は残ります)。または、Maker で切り離してください。--allow-destructiveを指定しても、この HALT は回避されません。ビルドはページをその場で更新する直前にも再確認するため、ビルド中に別のアプリがページを追加した場合も、その時点で停止します(「このビルドの実行中にアプリ間で共有されるようになりました」)。ページのアップロード中に別のアプリがページを追加した場合は、その時点ではすでに書き込まれているため、アプリ名を示す警告が後から出力されます。pages-shared-check-failed/pages-existence-failed/pages-sitemap-read-failed— 前提となる読み取りに失敗しました。ビルドを安全に続行できません。一時的なエラーの場合は再試行し、継続する場合は権限を確認してください。pages-griffel-shorthand— ページのmakeStylesに、実行時に Griffel が破棄する CSS ショートハンドが記述されているため、ページはボーダー、色、またはリセットを適用せずにデプロイされます。メッセージにはページ名、各キーの行と列、および記述すべきロングハンドが表示されます。ページのソースを修正して再実行してください。何もアップロードされていません。ビルドで新規作成するページ、および前回のビルド後にソースが変更されたページでこのエラーが発生します。変更していないページにすでに該当する記述がある場合は、現状のまま再送信され、警告が表示されます(現在、そのキーはレンダリングされません)。キーを削除するとページの見た目は現状のまま維持され、ロングハンドを記述するとスタイルがレンダリングされるようになります。同じ HALT は、チェックで確実に読み取れないmakeStylesの呼び出しも報告します。その場合は Griffel が破棄する CSS としてではなく、どのコードを変更すべきかを示します。
--non-interactive— 対話型プロンプトを抑制します(自動化/CI 用)。既存のアプリに遭遇した非対話型ビルドは、警告して続行するのではなく失敗します。ただし、--allow-destructiveも設定されている場合を除きます。このフラグだけでは破壊的な操作は許可されません。許可するのは--allow-destructiveのみです。POWER_PLATFORM_SKILLS_NONINTERACTIVE=1(またはtrue)—--non-interactiveと同等の環境変数です。動作も同じで、プロンプトのみを抑制し、破壊的な操作は許可しません。対話型プロンプトで処理が停止しないよう、CI ジョブの環境で設定してください。- 自動操縦/評価モード(
--non-interactive+--allow-destructive)では、計画の実行前にデザイン成果物としてpreview-app.jsがディスクに書き込まれます。対話型の同意ゲートは回避され、明示的に許可されていない破壊的な操作がある場合、ビルドはフェイルクローズします。
AI ファースト機能
App Spec の ai ブロックでは、アプリレベルの4つの機能と、テーブルごとの Copilot 行
要約を制御します。すべての機能は管理者による制御が必要です。環境管理者が Power Platform Admin Center(Environments → Settings →
Product → Features)で有効にした環境でのみ有効になります。ai-features ビルドフェーズでは、SDK
(RetrieveSetting)を使って各設定の事前確認を行い、無効になっている設定は警告を出してスキップします。ビルドが失敗することはなく、管理者やテナントのスイッチを独自に切り替えることもありません。
事前確認(単独実行):
node "${PLUGIN_ROOT}/scripts/ai-preflight.js" --env <envUrl> [--app <uniqueName>]
各機能のオン/オフ状態と、オフの場合に必要な管理者の操作を正確に表示します。 失敗することはありません。
アプリレベルの機能(ai.appFeatures)— formFill(Copilot によるフォーム入力)、nlSearch
(自然言語によるグリッド/ビュー検索)、nlChart(自然言語のグラフ/AI データ可視化)、m365(M365
Copilot)。m365 を除き、すべてデフォルトでオンです。m365 はプラットフォームのデフォルト設定のままです。false を指定すると、このアプリに明示的なオフ設定を書き込みます(各設定の値については references/app-spec-schema.md → ai を参照)。
テーブルごとの行要約(ai.summaries):
default: "auto"— スキルが適切な候補となるテーブルを自動選択します(参照のみ/構成/ジャンクションテーブルと、Dynamics 365 が所有するincident、lead、opportunityは除外します)。default: "off"— テーブルで明示的に有効化しない限り、要約は無効です。summaries.tablesでテーブルごとの設定を上書きできます。enabled、カスタマイズしたinstruction、および要約で読み取るフィールドを指定するcolumns[]を設定します。{ "enabled": false }の項目を指定すると、特定のテーブルが対象外になります。
プロンプト作成のガイドライン(instruction 用):フィールド/値の繰り返しではなく、有益な洞察が得られるように記述します。レコード GUID は含めないでください。関連する場合は最近のアクティビティを取り入れ、対象者に適した語調を使い、明確な出力形式(短い段落など)を指定してください。
ティアダウンでは、標準の成果物に加えて、ai-features フェーズで作成された AI レコード(要約構成行および公開済み AI モデル)を削除します。
デプロイ済みアプリの編集(ダウンロード → 編集 → 再ビルド)
編集にも同じ App Spec を使用します。別個の編集手順はありません。既存のアプリを変更する場合(フィールド/ビュー/ページの追加、ページのコード編集、ナビゲーションのタイトル変更/並べ替え、アイコンの差し替えなど)は、まずデプロイ済みアプリを最新の状態で spec に取り込み、その spec を編集して Phase 2 を再実行します。
node "${PLUGIN_ROOT}/scripts/download-model-app.js" --env <envUrl> --app <appId|uniqueName|displayName> --out <working-dir>
--app は、アプリ ID(GUID)→ uniquename → 表示名の順に照合して特定します。表示名は変更でき、重複する可能性があるため、一意の名前を優先してください。一意の名前は変更できません。複数のアプリが一致する表示名は受け付けず、推測で選ぶのではなく、候補となる一意の名前を一覧表示します。
この操作で、アプリは <working-dir>/app-spec.json に再構築されます。往復変換の範囲 — 正確に把握してください。すべてが対象ではありません:
- **往復変換されるもの:**サイトマップから
appShell(すべてのサブエリアとアイコン)、すべての生成ページ(SDK を通じて読み取ります。ページはサイトマップのGenPageサブエリアであり、Maker で追加されたページも含まれます。また、それぞれの名前とモデルが保持されます)と、それらの.tsxファイルをpages[]に格納したもの、参照されているエンティティ(最小限。ビルドでは既存のテーブルを再利用します)、クラシックダッシュボード(デプロイ済みのビュー ID/グラフ ID を保持する、ID パススルーのタイル)、アイコンの Web リソース、ソリューション。 - 往復変換されないもの:
forms[]、views[]、charts[]、commands[]。これらは空の状態で戻ります。4 つすべてが稼働中のアプリには保持されます(再ビルド時に検出されるため、保持されます)。そのため、通常の編集は安全です。ただし、ダウンロードした仕様からは編集できません。Maker または新しい仕様で変更してください。 - **ロールは仕様に含まれず、再ビルドしてもそのまま維持されます。**ダウンロードには
personas[]が含まれません。アプリに関連付けられたロールは、環境に設定されている状態のままです。ロールを他の人が所有するアプリを拡張する場合は、personas[]を含めないでください。ペルソナのロールは、宣言された権限に完全に収束され、ビルドで作成していないロールは拒否されます。既存のロールに新しいテーブルを付与するには、roleGrants[]エントリを追加してください(追加のみ。ロールはアプリに関連付けられません)。Lint と設計ドキュメントには、ペルソナも付与設定も適用されていない新しいテーブルがそれぞれ記載されます。また、write-app-spec-doc.js --envには、アプリが持つロールが一覧表示されます。
次に:
- 編集セッションの開始時に必ず最新の内容を取得します — Maker で誰かがアプリを変更している可能性があります。ビルドではハイドレーション時に etag を読み込むため、取得後に変更された成果物に書き込むとバージョン競合が発生します → 再取得して再試行し、決して上書きしないでください。毎回、同じ
<working-dir>に取得してください。ページには、以前のダウンロード時に割り当てられたkeyが保持されます(既存のapp-spec.jsonで、このアプリがapp.uniqueNameに指定されている場合はそこから読み取り、ページの id で照合します)。また、別の環境にデプロイされた spec のコピーは、そこで作成されたページにそのキーで紐付けられます。キーが変わると別のページが更新されます。新しいフォルダーではキーが再生成されます。取得時に"code": "page-keys-ambiguous"が返された場合、以前のapp-spec.jsonで1つのキーが2つのページに割り当てられている(または1つのページに2つのキーが割り当てられている)ため、何も書き込まれていません。ページ名とキーが記載されたメッセージをユーザーに表示し、ファイルを修正して再取得するか、キーを新しくすると別の環境にデプロイされたコピーが誤ったページを更新する可能性があるため、ユーザーが指示した場合に限り、--reset-page-keysを指定して再取得し、該当するページだけキーを再割り当てしてください。"code": "navigation-language-unknown"が返された場合、環境の基本言語を読み取れず、アプリのナビゲーションタイトルの言語が不明なため、何も書き込まれていません。再取得するか、--language-code <lcid>(環境の基本言語。ビルドで受け付けるフラグです)を指定してください。フォルダー内の spec ですでにlanguageCodeが固定されている場合は、どちらも不要です。推測で決めないでください。タイトルが誤った言語で読み取られた spec を使うと、次のビルドで正しいタイトルが上書きされます。 - 依頼された変更に合わせて
app-spec.json(および必要なページの.tsx)を編集します。手作業で編集したページも生成されたページと同じチェックを受けます。再ビルドする前に、node "${PLUGIN_ROOT}/scripts/check-griffel-styles.js" --file <page.tsx>を実行し(ルールと10個のショートハンドについてはフェーズ1.5の手順5を参照)、報告された問題を修正してください。ダウンロード時点ですでにページに存在していたキーも報告されます。デプロイ済みのページは現在そのキーなしで描画されるため、削除してもページの見た目は変わりません。一方、ロングハンドで書き換えるとスタイルが描画されるようになります。ユーザーがその変更を望んでいない限り、キーを削除してください。ビルドでは、このアプリに対する直近の正常な apply 以降に新規作成または変更された、アップロード対象のすべてのページに対して同じチェックを実行し、pages-griffel-shorthandとして停止します。ページ名、各キーの行と列、およびロングハンドが示されるため、問題のあるページがアプリに反映されることはありません。「変更」の判定には、.maker-workspace/last-applied.jsonに記録された、そのページの apply 時のソースを使用します(正常な全件または変更分のみの apply、あるいはダウンロード時に記録されます。失敗したビルドや部分的なビルドでは何も記録されません)。変更していないページはそのまま再送信され、すでに存在するキーは警告だけを出します。また、ページを変更したものの、そのページの記録がないワークスペース(新規ページや移動したページ、別の環境など)でも警告だけが出ます。その場合、ビルドでは何が送信されたか判別できないため、そのページに対して自分でチェッカーを実行してください。 - 編集でページを追加する場合(またはページの
sourceをintentに戻して再生成する場合)は、フェーズ2の前にフェーズ1.5を再実行してください。ダウンロードされた spec にはkind: "tsx"のページしか含まれないため、追加されたintentページにはコードがなく、フェーズ2のdeployプロファイルで拒否されます。フェーズ1.5は安全に再実行できます。write-page-plan.jsはすべてのページを投影するため、ワーカーは実際のナビゲーション構造を認識します。エコーがintent: trueを示すページにのみワーカーが割り当てられ、promote-intent-pages.jsはビルド済みのページを変更しません。既存ページの.tsxを手作業で編集する場合、再生成は不要です。 - ビルドを再実行します(フェーズ2)。ビルドはべき等です。既存のアプリ/テーブル/ビューを再利用し、各ページをその場で更新します(名前で照合 →
--page-id。そのため重複は作成されません)。また、既存のGenPageサブエリアを保持します(ダウンロード時にpages[]/appShellに列挙されているため、サイトマップ全体の置き換えによって削除されることはありません)。 - 変更が意図したとおりにのみ反映されたことを確認するため、検証します(フェーズ3)。
genpage-first ポリシーに従い、従来型のダッシュボードより生成ページを優先してください。従来型のダッシュボードは往復変換に対応します(タイルは ID をそのまま通過させます)が、タイルが参照するビューやグラフは対応していないため、Maker でしか編集できません。
ビルダーの処理内容(順序)
ソリューション(冪等)→ データモデル — SDK を介して既存のテーブル/列/リレーションシップを検出し(findTables / findColumns / fetchEntityMetadata)、不足しているものだけを作成します(createTable / createColumn / createRelationship)→ サンプルデータ(オプトイン。リレーショナル/トポロジカルに作成し、$parent をエンティティセット名を使った @odata.bind に変換)→ Web リソース(オプトイン。フォームの JS/HTML/CSS 用に createWebResource を使用)→ ビュー → グラフ → フォーム(プライマリと列を配置し、明示的に指定された tabs を適用。サブグリッド、クイックビュー、フォーム JS(events[])は、SDK の汎用 addElement サーフェスを介して、正規のコントロールセル//bag/c のイベント領域として適用します)→ ビジネスルール(businessRules[] — バインドされた CreateProcessWithWfomJson メンバーを介してワークフローオブジェクトモデルとして作成し、有効化します。そのメンバーが宣言されていない環境では、警告を出してスキップします)→
ビジネスプロセスフロー(businessProcessFlows[]。作成したステージからコンパイルしたカテゴリ 4 のプロセスを有効化します。これは SDK の汎用アーティファクトサーフェス、つまり通常の workflows 行を介するため、上記のバインドされたメンバーのゲートの対象にはなりません)→ コマンドバー(commands[])→ 従来型のダッシュボード(オプトイン)
→ アプリモジュール+サイトマップ → 生成ページ(各ページの .tsx はフェーズ 1.5 で生成済みです。ビルドでは各 pages[] ページを SDK 経由で書き込み、配置は行いません。その後、SDK がサイトマップを書き換えて GenPage サブエリアを追加します)→ AI 機能(オプトイン)→
セキュリティ(personas[] の各エントリに対し、ジョブで宣言されたアクセス権に応じたロールを 1 つ作成します。アプリモジュールの読み取り権限を追加し、各ロールにアプリを関連付けて、そのペルソナでアプリを開けるようにします)→ 公開(オプトイン)。アプリに生成ページのサブエリアがある場合、アプリモジュールはそれらを含めずに先に作成されます(ページのアップロード前は解決できないため)。その後、ページのフェーズでサイトマップを書き換えます。Dataverse へのアクセスはすべて SDK 経由で行われるため、ダウンロードしたメタデータは .maker-workspace/ に保存されます。独立した操作(列、ビュー/グラフ/フォーム)は並列処理数を制限して実行します。公開では、エンティティごととアプリごとに 1 回の往復処理を行います。サブグリッドから子ビューの ID を参照できるように、ビュー/グラフはフォームより先に作成します。各ステップで [n/total] が出力されます。
注意事項と制限
- ヘッドレスで、ブラウザーは不要です。 SDK(
cds-maker-sdk。scripts/vendor/にベンダー提供)は、デザイナー独自のシリアライザーを再利用して、デザイナー品質の FormXML/FetchXML/サイトマップを生成し、azトークンを使う HttpClient 経由で Web API に書き込みます。リレーもデザイナーのタブも必要ありません。 - アプリごとに専用のアンマネージドソリューションを使用します(レビュー/削除用)。
--publishは、アプリのエンティティとアプリのカスタマイズに対する最後の 一括 公開を実行する条件です(各エンティティとアプリごとに 1 回のPublishXml)。--publishを指定すると、この 1 回の公開には既定ビューの拡充も含まれ、ビルドで変更したテーブルと、アプリが保持する、またはこれから保持するフォームやグラフのテーブルも、アプリより前に 1 回のリクエストでまとめて再公開されます。対象には、既存のフォームやビューの調整、フォームイベント、クイックビューの配置によって触れたテーブルが含まれます。これらが個別に公開されることはありません。また、ビルドで書き込んだグラフのテーブルも含まれます(グラフの説明は未公開レイヤーに保存されます)。ビルドがアプリをプッシュするたびに、ナビゲーションに含まれるテーブルも対象になります(SDK はそれらのアクティブな Main フォームをアプリに追加します。ラベルを保存しただけで公開されていないフォームが稼働中の場合、そうしなければ、テーブルより先にアプリとともに固定されて公開されてしまいます。app.mainFormsリストにフォームがないテーブルは何も追加しません。アプリが失った既定ビューを固定する必要があるページの、変更部分のみの再アップロードも対象です。プッシュによってビューが追加され、フォームは追加されないため、アプリより先に公開されるのは、アプリが保持するフォームとグラフのテーブルです。固定するものがない場合は何も公開されません)。さらに、すでに存在するアプリの場合は、保存済みコンポーネントリストに名前があるフォームとグラフのコンポーネントのテーブルも対象です。メーカーが追加して一度も公開していないフォームも含まれるため、そこで保存しただけで未公開のラベルがアプリの公開によって保留されることはありません。アプリがフォームやグラフを保持していると認識されていないテーブルは対象に含めません(宣言されているだけのテーブル、ルックアップ列の参照先、ページから読み取られるだけのテーブル、またはapp.tablesに固定されているだけのテーブルなど)。テーブルを公開すると、誰が保存したものであっても、そのテーブルに保存されたすべての内容が公開されます。アプリのコンポーネントを完全に読み取れない場合、ビルドでは変更したものと、書き込みによって追加するものだけを公開し、失敗した読み取りを通知します。また、変更を有効にするために編集/確定処理で必要となる、小規模な対象を絞った公開は抑制しません。--publishを指定しない場合、既存のフォームまたはビューの調整、フォームイベントの設定、クイックビューの配置では、その成果物だけを公開します。指定の有無にかかわらず、既存アプリのサイトマップの再同期と、生成ページの公開後に行うサイトマップの確定では、アプリを公開します。また、古い既定値のラベルが残ったルックアップ列を修復すると、そのテーブルを公開します(稼働中の成果物に対する未公開の編集は反映されません)。--publishを指定しない新規ビルドでは、新しいテーブル/列/リレーションシップは、ソリューション内でステージングされますが、未公開のままです。 - べき等ですが、望ましい状態への完全な収束ではありません。 既存のソリューション/テーブル/列/リレーションシップ/ビュー/グラフ/フォーム/コマンド/ダッシュボードは検出され、再利用されるため、再実行や既存テーブルがある環境でも衝突は発生しません。**編集時の注意点:**仕様から削除した成果物がビルドで削除されることはなく、既存の成果物に対する編集も一部しか再適用されません。フォームでは、フィールド(追加したもの。明示的なレイアウトの場合は削除したものも削除されます。下記の
prune: falseを参照)、列数、幅が収束します。ビューでは列が追加されるだけです。仕様から削除した列や、新しい列の順序は適用されず、フィルターや並べ替えも適用されません。列の種類を変更しても、コマンドやダッシュボードを編集しても再適用されません。既存のグラフには変更した説明のみが反映され、既存のアプリには変更した名前と説明が反映されます(アプリを一度も公開していない場合、そのテキストは保持され、ビルドは適用されなかったことを警告します。名前または説明がローカライズされている場合も同様です。保留されるのはそのテキストだけで、その他のテキストとルーティングの説明は適用されます。SDK は変更されたものだけを書き込み、SDK 自身によるヘッダーの読み取りに失敗した場合も、プレーンテキストではないテキストは送信されません。アイコンはアプリの作成時に設定されます。異なるapp.iconは適用されなかったものとして報告されます)。既存のビジネスプロセスフローには、レコードを移動させずに行えるステージとステップの編集(ステージの追加または名前変更、ステップの追加、名前変更、再バインドまたは移動)が適用されます。ステージまたはステップの削除、あるいはステージの並べ替えにつながる編集は、理由を示して拒否されます(その場合、ステージやステップの編集は一切適用されません。要求された Active/Draft 状態の設定は独立して処理されます)。 これらの編集を適用するには、Maker で変更するか、teardown --applyを実行してから新規にビルドしてください。--verifyは、仕様にあるビューの列、フィルター条件、並べ替えキー(作成した並べ替えキーでは順序も一致させる必要があります)、リレーションシップ、コマンド、ダッシュボードなど、不足しているものを検出して、明確なverify FAILを出します。デプロイ済みの余分な内容は許容されるため、仕様から削除したビューの列、フィルター、並べ替えキーは、メーカーが手作業で追加したものと同様に、残っていても検証に合格します。 - 対象外(今後対応):条件付きコマンドの表示(Power-Fx のみ)、タイトル付きコマンドグループ(一からの作成。SDK が合成する親行が必要)、ルックアップ/関連ビュー、複数エリアのサイトマップ、列レベル(フィールド)のセキュリティ、アクセスチーム/階層セキュリティ(いずれも SDK の今後の対応項目として記録済み)。現在のセキュリティ機能は、ペルソナごとのロールとフォームごとのロール割り当てで、どちらも提供されます。また、仕様の検証で拒否される BPF の設定項目(エンティティをまたぐステージ、分岐、ステージアクション)も対象外です。
- 環境によって制限されます(実行環境では動作しない場合があります):
- ビジネスルール(
businessRules[])。SDK は、バインドされたCreateProcessWithWfomJsonメンバーを通じてルールを書き込みます。これは、最新のビジネスルールデザイナーが使用するものと同じです。代替手段はありません。以前の代替手段だったクライアント側のワークフロー XAML コンパイラーは、7 種類のアクションのうち 4 種類と単一の句しか扱えず、作成者が記述した内容と異なるルールへと、気付かないまま縮小してしまうため、上流で削除されました。そのメンバーを宣言していない環境では、ビジネスルールを一切ホストできません。これは例外的なケースではなく、一般的なケースです。ビルドはルールをスキップし、メンバー名を示す警告を 1 回出して、ほかのものはすべて通常どおりビルドするため、アプリが作成途中の状態で残ることはありません。ルールが不可欠な場合は、事前に環境を確認してください。 ビジネスプロセスフローはこの制限の影響を受けません。 BPF は、バインドされたメンバーを使わずに、SDK の汎用成果物インターフェイスを通じて通常のworkflows行として書き込まれます。
- ビジネスルール(
- サポート対象:完全なデータモデル — すべての列の種類、自動採番の主列、グローバル選択肢、ステータスの理由、代替キー、N:N + ペイロード付きジャンクション。既存の列に対する
requiredの調整(true、false、または"recommended"。それ以外は検証時に拒否されます。明示的なrequiredは再ビルド時に収束し、省略した場合は必須ではない状態に変更されません)、新しいテーブルの作成時に主列へ指定するrequired(SDK が確認した場合にのみ適用済みと報告)、ブール値のdefaultValue、整数のintegerFormat(Durationを含む)、列ごとの書き込み権限(isValidForCreate/isValidForUpdate/isValidForRead。列を読み取り専用にする方法です。いずれも作成時と再ビルド時に適用)、1:N/N:N サブグリッドを備えたアダプティブなメインフォーム(セクション間、またはtab/column/after/beforeを使ってタブ/フォーム列内に配置でき、再ビルド時に配置が変更されます)、フィールドごとのフォームコントロール(readOnly/hidden/afterによる配置、およびフォームの一部を非破壊的に編集するprune: false)、クイック作成/クイックビューのフォーム(formType)とクイックビューの配置(forms[].quickViews[])、フォームごとのセキュリティロール(forms[].securityRoles。このフォームを表示するpersonas[]を指定するか、everyone: trueを指定します。ロールの作成後に適用されます。割り当てのないフォームはすべてのロールに表示されるため、これはフォームのアクセス権を付与するのではなく制限する設定です)、テーブルを開くときに使用するフォーム(forms[].isDefault/entities[].mainFormOrderにより、既存のテーブルでもテーブルの Main Form Set の順序を設定します。ユーザーが記憶させたフォームは、そのユーザーに対して引き続き優先して開きます。app-spec-schema.mdを参照)、選択肢列のグラフ、ビジネスルール(businessRules[]。最新のワークフローオブジェクトモデルとして作成し、有効化します。上記の環境制限を参照)、セキュリティロール(personas[]。ペルソナごとに、達成すべき業務に応じたロールを 1 つ作成し、管理者以外のユーザーもアプリを開けるようにアプリアクセスを設定します)、ダッシュボード(dashboards[]。グラフ/リスト/iframe/Web リソースのタイル)とダッシュボードのサイトマップ配置、生成ページ(pages[]。生成ページを既定とする方式で、SDK 経由で書き込み、GenPageサイトマップサブエリアとして表示します。download-model-app.jsによる作成と編集の完全な往復処理に対応)、最新のコマンドバーのボタン(commands[]。フライアウト/分割ボタンのメニューを含む)、詳細なビューのフィルター(eq-userid/this-week/in/not-in)、カスタムグリッドのレンダリング(entities[].columns[].visualization。放射状ダイヤル/折れ線グラフ/ヒートマップ/星評価、プレビュー)、Web リソースとフォームの JS イベントハンドラー、複数の親を指定する$parentsとstatusReasonを使ったサンプルデータ。詳細はdocs/app-builder-capabilities.mdとreferences/app-spec-schema.md(参照先の条件付きフィールドについてはapp-spec-schema-advanced.mdも参照)をご覧ください。仕様の作成にはこれらのドキュメントを使用してください。仕様を書くために SDK、リンター、エンジンを読む必要はありません。