@topy-ai/maggie 0.7.46 → 0.7.48

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. package/README-zh-TW.md +12 -4
  2. package/README.md +55 -11
  3. package/bin/maggie.js +26 -4
  4. package/bundled-contracts/maggie-design/palette-roles-v1.schema.json +47 -0
  5. package/bundled-contracts/maggie-marketplace/template-content-v1.schema.json +103 -0
  6. package/bundled-contracts/maggiedash/booking-browser-evidence-v1.json +21 -0
  7. package/bundled-contracts/maggiedash/booking-browser-evidence-v2.json +191 -0
  8. package/bundled-contracts/maggiedash/booking-email-templates-v1.json +3 -1
  9. package/bundled-contracts/maggiedash/booking-voucher-lifecycle-v1.json +85 -0
  10. package/bundled-contracts/maggiedash/execution-board.json +4629 -1553
  11. package/bundled-contracts/maggiedash/stripe-booking-capabilities-v1.json +1 -0
  12. package/bundled-marketplace/README.md +17 -0
  13. package/bundled-marketplace/catalog.json +56 -7
  14. package/bundled-references/browser-inspection.md +25 -0
  15. package/bundled-references/maggiedash-booking/CURRENT-STATE.md +128 -10
  16. package/bundled-references/maggiedash-booking/EXECUTION-BOARD.json +4629 -1553
  17. package/bundled-references/maggiedash-booking/HOST-ADAPTER.md +5 -0
  18. package/bundled-references/maggiedash-booking/ORAWELLNESS-INTEGRATION-AUDIT.md +64 -21
  19. package/bundled-references/maggiedash-booking/PRD.md +9 -1
  20. package/bundled-references/maggiedash-booking/PROGRESS.md +244 -2399
  21. package/bundled-references/maggiedash-booking/QA-TEST-PLAN.md +37 -6
  22. package/bundled-references/maggiedash-booking/README.md +23 -6
  23. package/bundled-references/maggiedash-booking/RUNTIME-OPERATIONS.md +64 -8
  24. package/bundled-references/maggiedash-booking/SKILLS-AND-CLI.md +11 -2
  25. package/bundled-references/maggiedash-booking/STRIPE-INTEGRATION.md +66 -2
  26. package/bundled-references/maggiedash-booking/TASK-RUNBOOK.md +1 -1
  27. package/bundled-references/maggiedash-booking/TASKS.md +44 -3
  28. package/bundled-references/maggiedash-booking/VOUCHERS.md +47 -0
  29. package/bundled-references/memory-hook.md +18 -5
  30. package/bundled-references/provider-adapter-contract.md +33 -0
  31. package/bundled-skills/maggie-booking/SKILL.md +8 -0
  32. package/bundled-skills/maggie-clone-to-template/SKILL.md +26 -0
  33. package/bundled-skills/maggie-deployment/SKILL.md +59 -1
  34. package/bundled-skills/maggie-deployment/references/vps.md +41 -0
  35. package/bundled-skills/maggie-design/SKILL.md +99 -0
  36. package/bundled-skills/maggie-feedback/SKILL.md +41 -2
  37. package/bundled-skills/maggie-marketplace/SKILL.md +91 -0
  38. package/bundled-skills/maggie-memory/SKILL.md +10 -1
  39. package/bundled-skills/maggie-qa-workflow/SKILL.md +41 -1
  40. package/bundled-skills/maggie-service-booking/SKILL.md +23 -0
  41. package/bundled-skills/maggie-social-share/SKILL.md +37 -5
  42. package/bundled-skills/maggie-social-share/references/queue-and-connections.md +101 -0
  43. package/bundled-skills/maggie-template/SKILL.md +57 -3
  44. package/bundled-skills/maggie-template/references/template-content-v1.example.json +34 -0
  45. package/bundled-tools/clis/maggie_booking.py +199 -26
  46. package/bundled-tools/clis/maggie_booking_vouchers.py +185 -0
  47. package/bundled-tools/clis/maggie_clone_to_template.py +14 -0
  48. package/bundled-tools/clis/maggie_deployment.py +295 -0
  49. package/bundled-tools/clis/maggie_design.py +9 -0
  50. package/bundled-tools/clis/maggie_design_lint.py +277 -0
  51. package/bundled-tools/clis/maggie_feedback.py +107 -3
  52. package/bundled-tools/clis/maggie_marketplace.py +199 -5
  53. package/bundled-tools/clis/maggie_memory.py +10 -3
  54. package/bundled-tools/clis/maggie_palette.py +280 -0
  55. package/bundled-tools/clis/maggie_qa_workflow.py +156 -1
  56. package/bundled-tools/clis/maggie_social_queue.py +338 -0
  57. package/bundled-tools/clis/maggie_social_share.py +42 -9
  58. package/bundled-tools/clis/maggie_template_package.py +1141 -0
  59. package/bundled-tools/runtime/maggie_memory.py +17 -2
  60. package/package.json +1 -1
  61. package/references/browser-inspection.md +25 -0
  62. package/references/memory-hook.md +18 -5
  63. package/references/provider-adapter-contract.md +33 -0
@@ -150,6 +150,39 @@ image-processing contract: optimisation may use Cloudflare Images
150
150
  transformations, Astro build tooling or a provider-specific implementation
151
151
  behind the same interface.
152
152
 
153
+ ## OAuth connections
154
+
155
+ A provider connection is only as reliable as its weakest connect path:
156
+
157
+ - Each adapter declares one canonical OAuth scope set. Every client that
158
+ starts the flow (dashboard, mobile app, CLI) requests exactly that set.
159
+ LinkedIn invalidates a member's earlier tokens when a later sign-in asks for
160
+ a different scope set, so a mobile app that omits `email` silently revokes
161
+ the dashboard's token while the database still says `active`.
162
+ - Prefer one OAuth client per product. When a client ID is shared with other
163
+ products or callbacks, record it as `client_shared_with`; their sign-ins can
164
+ revoke this product's tokens unless they use the identical scope set.
165
+ - Treat stored connection status as a cache. A token that the provider has
166
+ revoked, or that the serving host cannot decrypt, is `needs_reconnect`
167
+ before anything is scheduled on it — not when a post fails.
168
+ - Provider media URLs (for example `media.licdn.com` with an `e=` expiry) are
169
+ signed and expire. Cache the bytes in owned storage or refresh on readback.
170
+
171
+ `maggie tool maggie_social_share.py adapters` and `connections` check these
172
+ rules from a redacted JSON manifest; see the Social Share skill for shapes.
173
+
174
+ ## Structured model output
175
+
176
+ Keep structured-output schemas small. Gemini rejected a JSON schema whose enum
177
+ had 125 values with `400 INVALID_ARGUMENT`, and the caller silently fell back
178
+ for every request. For a large vocabulary (styles, categories, catalogue IDs):
179
+
180
+ 1. ask for a free string (optionally with a short list of examples in the
181
+ prompt) instead of a large `enum`;
182
+ 2. validate the returned value server-side against the authoritative list;
183
+ 3. treat a schema rejection or an unknown value as a visible, counted failure —
184
+ never a silent fallback to a default.
185
+
153
186
  ## Adding a provider
154
187
 
155
188
  1. Implement the relevant interface in `src/lib/providers/`.
@@ -373,6 +373,14 @@ node scripts/maggie-booking-schema.mjs --apply --confirm
373
373
  node scripts/maggie-booking-worker.mjs --write --confirm
374
374
  ```
375
375
 
376
+ Before switching Stripe to live mode, follow the read-only live setup runbook
377
+ in `docs/maggiedash-booking/STRIPE-INTEGRATION.md`: verify with list/retrieve
378
+ calls only, never use a create call as a probe, have the owner install
379
+ webhook and event-destination signing secrets with a no-echo command, and hand
380
+ Dashboard-only steps to the owner. Gift vouchers follow the host-owned
381
+ `booking-voucher-lifecycle-v1.json` contract; validate a host ledger with
382
+ `maggie booking voucher-contract --ledger FIXTURE`.
383
+
376
384
  The dry-run executes the complete additive migration in a transaction and
377
385
  rolls it back, which verifies PostgreSQL permissions without changing data.
378
386
  The apply command commits the migration as one transaction.
@@ -67,6 +67,32 @@ then stores the prompt as
67
67
  `CUSTOMIZATION_PROMPT.md` beside the package. It creates a resumable job under
68
68
  `marketplace/.maggie/clone-to-template-jobs/`.
69
69
 
70
+ ### Neutral display identity
71
+
72
+ A package's customer-facing identity is separate from its source evidence.
73
+ `template.json` `name` and `id` are internal; `sourceMetadata` records the
74
+ source title only as provenance. Pass a designed, neutral style name and a short
75
+ description when planning:
76
+
77
+ ```bash
78
+ maggie tool maggie_clone_to_template.py plan <url> "<approved brief>" --rename <template-id> \
79
+ --display-name "Olive Atelier" \
80
+ --display-description "A light editorial beauty homepage with olive accents."
81
+ ```
82
+
83
+ Packaging forwards both to the marketplace importer. Without them, completion
84
+ derives a name from the measured design (accent hue, display typeface,
85
+ industry). The validator rejects a name that repeats a distinctive source-title
86
+ word, looks like a counter (`Beauty Studio 20 001`), or duplicates another
87
+ catalogue entry. Change it later with `maggie_marketplace.py identity <id>
88
+ --display-name …`. Template pickers must show `displayName` and
89
+ `displayDescription`, never the source business name.
90
+
91
+ Packaging also measures `DESIGN.md` from the rendered CSS, records
92
+ `screenshotReview`, and lists every asset with its provenance. Review captures
93
+ stay at viewport height; tile any full-page capture as described in the
94
+ `maggie-marketplace` package quality gates.
95
+
70
96
  If the full clone run fails or cannot reach `verified`, stop and report the
71
97
  clone checkpoint. Do not invoke the marketplace importer as a fallback. If the
72
98
  Maggie design review fails, stop before declaring the template ready.
@@ -2,7 +2,7 @@
2
2
  name: maggie-deployment
3
3
  description: Deploy and operate Maggie blog projects with Cloudflare Workers as the default target, while preserving an adapter boundary for VPS, GCP, and AWS.
4
4
  metadata:
5
- version: 1.4.0
5
+ version: 1.5.0
6
6
  ---
7
7
 
8
8
  # Maggie Deployment
@@ -219,6 +219,12 @@ files and the application remain separated (`maggie-deploy` versus
219
219
  Install and review that narrow sudoers policy on the host before executing a
220
220
  runner.
221
221
 
222
+ Generated release runners include their Maggie version and a template
223
+ fingerprint. VPS preflight checks runners under `.maggie/deployment/` and warns
224
+ when they are unmarked or stale; use `--check-runner PATH` for a runner stored
225
+ elsewhere. Regenerate from the reviewed VPS plan, inspect the diff, and replace
226
+ the checked-in runner only after review.
227
+
222
228
  VPS plans include a bounded retention policy: keep two immutable releases,
223
229
  preserve the `current` target and rollback target, and review prune candidates
224
230
  before any operator executes cleanup. Generate a read-only candidate report:
@@ -233,6 +239,58 @@ maggie tool maggie_deployment.py --retention-plan \
233
239
  The CLI never deletes release directories and never permits fewer than two
234
240
  retained releases.
235
241
 
242
+ ### Multi-host secret parity
243
+
244
+ When several hosts serve the same routes, check that each one holds every
245
+ required secret. The check compares key names and SHA-256 fingerprints and
246
+ never prints, stores, or transmits values:
247
+
248
+ ```bash
249
+ # Local env files (one per host):
250
+ maggie deployment secret-parity \
251
+ --host api-1=.secrets/api-1.env --host api-2=.secrets/api-2.env \
252
+ --required SOCIAL_SHARE_ENCRYPTION_KEY
253
+
254
+ # Or fingerprint manifests produced on each host:
255
+ maggie deployment secret-fingerprint --env-file /etc/example.env \
256
+ --host api-1 --output api-1.json
257
+ maggie deployment secret-parity --manifest api-1.json --manifest api-2.json \
258
+ --required SOCIAL_SHARE_ENCRYPTION_KEY
259
+ ```
260
+
261
+ A required key that is missing or differs on any host fails the check. Other
262
+ drifting keys are warnings unless `--strict` is set. A host without Maggie can
263
+ use the no-echo shell snippet in [the VPS reference](references/vps.md); the
264
+ parity command accepts its `KEY <sha256>` output directly. Manifests that
265
+ contain anything other than names and 64-character hex digests are rejected.
266
+
267
+ ### Local and production database isolation
268
+
269
+ ```bash
270
+ maggie deployment env-isolation --project . \
271
+ --production-env .env.production
272
+ # or: --production-db-host db.example.net
273
+ ```
274
+
275
+ The check fails when the local `.env` points at the production database (same
276
+ host, and port/name when known). The same server with a different database is
277
+ a warning. Deployment preflight runs the check automatically, as a non-blocking
278
+ warning, when `.env.production` exists or `MAGGIE_PRODUCTION_DB_HOST` is set.
279
+ Database URLs are reduced to host/port; credentials are never reported.
280
+
281
+ ### Release ordering for workers and notification templates
282
+
283
+ Deploy the worker and its templates before any code path can enqueue an event
284
+ that uses a new template. When local development or a staged app shares a
285
+ queue with production, an event that names a template the running worker does
286
+ not know yet must be held and retried, not dead-lettered: an unknown template
287
+ during a rollout is a release-ordering state, not a permanent failure. Check
288
+ that the outbox worker (MaggieDash Booking or the host's own) does not let
289
+ unknown-template deliveries consume the retry budget, and after the release
290
+ confirm the held deliveries were sent.
291
+ If dead-lettered rows already exist, requeue them only after the worker that
292
+ knows the template is live.
293
+
236
294
  Validate the database release separately before a VPS migration:
237
295
 
238
296
  ```bash
@@ -132,6 +132,47 @@ inspect → plan → backup/migrate → npm ci → npm run build
132
132
  Deploy staging first. A passing build does not prove Nginx, systemd, DNS, TLS,
133
133
  robots, sitemap, or private-route correctness.
134
134
 
135
+ ### Release retention
136
+
137
+ Keep exactly the `current` release plus one previous release as the rollback
138
+ target. Prune after every deploy, and only after the new release passed its
139
+ health checks: an unhealthy release must still have its predecessor on disk.
140
+ The generated release runner does this as its final step; it never removes the
141
+ release `current` points at or the release it replaced. Without pruning,
142
+ `releases/` grows by one full `node_modules` tree per deploy until the disk
143
+ fills. Use `--retention-plan` for a read-only list of prune candidates on hosts
144
+ whose runner predates this step, and review it before deleting anything.
145
+
146
+ ### Multi-host secret parity
147
+
148
+ When more than one host can serve the same routes (failover, load-balanced API
149
+ nodes, workers), every host must hold the same required secrets. A key that
150
+ exists on only one host is invisible until traffic fails over to another and
151
+ returns 5xx. Compare hosts by name and SHA-256 fingerprint, never by value:
152
+
153
+ ```bash
154
+ # On each host (prints names and digests only; values are never echoed):
155
+ for k in SOCIAL_SHARE_ENCRYPTION_KEY DATABASE_URL; do
156
+ v=$(sed -n "s/^$k=//p" /etc/example.env | head -1)
157
+ printf '%s %s\n' "$k" "$(printf %s "$v" | sha256sum | cut -c1-64)"
158
+ done > /tmp/api-1.fingerprints
159
+
160
+ # Locally, after copying each host's fingerprint file:
161
+ maggie deployment secret-parity \
162
+ --manifest api-1.fingerprints --manifest api-2.fingerprints \
163
+ --manifest api-3.fingerprints \
164
+ --required SOCIAL_SHARE_ENCRYPTION_KEY --required DATABASE_URL
165
+ ```
166
+
167
+ Run it after adding a secret and before enabling a host in a pool.
168
+
169
+ ### Environment isolation
170
+
171
+ A local `.env` must never point at the production database. Shared databases
172
+ let local test records (vouchers, palettes, emails) appear on live pages and be
173
+ picked up by production workers. `maggie deployment env-isolation` fails when
174
+ the local database host, port, and name match production.
175
+
135
176
  ## Verification and rollback
136
177
 
137
178
  Verify the homepage, changed service routes, `/robots.txt`, `/sitemap.xml`,
@@ -285,6 +285,57 @@ all required camera states, and valid PNGs at 390px, 768px, and desktop
285
285
  widths. The machine-readable contract is
286
286
  [mobile-app-surface-v1.schema.json](../../bundled-contracts/maggie-design/mobile-app-surface-v1.schema.json).
287
287
 
288
+ ### Onboarding wizards
289
+
290
+ Use one pattern for multi-step setup (brand, logo, voice, posting hours, and
291
+ similar first-run flows) instead of designing each flow ad hoc:
292
+
293
+ - A segmented progress bar with one segment per step; the current step is
294
+ visibly distinct and completed steps are tappable.
295
+ - Each step shows Maggie (or the product guide) with exactly one headline and,
296
+ at most, one supporting line. Put help in the control, not in paragraphs.
297
+ - Record step state on the server (`pending`, `done`, `skipped`) after every
298
+ step, and resume from the first unfinished step on any device. Local state
299
+ alone loses progress on reinstall or a second device.
300
+ - Every optional step offers **Later**. A skipped step reopens on the next
301
+ sign-in until it is done or explicitly dismissed; never block the app on it.
302
+ - Completed steps keep a redo action (for example "Retrain voice" or
303
+ "Choose another logo") that reopens that step with the saved value
304
+ preselected, without restarting the wizard.
305
+ - The primary action stays in the fixed footer; Back never discards saved
306
+ server state.
307
+
308
+ ### Pickers with previews
309
+
310
+ For choices that need to be seen (logo styles, templates, palettes, voices):
311
+
312
+ - The list sheet shows a thumbnail, name, and selection state per row; the
313
+ row itself selects, and a separate preview control opens a larger view.
314
+ - The large preview opens as a sheet nested in the list sheet, so dismissing
315
+ it returns to the same scroll position in the list. It offers **Use this**
316
+ and close; it never replaces the list route.
317
+ - Thumbnails are generated or cached assets, not live renders of every option.
318
+
319
+ ### React Native Web pressables
320
+
321
+ React Native Web renders `Pressable` and the `Touchable*` family as button-like
322
+ DOM elements. A chip with a nested remove control becomes `<button>` inside
323
+ `<button>`: the DOM is invalid, browsers repair it differently, and taps land
324
+ on the wrong control (for example, removing a tag opens its preview). Render
325
+ the chip body and its remove control as **sibling** pressables inside a plain
326
+ `View`, each with its own accessible label. The same rule applies to `<a>`
327
+ and `<button>` on the web.
328
+
329
+ Run the static check before browser QA; it scans `.tsx`/`.jsx`, skips build
330
+ and dependency folders, and treats `asChild` wrappers (such as an expo-router
331
+ `Link`) as a pass-through:
332
+
333
+ maggie design pressable-check --project . [--pressable Chip --pressable IconButton]
334
+
335
+ Pass `--pressable` for project components that render a pressable. A rare,
336
+ reviewed exception can carry `maggie-allow-nested-pressable` in a comment on
337
+ the inner element's line.
338
+
288
339
  ## Explicit homepage rebrand mode
289
340
 
290
341
  The homepage `review` mode only compares screenshots. It does not rebrand a
@@ -543,6 +594,54 @@ collapsed-rail, mobile-drawer, and modal evidence. Sample plans require
543
594
  noindex, sitemap exclusion, a visible sample banner, placeholders, and a
544
595
  finish checklist.
545
596
 
597
+ ### Tailwind v4 cascade layers
598
+
599
+ Tailwind v4 emits utilities inside `@layer utilities`. An unlayered rule beats
600
+ every layered rule regardless of specificity, so an unlayered
601
+ `h1, h2, h3 { font-family: … }` silently defeats template `font-*` utilities,
602
+ and an unlayered icon runtime rule such as `.ph { display: inline-block }`
603
+ defeats `hidden` and `group-open:inline` (a mobile menu then shows both the
604
+ open and close icons). Static class checks pass; only a browser shows it.
605
+
606
+ - Put app-wide element rules (headings, links, body copy) in `@layer base`.
607
+ - Put icon-font runtime rules and component classes in `@layer components`,
608
+ or import the icon stylesheet with `@import "./icons.css" layer(components);`.
609
+ - Keep `@theme`, `@utility`, and `@font-face` as they are; they are not
610
+ competing rules.
611
+
612
+ Run the static check whenever CSS or the icon package changes:
613
+
614
+ maggie design layer-check --project .
615
+
616
+ It runs only when an `@import "tailwindcss"` entry exists (or with
617
+ `--tailwind-v4`), honours `@layer` blocks and `layer(...)` imports, and fails on
618
+ unlayered element or icon rules that set utility-competing properties.
619
+ Unlayered `html`/`body` rules and class rules that set `display` are reported
620
+ as warnings. Keep `css-cascade-check` for the rendered-browser proof.
621
+
622
+ ### Palette role contract
623
+
624
+ A template that offers brand colour choices exposes semantic roles instead of
625
+ raw hex values in markup: `canvas`, `panel`, `soft`, `text`, `accent`,
626
+ `accentText`, `onAccent`, `dark`, and `deep`. Bind them to CSS variables (for
627
+ example `--color-canvas`) so a palette swap never edits markup. The generator
628
+ keeps the signature palette and derives named variants by moving hue while
629
+ keeping lightness; neutrals never gain chroma, accent saturation is capped
630
+ (uncapped variants turn garish), `accentText` is forced to 4.5:1 on canvas,
631
+ and `onAccent` is the most legible of white, deep, text, and canvas:
632
+
633
+ maggie design palette generate --template <template-id> \
634
+ --canvas '#F7F3EE' --text '#1F1B16' --accent '#B5651D' \
635
+ [--roles roles.json] [--count 17] [--max-saturation 0.65] \
636
+ --output design/palettes.json
637
+ maggie design palette validate --palette design/palettes.json
638
+
639
+ Measure the signature roles from the template's rendered CSS, not from a
640
+ reference palette. Generation stops if the signature itself fails the
641
+ contrast rules; fix the signature rather than lowering the threshold. The
642
+ contract is
643
+ [palette-roles-v1.schema.json](../../bundled-contracts/maggie-design/palette-roles-v1.schema.json).
644
+
546
645
  For generated or converted pages, run the markup gate before handing the page
547
646
  to a host editor:
548
647
 
@@ -2,7 +2,7 @@
2
2
  name: maggie-feedback
3
3
  description: Collect, review, and explicitly submit privacy-safe feedback about a Maggie skill run, workflow result, bug, or feature request.
4
4
  metadata:
5
- version: 1.1.0
5
+ version: 1.2.0
6
6
  ---
7
7
 
8
8
  # Maggie Feedback
@@ -30,7 +30,9 @@ maggie feedback --project . collect \
30
30
  maggie feedback preview .maggie/feedback/<feedback-id>.json --format markdown
31
31
  ```
32
32
 
33
- The draft is written to `.maggie/feedback/`. It contains the Maggie version,
33
+ The draft is written to `.maggie/feedback/`. List local drafts with
34
+ `maggie feedback list --project .`; `--project` works before or after the
35
+ subcommand. A draft contains the Maggie version,
34
36
  skill, run ID, phase, error fingerprint, expected/actual result, reproduction
35
37
  steps, resolution, validation, and metadata-only screenshot references.
36
38
 
@@ -116,6 +118,43 @@ Example:
116
118
  ]
117
119
  }
118
120
 
121
+ ## Feedback types
122
+
123
+ - `bug`: the skill or CLI did something wrong.
124
+ - `quality`: the result works but falls short (unclear output, weak defaults).
125
+ - `feature`: a missing capability.
126
+ - `improvement`: a concrete proposal to change an existing skill or CLI
127
+ (a new flag, a better default, a guidance section).
128
+ - `general`: anything else.
129
+
130
+ The hosted endpoint accepts `bug`, `feature`, `quality`, and `general`. An
131
+ `improvement` draft keeps its type locally and is submitted as `feature` with
132
+ `subtype: "improvement"`, so maintainers can still filter it.
133
+
134
+ ## Draft a batch from a working session
135
+
136
+ After a long session, draft batch items from the commits made since a known
137
+ point instead of writing them by hand:
138
+
139
+ ```bash
140
+ maggie feedback session-summary --project . \
141
+ --repo . --since v1.4.0 \
142
+ --batch-id social-session-2026-10 --skill maggie-social-share
143
+ ```
144
+
145
+ The helper reads commit subjects only (no diffs, paths, or file contents) and
146
+ redacts secrets and local paths. `fix:` commits become fixed `bug` items with a
147
+ `commit:<sha>` evidence reference; `feat:`, `perf:` and `refactor:` commits
148
+ become `improvement` candidates; other commits are skipped and counted. It also
149
+ adds one placeholder for an open ask. It writes a draft batch file under
150
+ `.maggie/feedback/batches/` and does not create or submit feedback.
151
+
152
+ Review the file: delete items that concern the project rather than a Maggie
153
+ skill or CLI, and replace every `REVIEW:` field (expected, actual, validation).
154
+ `maggie feedback batch` rejects a file that still contains `REVIEW:`
155
+ placeholders. Then continue with `batch`, `batch-review`, and explicit
156
+ `submit` as usual.
157
+
119
158
  ## Submit explicitly
120
159
 
121
160
  The CLI never submits automatically. After reviewing the draft:
@@ -52,6 +52,18 @@ maggie tool maggie_marketplace.py apply \
52
52
  --id medical-spa-landing-30 --project /path/to/astro-project
53
53
  ```
54
54
 
55
+ Package-quality commands (read-only unless `--write`/`--record`/`--approve`):
56
+
57
+ ```bash
58
+ maggie tool maggie_marketplace.py audit-package <id> # all package-quality gates, JSON report
59
+ maggie tool maggie_marketplace.py measure-design <id> --write # palette roles + fonts from homepage CSS
60
+ maggie tool maggie_marketplace.py repair-assets <id> --write # list unlisted assets honestly; add file extensions
61
+ maggie tool maggie_marketplace.py identity <id> --display-name "Olive Atelier" \
62
+ --display-description "A light editorial beauty homepage with olive accents."
63
+ maggie tool maggie_marketplace.py image-plan <id> --unit-cost 0.04 --currency USD
64
+ maggie tool maggie_marketplace.py image-review <id> [--approve --reviewer NAME | --flag assets/x.png]
65
+ ```
66
+
55
67
  The native installer exposes the same operation as
56
68
  `maggie marketplace add <template-url> clone <preview-url> --rename <id>`.
57
69
 
@@ -95,6 +107,55 @@ validator before it is reported complete. If the validator has changed or the
95
107
  artifact drifted, the job becomes `STALE` and must be resumed or rebuilt; do
96
108
  not treat an old readiness flag as proof of current validity.
97
109
 
110
+ ## Package quality gates
111
+
112
+ `validate` and the completion checkpoint include five package-quality gates.
113
+ `audit-package` runs only these, without the mutating cleanup that `validate`
114
+ performs, so it is safe on any checkout.
115
+
116
+ 1. **Screenshots decode and fit a pixel budget.** Every file in
117
+ `screenshots/` must fully decode (PNG chunk CRCs and inflated size, JPEG
118
+ frame/end markers, WebP header; Pillow is used too when installed). A
119
+ corrupt capture shows as glitch noise and is reported as
120
+ `recapture-required`; recapture it with `maggie_clone_to_template.py
121
+ review` — never hand-edit or keep it. The budget is 40 MP per image and
122
+ 16383 px per edge, well under sharp's default `limitInputPixels`
123
+ (268,402,689 px) and Pillow's decompression-bomb guard, so consumers never
124
+ need to disable those limits. Ship full-page captures as tiles no taller
125
+ than 4096 px (`desktop-full-01.png`, `desktop-full-02.png`, …) or as a
126
+ compressed WebP preview; keep `desktop.png`/`tablet.png`/`mobile.png` at
127
+ viewport height. `audit-package --record` stores the per-file result in
128
+ `template.json` `screenshotReview`.
129
+ 2. **`DESIGN.md` palette is measured, not inherited.** The palette and fonts
130
+ come from the template's own CSS: Tailwind config colours and fonts,
131
+ arbitrary utilities (`bg-[#…]`), the Tailwind neutral scales, body rules,
132
+ inline and stylesheet declarations, and Google Fonts links.
133
+ `measure-design --write` rewrites the `### Reference palette` and
134
+ typography lines, stores `designTokens` (the nine
135
+ `maggie-palette-roles-v1` roles plus fonts and missing font links) in
136
+ `template.json`, and fills empty `styleTags` with measured tags
137
+ (`light-canvas`, `serif-display`, `warm-neutral`, …). Every declared colour
138
+ must exist in the page CSS and Background/Text primary must match the
139
+ measured canvas/text; derived contrast-safe roles are labelled `derived`.
140
+ Check the result against the screenshots before overriding anything.
141
+ 3. **Every asset has provenance.** Every image under `assets/` must be listed
142
+ in `generated-asset-manifest.json` with a provider and role. Captured
143
+ source images are listed as `provider: captured-source`, `reuse: false`,
144
+ `replacementRequired: true`; files without a generation record are
145
+ `provider: unrecorded`, `reuse: false`, `provenanceReview: required`. Both
146
+ block publishing. Files without an extension are rejected;
147
+ `repair-assets --write` sniffs the type, renames the file, and rewrites
148
+ `homepage.html` and `image-inventory.json`.
149
+ 4. **Neutral display identity.** `template.json` carries a customer-facing
150
+ `displayName` and `displayDescription` that are separate from the ID,
151
+ `name`, and `sourceMetadata`. The name must not repeat a distinctive word
152
+ from the source title, must not be a counter such as `Beauty Studio 20
153
+ 001`, and must be unique in the catalogue. Completion derives one from the
154
+ measured design (accent hue, display typeface, industry) when none is
155
+ given; prefer a reviewed, designed name. `list`, `suggest`, and the catalogue
156
+ show `displayName`; source titles never appear in customer-facing pickers.
157
+ 5. **Generated images pass a no-text review.** See step 4 below.
158
+
98
159
  Each import also creates `tasks.json`. It is the workflow ledger: it stores
99
160
  source/output inventories for logos, icons, images, headings, links, buttons,
100
161
  visible copy, and Tailwind, plus evidence and status for source analysis,
@@ -222,6 +283,32 @@ role, provider, date, and prompt in `generated-asset-manifest.json`. Validate
222
283
  that every PNG/JPEG decodes. Never apply text replacement tools to binary
223
284
  assets.
224
285
 
286
+ Report cost before and after every generation run, and review every output
287
+ for text. A "no text, no labels" prompt is not a guarantee: product bottles,
288
+ signage, and packaging routinely come back with readable words.
289
+
290
+ ```bash
291
+ # before generating: planned image count and estimated cost
292
+ maggie tool maggie_marketplace.py image-plan <id> --unit-cost <price-per-image> --currency USD
293
+ # after generating: actual count/cost, contact sheet, and text review
294
+ maggie tool maggie_marketplace.py image-review <id>
295
+ # a person checked image-review/contact-sheet.html and found no text
296
+ maggie tool maggie_marketplace.py image-review <id> --approve --reviewer <name>
297
+ # or record a failure, regenerate that asset, and review again
298
+ maggie tool maggie_marketplace.py image-review <id> --flag assets/maggie-hero.png
299
+ ```
300
+
301
+ `image-plan` counts inventory occurrences marked `needs-generation`, pending
302
+ roles, and captured-source assets awaiting replacement. Take the unit cost from
303
+ the provider's current price list; when omitted, the estimate is recorded as
304
+ unknown rather than guessed. `image-review` writes the post-run count and cost,
305
+ `image-review/contact-sheet.html`, and a per-image `textReview` in
306
+ `image-generation-report.json`. When `tesseract` is installed, OCR flags any
307
+ image with readable words; otherwise the review stays `pending-human-review`
308
+ until `--approve`. Completion and `validate` block until the review is
309
+ `passed` and covers every generated asset. These commands make no model or
310
+ paid API calls themselves.
311
+
225
312
  Before generating anything, create `image-inventory.json` from the final
226
313
  section structure. Include one record for every logo and image occurrence:
227
314
  `id`, source occurrence/line, semantic role, composition, dimensions/aspect
@@ -315,6 +402,10 @@ image references. It also verifies the generated asset roles used by the
315
402
  sample. A mismatch blocks `apply` and publish until the template is repaired
316
403
  or an explicitly approved `--sample` contract is selected.
317
404
 
405
+ The validator also runs the package quality gates above (screenshot
406
+ integrity and budget, measured palette, asset provenance, neutral display
407
+ identity, generated-image text review).
408
+
318
409
  Also parse all JSON and JSON-LD, require exactly one canonical, verify `en-GB`,
319
410
  decode every local image, scan for source brand/person/place/phone/social URL
320
411
  remnants, confirm no Iconify/platform runtime remains, and inspect desktop,
@@ -29,7 +29,7 @@ truth, content state, or audit log.
29
29
 
30
30
  ## Workflow
31
31
 
32
- 1. At the start of a relevant workflow, run `maggie memory context --project . --skill <skill>` and load only matching active items.
32
+ 1. At the start of a relevant workflow, run `maggie memory context --project . --skill <skill>` and load only matching active project-scope items. Use `--include-shared` only after explicit opt-in.
33
33
  2. Show material preferences, conventions, and prevention lessons before making a decision.
34
34
  3. When the user gives a durable preference or confirms a repaired pitfall, save it explicitly as `candidate` or `active` with scope and evidence.
35
35
  4. Record every meaningful failure with `record-error`; include a stable fingerprint, resolution, and validation result when fixed.
@@ -45,6 +45,15 @@ truth, content state, or audit log.
45
45
  preserving project scope. Expired active items remain inspectable through
46
46
  explicit status listing but are excluded from normal context.
47
47
 
48
+ Project-scope `maggie init` creates the repository's `.maggie/memory/` store.
49
+ Repeated initialization preserves existing memory files without rewriting
50
+ their contents or timestamps. A context response distinguishes a ready store
51
+ from an uninitialized project; the shared memory hook falls back to the
52
+ installed CLI when local Python tools are absent.
53
+
54
+ Project `context`, `search`, and `list` read only project-scope items by
55
+ default. `--include-shared` explicitly opts into user/workspace-scoped entries.
56
+
48
57
  ```bash
49
58
  maggie memory init --project .
50
59
  maggie memory context --project . --skill maggie-clone
@@ -2,7 +2,7 @@
2
2
  name: maggie-qa-workflow
3
3
  description: Run scenario-based browser QA with explicit evidence, fix/retest lifecycle, and release-gate decisions for web projects.
4
4
  metadata:
5
- version: 1.2.0
5
+ version: 1.3.0
6
6
  ---
7
7
 
8
8
  # Maggie QA Workflow
@@ -74,6 +74,46 @@ the host browser adapter. The adapter owns console, network, authentication,
74
74
  URL, viewport, and screenshot capture; this skill stores only a relative path,
75
75
  URL reference, and hash when a local file exists.
76
76
 
77
+ ## Protect production data
78
+
79
+ Declare which API the build under test talks to, and mark scenarios that
80
+ write data with `"mutates": true` in the scenario manifest:
81
+
82
+ ```bash
83
+ maggie qa start --project . --run-id local-qa-002 \
84
+ --environment local --base-url http://localhost:4321 \
85
+ --api-base https://api.example.com \
86
+ --production-api https://api.example.com
87
+ ```
88
+
89
+ When the API base is a production API, mutating scenarios start as `blocked`
90
+ and `record` refuses a pass or fail result for them. Run those scenarios
91
+ against a non-production API, or start a run with `--allow-production-writes`
92
+ only after the user explicitly consents and a restore path exists. Overriding
93
+ `window.fetch` from the page does not stop a bundled API client from sending
94
+ requests; use network-layer interception as described in the
95
+ [browser inspection contract](../../references/browser-inspection.md).
96
+
97
+ ## Check CORS for every method the client uses
98
+
99
+ Before a release that adds or changes API calls from a browser or webview,
100
+ preflight every HTTP method the client sends through the public edge, not only
101
+ the origin server:
102
+
103
+ ```bash
104
+ maggie qa cors-preflight --project . \
105
+ --url https://api.example.com/v1/setup \
106
+ --origin https://app.example.com \
107
+ --method GET,POST,PUT,PATCH,DELETE \
108
+ --request-header content-type,authorization \
109
+ --output .maggie/qa-runs/cors-preflight.json
110
+ ```
111
+
112
+ The command sends only `OPTIONS` requests and fails when a method, origin, or
113
+ request header is not allowed. A method missing from the edge allow-list
114
+ fails in the browser with a generic network error (Safari: "Load failed") and
115
+ leaves no request in server logs, so it is easy to misdiagnose.
116
+
77
117
  ## Assert the requirement at runtime
78
118
 
79
119
  Do not use a source class, edited markup fragment, or implementation detail as
@@ -427,6 +427,29 @@ FAQ helper from the first category implementation; it is a known gap and must
427
427
  remain marked incomplete until each FAQ record is independently AI-authored and
428
428
  reviewed.
429
429
 
430
+ ## Payments: Stripe live setup and gift vouchers
431
+
432
+ Service pages often lead to first-party payments. When the host takes money
433
+ through MaggieDash Booking (rather than the external provider), follow the
434
+ read-only live setup runbook in `docs/maggiedash-booking/STRIPE-INTEGRATION.md`:
435
+
436
+ - verify live state with list/retrieve (`GET`) calls only; never use a create
437
+ call as a probe — a probe expected to fail can create a real live object;
438
+ - the owner installs webhook and Connect event-destination signing secrets
439
+ with a no-echo command (`read -rs … | <secret store>`); the agent never sees
440
+ them;
441
+ - thin-event destination signing secrets cannot be retrieved via the API;
442
+ roll them in the Dashboard if they were not captured;
443
+ - the Stripe Dashboard may be unusable under browser automation, so hand
444
+ Dashboard-only steps to the owner and confirm them with read-only calls.
445
+
446
+ Gift vouchers (online and at the till, partial redemption, undo, void, expiry,
447
+ refunds, buyer/recipient emails, merchant ledger) follow the host-owned
448
+ `contracts/maggiedash/booking-voucher-lifecycle-v1.json` contract described in
449
+ `docs/maggiedash-booking/VOUCHERS.md`. Do not invent a separate voucher model;
450
+ replay the host's sanitized ledger with
451
+ `maggie booking voucher-contract --ledger FIXTURE`.
452
+
430
453
  ## Gates
431
454
 
432
455
  The workflow stops when any gate fails: