Skip to content

Commit 49ac53a

Browse files
MaliheasadiCopilot
andcommitted
fix(canvas-apps): improve generated app functionality
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 8251d2c commit 49ac53a

8 files changed

Lines changed: 996 additions & 250 deletions

File tree

plugins/canvas-apps/AGENTS.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ references/
3434
LayoutGuide.md ← Responsive sizing, scrolling, galleries, and contrast
3535
GridLayoutGuide.md ← Conditional GridLayout formulas and invariants
3636
PowerFxGuide.md ← State, events, named formulas, and mock data
37+
BehaviorGuide.md ← Acceptance contracts for advanced app behavior
3738
DesignGuide.md ← Aesthetic guidelines, anti-patterns, design process
3839
QAChecks.md ← Named runtime anti-pattern checks for per-screen self-QA
3940
PlanTemplates.md ← Progressive index, shared plan, and screen-brief structures

plugins/canvas-apps/agents/canvas-app-planner.md

Lines changed: 68 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,9 +50,44 @@ exactly, record an explicit approximation and reason; never silently rename butt
5050
"drag-style", call buttons "handles", or put copy in the app that promises an interaction
5151
the controls do not provide.
5252

53+
Convert every concrete requested or approved-plan action into an Action Contract. Treat
54+
create, edit, delete, search, filter, flag, review, approve, reject, and similar verbs as
55+
separate flows with their own visible entry point, owning screen, handler, required data
56+
effect, and observable result. Broad words such as "manage", "maintain", or "track" do not
57+
require universal CRUD across every entity. However, a role-scoped requirement to manage
58+
all records of the app's primary entity is operational: plan a reachable management list,
59+
record detail, correction/update, and remove/cancel paths unless the request narrows the
60+
allowed operations or the domain makes a destructive action inappropriate. A review or
61+
approval workflow that distinguishes final approved records requires both approve and
62+
reject/decline decisions and visible resulting statuses unless the request explicitly
63+
defines a one-way review. Once included, each action must be planned end to end rather
64+
than represented by a screen or entity alone.
65+
66+
Treat temporal qualifiers and outputs as behavior, not decorative copy. Quarterly,
67+
monthly, annual, cycle, period, or similar requirements need a shared field or derivation
68+
that is visible on affected forms and records and can distinguish the active period.
69+
Export, download, print, or report requests need their own Action Contract with the exact
70+
eligible-record predicate, output fields, trigger, and visible completion evidence. If
71+
discovered controls and data sources cannot provide the requested output mechanism, plan
72+
an explicit approximation rather than omitting the action.
73+
74+
Decompose compound behavior into acceptance paths. Reordering, moving, constraints,
75+
derived metrics, version comparison, category management, and ranking each need an initial
76+
state, success path, boundary or rejection path when applicable, shared source of truth,
77+
and visible evidence. Record those paths in the Action Contract rather than assuming the
78+
builder will infer them from a feature name.
79+
80+
Infer the minimum supporting setup actions needed to exercise requested behavior when the
81+
app uses local/mock mutable data. For example, an org restructuring app needs a reachable
82+
way to add teams and people with manager relationships before reassignment, metrics, and
83+
version comparison can be meaningfully tested. These supporting actions are required
84+
dependencies, not universal CRUD. Add them to Requirement Coverage and Action Contracts.
85+
5386
Use `ModernTabList` only when it switches visible panels within one screen. For navigation
5487
between separate screen files, plan a repeated ModernButton row with direct `OnSelect:
55-
=Navigate(...)` actions and an explicit current-screen appearance.
88+
=Navigate(...)` actions and an explicit current-screen appearance. Put every primary
89+
destination in that row and keep it in the initial viewport at each supported breakpoint,
90+
or use an immediately visible menu button that exposes the complete destination set.
5691

5792
## 1. Read Guidance
5893

@@ -62,6 +97,7 @@ Read:
6297
- `${PLUGIN_ROOT}/references/ControlGuide.md` — control selection, per-control properties, enums
6398
- `${PLUGIN_ROOT}/references/LayoutGuide.md` — responsive layout, scrolling, colour contrast
6499
- `${PLUGIN_ROOT}/references/PowerFxGuide.md` — state, events, named formulas, mock data
100+
- `${PLUGIN_ROOT}/references/BehaviorGuide.md` — advanced behavior acceptance contracts
65101
- `${PLUGIN_ROOT}/references/DesignGuide.md` — aesthetic direction and design process
66102
- `${PLUGIN_ROOT}/references/PlanTemplates.md` — the exact shape of every artifact you write
67103

@@ -115,6 +151,16 @@ Before writing plans:
115151
If validation must wait for a submit attempt, combine one attempt flag with the
116152
current invalid expression; do not maintain or clear separate validity flags in each
117153
input's `OnChange`.
154+
- For every mutation, specify how the screen reflects the new state after success.
155+
Updating data without refreshing or updating the collection bound to the visible
156+
list is incomplete. A success notification alone does not satisfy an outcome that
157+
requires the created, edited, deleted, or transitioned record to be visible.
158+
- Apply `${PLUGIN_ROOT}/references/BehaviorGuide.md` to every advanced behavior. Name
159+
each required success and boundary path, the shared source of truth, and the control
160+
that provides visible acceptance evidence.
161+
- For every named core visualization, specify its bound source, first-render records,
162+
relationship or comparison encoding, populated-state controls, and truthful empty
163+
state. Do not plan blank containers or decorative rectangles as visualization content.
118164
7. Define data-field semantics once and reuse them. If a task has `ScheduledDate`,
119165
`DueDate` and `CompletedDate`, state which field drives calendar placement, which date
120166
the task list displays, and which field the monthly report groups by. Seed data,
@@ -165,6 +211,10 @@ For every screen brief, state explicitly:
165211
- That responsive layout properties derive directly from `App.Width`, `Parent.Width` or
166212
`Self.Width`. Do not initialize layout variables such as `varIsMobile` or `varColumns`
167213
in `OnVisible`; they can be unset in Studio and become stale after resize.
214+
- That the sole screen root always uses `Width: =Parent.Width`, `Height: =Parent.Height`,
215+
`LayoutMinWidth: =0`, and `LayoutMinHeight: =0`. Breakpoint sizing belongs on children;
216+
never put a narrow-width branch, button width, panel width, or fixed desktop width on
217+
the root.
168218
- That the root container scrolls (`LayoutOverflowY: =LayoutOverflow.Scroll`).
169219
- That the screen-level `Children:` list contains only that root, with every visible
170220
section nested under the root's `Children:` list.
@@ -178,13 +228,27 @@ For every screen brief, state explicitly:
178228
- A `TemplateSize` for every gallery that fits its row template **at each width branch**,
179229
counting a `ModernCard`'s image band. A dense desktop branch is the usual place card
180230
titles disappear.
231+
- For every mutation, where its observable result appears immediately afterward. Keep the
232+
result in the current viewport, navigate to the bound list/detail, or provide a visible
233+
control that takes the user there. Do not place the only proof far below a long form.
181234
- For every GridLayout: the exact `LayoutGridColumns`, `LayoutGridRows`,
182235
`LayoutGridColumnMinWidth`, `LayoutGridRowMinHeight` and `Height` formulas, plus every
183236
explicit child row/column position. The row count and height must reuse the same column
184237
expression.
185238
- For every fixed-height section and every horizontal row with four or more substantive
186239
children, include a per-breakpoint layout budget: child groups, minimum widths/heights,
187240
gaps, padding and the resulting section size. Presence of a breakpoint is not enough.
241+
- For every horizontal container, prove that visible child minimum widths plus gaps and
242+
padding fit at desktop, tablet, and phone widths, or specify the wrap/stack branch that
243+
makes them fit. For ManualLayout, provide bounds for every simultaneously visible
244+
control and prove they neither overlap nor extend beyond the parent at each supported
245+
width.
246+
- For every text-bearing control, state whether it is single-line or wrapping and provide
247+
a width/height budget for its longest planned or data-bound value.
248+
- Define one shared visual contract: title, section-heading, body, and caption type roles;
249+
spacing scale; surface and border treatment; primary/secondary action styling; and
250+
desktop/tablet/phone content density. Builders must copy these exact values rather than
251+
inventing screen-local themes.
188252
- Group each visible label with its corresponding input in one field container before
189253
the row stacks.
190254
- For bounded local galleries of about ten rows or fewer, size the gallery to all rows
@@ -253,6 +317,7 @@ Follow `${PLUGIN_ROOT}/references/PlanTemplates.md`.
253317
Write only orchestration information:
254318

255319
- Mode and requirements
320+
- Requirement Coverage and Action Contracts
256321
- Working directory
257322
- Compact discovery summary
258323
- Dispatch table
@@ -291,6 +356,8 @@ Each brief contains only what that builder needs:
291356

292357
- Action, logical screen, target file, YAML key, and control name prefix
293358
- Screen specification or exact edit list
359+
- Every Action Contract owned or affected by the screen, including the visible entry
360+
point, exact handler behavior, data effect, and observable result
294361
- Relevant portions of data source schemas and API details
295362
- For every control type used on that screen: the complete list of valid input
296363
property names, plus the full `Enum name:` and the **compile-ready enum literal** for

plugins/canvas-apps/agents/canvas-screen-builder.md

Lines changed: 47 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,10 @@ Do not read `canvas-app-plan.md`, other screen briefs, or other screen YAML file
4141
Do not call discovery tools. The assigned documents contain all required context.
4242

4343
Before writing, verify that the screen brief includes definitions for every control type
44-
it asks you to add or create. If any definition or required assignment field is missing,
45-
do not write partial YAML. Return:
44+
it asks you to add or create, and that every Required Actions row names an entry point,
45+
control event, required formula behavior, and observable result. If any definition,
46+
required assignment field, or action-contract field is missing, do not write partial YAML.
47+
Return:
4648

4749
```markdown
4850
Screen: [logical name]
@@ -87,6 +89,39 @@ Do not fix unrelated pre-existing issues.
8789

8890
### Both
8991

92+
- Implement every row in `## Required Actions`. The entry point must be visible and
93+
reachable, the named event must contain the required behavior, and the observable
94+
result must be rendered from the same source or state changed by the action.
95+
- Keep primary navigation and management actions in the initial viewport or behind an
96+
immediately visible menu or scroll affordance. A control that exists only below an
97+
unscrollable or ambiguous container is not reachable.
98+
- For search and filter actions, bind the named input directly into the target list's
99+
`Items` formula and include every field or state named by the brief.
100+
- For mutations, update or refresh the collection/source used by the visible list or
101+
detail after success. A `Notify()` call without a visible data result is not a complete
102+
implementation when the brief requires the changed record to appear, disappear, or
103+
move state.
104+
- Make the mutation's observable result visible immediately after the handler runs. Keep
105+
it in the current viewport, navigate to the bound list/detail, or expose an immediately
106+
visible action that opens it. Do not leave the only changed row below a long form.
107+
- Implement every success, boundary, rejection, persistence, and recalculation path named
108+
in `## Required Actions`. Reordering, constraints, metrics, versions, categories, and
109+
rankings are incomplete when only their happy-path control or display exists.
110+
- Implement role-scoped management actions on the primary-record surface named by the
111+
brief. Edit must load and update the selected record, delete/remove must have a
112+
confirmation or cancel path, and approve/reject controls must visibly update status.
113+
- Persist period or cycle values in the shared record source and render them wherever the
114+
brief requires period-aware review. Export/report actions must apply the exact eligibility
115+
predicate and fields from the brief and show completion evidence; a notification without
116+
an output is incomplete.
117+
- Implement supporting setup actions from `## Required Actions` against the same shared
118+
source used by the requested behavior. Seeded rows do not substitute for reachable
119+
creation of the minimum records needed to exercise the behavior.
120+
- Render every specified core visualization with bound content. Do not ship empty filled
121+
containers, disabled-looking input blocks, or decorative placeholders where the brief
122+
requires a hierarchy, chart, comparison, board, timeline, or map.
123+
- Follow the shared Visual Contract exactly. Do not introduce screen-local palette,
124+
typography, spacing, surface, or action styles.
90125
- Every control you **add** carries your assigned control name prefix. Control names are
91126
unique across the whole app, and you cannot see the other screens — the prefix is the
92127
only thing preventing a collision. This applies to repeated UI blocks such as nav bars
@@ -154,13 +189,16 @@ the first builder returns, so return promptly rather than polishing indefinitely
154189
Screen: [logical name]
155190
Action: [Create / Modify]
156191
File: [absolute target file]
192+
Actions: [implemented count]/[required count]
157193
QA: 1 [outcome] · 2 [outcome] · …
158194
- [fix summary, or "clean"]
159195
Status: Done
160196
```
161197

162198
The `QA:` line must list every check in `${PLUGIN_ROOT}/references/QAChecks.md`. A return
163199
without it is incomplete, and the orchestrator will send the screen back.
200+
The `Actions:` count must cover every Required Actions row. A lower implemented count
201+
means `Status: Blocked` with the unresolved action and reason.
164202

165203
## Constraints
166204

@@ -173,6 +211,13 @@ without it is incomplete, and the orchestrator will send the screen back.
173211
unquoted — `DecimalPrecision.'1'`, not `DecimalPrecision.1`.
174212
- Never leave a `ModernCard` slot unset. For text-only cards set `Image: =Blank()` and,
175213
when supported by the control definition, `HeaderImage: =Blank()`.
214+
- The sole responsive screen root always sets `Width: =Parent.Width`,
215+
`Height: =Parent.Height`, `LayoutMinWidth: =0`, and `LayoutMinHeight: =0`. Never copy a
216+
child control's fixed or conditional width onto the root during a repair.
217+
- A bounded Gallery's `Height` and empty-state visibility count the same source/filter
218+
expression used by `Items`. Never size or classify an empty gallery from
219+
`Self.AllItems`, `Self.AllItemsCount`, or rendered `AllItemsCount`; those values can
220+
create a zero-height materialization cycle.
176221
- Every multiword ModernButton or link that is a direct child of a vertical AutoLayout
177222
container sets `Width: =Parent.Width`; `LayoutMinWidth` and stretch alignment alone do
178223
not make the rendered control fill the row.

0 commit comments

Comments
 (0)