diff --git a/.agents/skills/scaffold-code-app/SKILL.md b/.agents/skills/scaffold-code-app/SKILL.md index f358005..8040eb0 100644 --- a/.agents/skills/scaffold-code-app/SKILL.md +++ b/.agents/skills/scaffold-code-app/SKILL.md @@ -79,7 +79,20 @@ npx power-apps init -n '' -e "" This writes `power.config.json` (`appDisplayName`, `environmentId`, `region`, etc.). -### 5. Build and push the app into a solution (optional) +### 5. Set up the quality tooling (make the app verifiable) + +The Vite starter ships **no test runner** and at most a minimal linter, but every build task is gated +by `npm run verify`. Make the project verifiable now, before any feature work: + +- Add **Vitest + React Testing Library + jsdom**, wired to `npm test`. +- Add **ESLint + typescript-eslint + eslint-plugin-react-hooks**, wired to `npm run lint`. +- Add an **`npm run verify`** script that runs typecheck + lint + test in one command. + +See **AGENTS.md (repo root) → Stack notes** for the exact pins. After this, `npm run verify` runs +clean on the empty app, so the first task gate (Task 1) has a working harness to run against rather +than being set up live. + +### 6. Build and push the app into a solution (optional) Publishes the built app into a Dataverse **solution**. `power-apps push` needs the solution's **GUID** (`--solution-id`), but you should never have to find or paste a GUID — `push.mjs` resolves it @@ -114,9 +127,10 @@ needs rights to push into the target solution. - Verify `power.config.json` has the expected `appDisplayName` and `environmentId`. - Confirm `package.json` shows `@microsoft/power-apps` at `1.2.2`. +- Confirm `npm run verify` runs clean on the empty app, so the gate is ready before Task 1. - The app is now ready to scaffold/seed Dataverse tables and add them as data sources — see the `dataverse-scaffold-tables`, `dataverse-create-records`, and `dataverse-add-data-source` skills. -- To publish the app into a solution, run step 5 (`push.mjs`) — typically after the tables are scaffolded +- To publish the app into a solution, run step 6 (`push.mjs`) — typically after the tables are scaffolded into that same solution. ## Notes diff --git a/.claude/skills/scaffold-code-app/SKILL.md b/.claude/skills/scaffold-code-app/SKILL.md index f358005..8040eb0 100644 --- a/.claude/skills/scaffold-code-app/SKILL.md +++ b/.claude/skills/scaffold-code-app/SKILL.md @@ -79,7 +79,20 @@ npx power-apps init -n '' -e "" This writes `power.config.json` (`appDisplayName`, `environmentId`, `region`, etc.). -### 5. Build and push the app into a solution (optional) +### 5. Set up the quality tooling (make the app verifiable) + +The Vite starter ships **no test runner** and at most a minimal linter, but every build task is gated +by `npm run verify`. Make the project verifiable now, before any feature work: + +- Add **Vitest + React Testing Library + jsdom**, wired to `npm test`. +- Add **ESLint + typescript-eslint + eslint-plugin-react-hooks**, wired to `npm run lint`. +- Add an **`npm run verify`** script that runs typecheck + lint + test in one command. + +See **AGENTS.md (repo root) → Stack notes** for the exact pins. After this, `npm run verify` runs +clean on the empty app, so the first task gate (Task 1) has a working harness to run against rather +than being set up live. + +### 6. Build and push the app into a solution (optional) Publishes the built app into a Dataverse **solution**. `power-apps push` needs the solution's **GUID** (`--solution-id`), but you should never have to find or paste a GUID — `push.mjs` resolves it @@ -114,9 +127,10 @@ needs rights to push into the target solution. - Verify `power.config.json` has the expected `appDisplayName` and `environmentId`. - Confirm `package.json` shows `@microsoft/power-apps` at `1.2.2`. +- Confirm `npm run verify` runs clean on the empty app, so the gate is ready before Task 1. - The app is now ready to scaffold/seed Dataverse tables and add them as data sources — see the `dataverse-scaffold-tables`, `dataverse-create-records`, and `dataverse-add-data-source` skills. -- To publish the app into a solution, run step 5 (`push.mjs`) — typically after the tables are scaffolded +- To publish the app into a solution, run step 6 (`push.mjs`) — typically after the tables are scaffolded into that same solution. ## Notes diff --git a/AGENTS.md b/AGENTS.md index fac2802..5170d59 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -74,6 +74,9 @@ paraphrase the spec; the section numbers are stable, use them. - **Per task:** typecheck + lint (near-instant). **On the data-layer task:** the audit pass (the checklist in tasks.md Task 1). The test suite exists from Task 1's smoke test and peaks at the modal milestone (Task 3). +- **Commit each task when its gate is green.** After `npm run verify` passes (and the audit pass where + the task requires it), commit that task with a short message naming it, before starting the next. + The git log is the build record; never bundle two tasks into one commit. - Let the generated types and `tsc` catch drift. Prefer deleting and regenerating over hand-editing generated files. diff --git a/DEMO-PLAN.md b/DEMO-PLAN.md index 77976c3..e5ec631 100644 --- a/DEMO-PLAN.md +++ b/DEMO-PLAN.md @@ -1,4 +1,60 @@ -1. /dataverse-scaffold-tables -2. /dataverse-create-records -3. /scaffold-code-app -4. /dataverse-add-data-source +# Demo run sheet — EPPC26 Session Feedback Code App + +Build a governed Power Apps Code App live, from an empty environment, directed not typed. + +## Before you start (the skeleton) + +- This repo is the **harness only**: `AGENTS.md` (how we build), `specs/` (what to build), and the + mirrored `.agents/skills` + `.claude/skills`. There is **no Code App and no Dataverse tables yet**. +- The Power Platform environment has **no solution and no tables**. The demo creates them. +- One **cheap, fast model** runs the whole build, on purpose: it proves the harness matters more than + the model. + +## The run-through + +### Setup (3 skills) + +1. **`/dataverse-scaffold-tables`** — signs in (`npx power-apps login`), then creates the solution, + the option sets, both tables, and the relationship. This is the **Beat 2 failure-and-fix** moment + (harness off, then on). +2. **`/dataverse-create-records`** — seeds the sessions. +3. **`/scaffold-code-app`** — clones the Vite starter, pins the SDK, inits the app against the + environment, and **sets up the quality tooling** so `npm run verify` (typecheck + lint + test) runs + clean on the empty app. + +### Build-verify loop (4 tasks, one at a time) + +4. **Complete Task 1** — data layer. Opens by running `/dataverse-add-data-source`, then proves the + read path, adds the smoke test, and runs the **audit pass** ("agents auditing agents"). +5. **Complete Task 2** — home list (sessions as cards). +6. **Complete Task 3** — rate modal + submit. The **test milestone**. +7. **Complete Task 4** — EPPC branding (the design payoff). + +Each task: the agent reads `AGENTS.md`, then the task file, builds only that scope, runs +`npm run verify`, **commits when the gate is green**, and **stops**. You review, then run the next. +Never batch tasks. + +### Deploy + the live proof + +- `npm run build`, then `power-apps push` into the same solution. +- Open the governed URL: show **Entra sign-in working** and a **real rating writing to Dataverse**, + the card flipping to its rated state. +- Land it: **"I didn't write this. I directed it."** + +## Why this is trustworthy (the teaching points) + +- **One deterministic gate**, `npm run verify`, at every task. The trust comes from the checks, not + from eyeballing the code. +- **The git log** shows four clean commits the agent made, each behind a passing gate. Scroll it on + stage: directed, not typed. +- **No CI or git hook** — the build is throwaway and local, so the verify gate is the enforcement. +- **No "evals"** — the app has no AI inside it, so tests are the right tool; evals are for generated + output. + +## Highest dry-run risks (re-check on the day) + +- Exact `add-data-source` verb/flags under the npm `power-apps` CLI. +- `power-apps` global vs `npx power-apps`; pin the package version. +- The Vite template ships no test runner and only a minimal linter — `scaffold-code-app` must add + Vitest/RTL/jsdom + ESLint and the `verify` script. +- Node 22+ required. diff --git a/specs/tasks/task-1-data-layer.md b/specs/tasks/task-1-data-layer.md index 44c4ed6..bc94b26 100644 --- a/specs/tasks/task-1-data-layer.md +++ b/specs/tasks/task-1-data-layer.md @@ -5,6 +5,11 @@ **Goal:** the two Dataverse tables become typed data sources the app can read and write; no UI yet. +> **Start here:** run the `dataverse-add-data-source` skill to add `eppc_session` then `eppc_feedback` +> as data sources, which generates the typed `Model`/`Service` files the rest of this task builds on. +> Setup already created the tables, seeded them, and scaffolded the app with its tooling; this is the +> first build task. + **Implements:** - [../dataverse-schema.md §8](../dataverse-schema.md) — the generated `Eppc_sessionsService` / `Eppc_feedbacksService` contracts (read sessions, read feedback for a session, create feedback). @@ -16,19 +21,17 @@ **Scope (what must exist, not how to build it):** - Both tables are typed data sources with their generated `Model`/`Service` files committed — - `Eppc_sessionsModel`/`Service` and `Eppc_feedbacksModel`/`Service`. The `dataverse-add-data-source` - skill owns the command; this task only names the tables to add (`eppc_session`, then - `eppc_feedback`). + `Eppc_sessionsModel`/`Service` and `Eppc_feedbacksModel`/`Service` (produced by the + `dataverse-add-data-source` run above). - A read path proves the seeded sessions come back typed and ordered by `eppc_starttime`. With no UI yet, prove it somewhere disposable (console or a throwaway dev view) — the durable read UI is Task 2. - The write contract Task 3 depends on is present and type-correct: `Eppc_feedbacksService.create` exists, the lookup is expressed as `@odata.bind`, and Choice fields are integers — so the heavy write task starts from a known-good signature. -- The test runner is in place: **Vitest + React Testing Library + jsdom** wired to `npm test` - (AGENTS.md Stack notes), proven by one smoke test that mocks the generated service and asserts the - read path returns typed sessions ordered by `eppc_starttime`. This gives the data layer its own - automated gate and confirms the harness works, so the Task 3 milestone runs against a configured - harness rather than one set up live. +- One smoke test proves the data layer: mocking the generated service, it asserts the read path + returns typed sessions ordered by `eppc_starttime`. The test runner itself was set up by + `scaffold-code-app`; this task just adds the first test, giving the data layer its own automated + gate so the Task 3 milestone runs against an already-exercised harness. **Done when:** - `tsc` is clean.