@topy-ai/maggie 0.7.49 → 0.7.51

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 (33) hide show
  1. package/README-zh-TW.md +3 -3
  2. package/README.md +58 -8
  3. package/bin/maggie.js +33 -14
  4. package/bundled-contracts/maggie-assistant-tools/tool-registry-example-v1.json +19 -0
  5. package/bundled-contracts/maggie-assistant-tools/tool-registry-v1.schema.json +50 -0
  6. package/bundled-contracts/maggie-deployment/bridge-host-example-v1.json +29 -0
  7. package/bundled-contracts/maggie-design/mobile-app-evidence-v1.schema.json +54 -0
  8. package/bundled-contracts/maggie-design/mobile-app-surface-v1.schema.json +137 -16
  9. package/bundled-skills/catalog.json +8 -0
  10. package/bundled-skills/maggie-assistant-tools/SKILL.md +93 -0
  11. package/bundled-skills/maggie-assistant-tools/references/approvals-and-audit.md +54 -0
  12. package/bundled-skills/maggie-assistant-tools/references/bridge-host.md +56 -0
  13. package/bundled-skills/maggie-assistant-tools/references/product-release.md +57 -0
  14. package/bundled-skills/maggie-deployment/SKILL.md +13 -0
  15. package/bundled-skills/maggie-design/SKILL.md +55 -21
  16. package/bundled-skills/maggie-design/references/app-ui-patterns.md +66 -0
  17. package/bundled-skills/maggie-feedback/SKILL.md +20 -3
  18. package/bundled-skills/maggie-marketplace/SKILL.md +28 -0
  19. package/bundled-skills/maggie-mobile-app/SKILL.md +122 -0
  20. package/bundled-skills/maggie-qa-workflow/SKILL.md +30 -0
  21. package/bundled-tools/clis/maggie_app_collect.py +236 -0
  22. package/bundled-tools/clis/maggie_assistant_tools.py +302 -0
  23. package/bundled-tools/clis/maggie_bridge_host.py +212 -0
  24. package/bundled-tools/clis/maggie_design.py +190 -29
  25. package/bundled-tools/clis/maggie_feedback.py +89 -37
  26. package/bundled-tools/clis/maggie_mobile.py +221 -0
  27. package/bundled-tools/clis/maggie_product_release.py +303 -0
  28. package/bundled-tools/clis/maggie_qa_app_preflight.py +248 -0
  29. package/bundled-tools/clis/maggie_qa_workflow.py +5 -0
  30. package/bundled-tools/clis/maggie_skill_catalog.py +262 -0
  31. package/bundled-tools/runtime/assistant_approval.py +111 -0
  32. package/bundled-tools/runtime/cdp_client.py +246 -0
  33. package/package.json +1 -1
@@ -2,6 +2,10 @@
2
2
  "schemaVersion": "maggie-skill-catalog.v1",
3
3
  "generatedFrom": "skills/*/SKILL.md",
4
4
  "skills": [
5
+ {
6
+ "name": "maggie-assistant-tools",
7
+ "description": "Build an AI assistant's tools once and expose them safely to an in-app agent, an MCP server and ChatGPT/Claude apps. Use for tool registries, risk levels and gates, approval cards with signed one-time tokens, audit logs, MCP annotations, user-facing capability pages, publishing product CLI/MCP packages and app reviews, and multi-tenant assistant bridge hosts."
8
+ },
5
9
  {
6
10
  "name": "maggie-auth-reference",
7
11
  "description": "Generate and validate a provider-neutral traditional email/password auth reference with secure server sessions and production security gates."
@@ -54,6 +58,10 @@
54
58
  "name": "maggie-memory",
55
59
  "description": "Persist and retrieve confirmed user preferences, project conventions, lessons from repaired mistakes, and structured error history across Maggie skill runs."
56
60
  },
61
+ {
62
+ "name": "maggie-mobile-app",
63
+ "description": "Ship a cross-platform product app from one Expo / React Native codebase to web, iOS and Android. Use for the dev server, web deploy, EAS build profiles, TestFlight and Play internal testing, EAS Update channels and runtime versions, store-review rules, and a release preflight with a cost notice before every build."
64
+ },
57
65
  {
58
66
  "name": "maggie-ops",
59
67
  "description": "Build, connect, operate, upgrade, and verify a private Maggie Ops dashboard for blog content, API Pull, sitemap matching, rewrite approvals, reports, and integrations. Use when the user asks for Ops/admin functionality or lifecycle operations rather than public blog pages."
@@ -0,0 +1,93 @@
1
+ ---
2
+ name: maggie-assistant-tools
3
+ description: Build an AI assistant's tools once and expose them safely to an in-app agent, an MCP server and ChatGPT/Claude apps. Use for tool registries, risk levels and gates, approval cards with signed one-time tokens, audit logs, MCP annotations, user-facing capability pages, publishing product CLI/MCP packages and app reviews, and multi-tenant assistant bridge hosts.
4
+ metadata:
5
+ version: 1.0.0
6
+ ---
7
+
8
+ # Maggie Assistant Tools
9
+
10
+ ## Automatic memory hook
11
+
12
+ Follow [Maggie Memory Hook](../../references/memory-hook.md) at invocation and completion.
13
+
14
+ Use the shared [Maggie decision loop](../../references/decision-loop.md) before changing risk levels, publishing a package, or submitting an app for review.
15
+
16
+ ## One registry, many surfaces
17
+
18
+ Define every tool once in product code and export it as
19
+ `maggie-assistant-tool-registry.v1` JSON
20
+ ([schema](../../bundled-contracts/maggie-assistant-tools/tool-registry-v1.schema.json),
21
+ [example](../../bundled-contracts/maggie-assistant-tools/tool-registry-example-v1.json)).
22
+ The in-app agent, the MCP server, ChatGPT/Claude apps and the capability page
23
+ all read that one definition. Per tool:
24
+
25
+ | Field | Meaning |
26
+ |---|---|
27
+ | `name` | snake_case, stable; model-facing only |
28
+ | `description` | model-facing; never shown to people |
29
+ | `user.label` / `user.detail` | what people see (≤ 60 characters / one line) |
30
+ | `user.confirm` | the approval-card sentence; required for every write |
31
+ | `risk` | `read`, `write-reversible`, `write-spends` (credits, quota, AI generation), `write-public` (public or hard to undo), `never` (the assistant must not do it) — `R0`…`W4` are accepted aliases |
32
+ | `gates` | declared preconditions, e.g. `verified-site`, `credits`, `ai-generation` |
33
+ | `scope` | `account` or `workspace`; account writes are audited at account scope |
34
+ | `channels` | `in-app`, `mcp`, `chatgpt`, `claude`, `cli` |
35
+
36
+ Write user copy by hand. Rewriting model descriptions with regexes ("the
37
+ user" → "you", dropping `(from connected_apps_list)`) needs overrides for a
38
+ large share of tools and drifts. The validator rejects user copy that
39
+ contains snake_case names, "the user", or "(from tool)" references.
40
+
41
+ ```bash
42
+ maggie assistant registry-validate --registry tools.registry.json
43
+ maggie assistant annotations --registry tools.registry.json --mcp-tools tools-list.json
44
+ maggie assistant capability-page --registry tools.registry.json --output docs/assistant-can-do.md
45
+ ```
46
+
47
+ `annotations` derives MCP hints from risk — `readOnlyHint` for `read`,
48
+ `destructiveHint` for `write-public`/`never` and destructive-sounding names
49
+ (`*_delete`, `*_remove`, `*_revoke`, `*_discard`, as app reviewers expect),
50
+ `idempotentHint` for reads and declared idempotent writes, `openWorldHint` for
51
+ public writes — and reports drift against an exported `tools/list`. `never`
52
+ tools are not served on MCP; list them on the capability page instead.
53
+
54
+ `capability-page` groups tools into "looks things up", "changes things after
55
+ you approve" and "publishes or is hard to undo", plus a "can't do" section
56
+ from `cantDo` entries and `never` tools, using only user copy.
57
+
58
+ ## Approvals and audit
59
+
60
+ Read [approvals and audit](references/approvals-and-audit.md) before
61
+ implementing writes. In short: a write runs only with a signed, short-lived,
62
+ single-use approval bound to the exact calls, caller and scope; the token is
63
+ stored with the model turn on the server so a client answering only yes/no
64
+ works; every write produces one audit entry with a readable summary.
65
+
66
+ ```bash
67
+ maggie assistant approval-selftest
68
+ maggie assistant audit-check --registry tools.registry.json --session recorded-session.json
69
+ ```
70
+
71
+ ## Publishing product CLIs and MCP servers
72
+
73
+ See [product release](references/product-release.md):
74
+
75
+ ```bash
76
+ maggie product release-check --package apps/cli --server-json apps/cli/server.json --changelog apps/cli/CHANGELOG.md --pack
77
+ maggie product smoke --package apps/cli
78
+ maggie product mcp-check --mcp-url https://mcp.example.com/mcp
79
+ maggie product review-status --reviews reviews.json --chatgpt-plugin apps/mcp/chatgpt-plugin/plugin.json
80
+ ```
81
+
82
+ ## Hosting many users' assistant sessions
83
+
84
+ See [bridge host](references/bridge-host.md) and
85
+ `maggie deployment bridge-plan|bridge-collect-script|bridge-check`.
86
+
87
+ ## Hard boundaries
88
+
89
+ - Never let the model see or choose an approval token; never accept a write
90
+ without one.
91
+ - Never expose `never` tools or billing changes on MCP or third-party apps.
92
+ - Never publish a package or submit an app for review without an explicit
93
+ yes; these commands only check.
@@ -0,0 +1,54 @@
1
+ # Approvals and audit for assistant writes
2
+
3
+ ## Approval token
4
+
5
+ Reference implementation: `tools/runtime/assistant_approval.py` (exercised by
6
+ `maggie assistant approval-selftest`).
7
+
8
+ - Payload: `{id, calls: [{name, args}], principal, scope, expires}`.
9
+ `principal` is a hash of the caller identity (API key or user), never the
10
+ raw key. `scope` is `account` or the workspace/site ID.
11
+ - Token: `base64url(canonical JSON) + "." + base64url(HMAC-SHA256)`, TTL
12
+ about 10 minutes, secret held by the server only.
13
+ - Verify signature, expiry, principal, scope and the exact canonical calls.
14
+ If the model changes an argument after approval, the call is refused.
15
+ - Single use is enforced on the server: delete the token when it is used.
16
+ - Every write gets `Idempotency-Key = sha256(approvalId:canonical call)[:48]`,
17
+ so a retried request cannot run twice.
18
+
19
+ ### Where the token lives
20
+
21
+ **In-app agent.** When the model proposes a write, the server emits an
22
+ approval card (`{actions: [{tool, summary, risk}], token}`) and stores the
23
+ token with that model turn in conversation history, stripped from what the
24
+ model sees. The client answers yes/no. On yes, the server uses the stored
25
+ token (or one the client echoes) and deletes it. A client that returns only
26
+ `{approved: true}` must work: expecting the client to send the token back made
27
+ every approval look "expired".
28
+
29
+ **MCP / ChatGPT / Claude apps.** Two calls: the first (without `confirm`)
30
+ returns `{status: "needs_confirmation", preview, confirmation}`; the second
31
+ repeats the call with `confirm: true` and the `confirmation` token. A client
32
+ that may only preview (for example a bridge running on behalf of another
33
+ product) is refused on the second call.
34
+
35
+ ## Audit entry
36
+
37
+ One entry per write, written by the server after the call:
38
+
39
+ ```json
40
+ {"scope": "account | <workspace id>", "channel": "app | mcp | chatgpt | claude | cli",
41
+ "actions": [{"tool": "post_schedule", "summary": "Scheduled a post for Monday 9:00",
42
+ "ok": true, "error": null, "actionId": "<approval id>"}]}
43
+ ```
44
+
45
+ - `summary` is readable: when the model gives no title, fall back to the
46
+ tool's `user.label` plus the object's name — never a bare UUID.
47
+ - Account-level writes (add a website, invite a teammate) are audited at
48
+ account scope, or under the object they created, not under whichever site
49
+ was open.
50
+ - Failed calls are audited with `ok: false` and a short error.
51
+
52
+ `maggie assistant audit-check` replays a recorded session
53
+ (`{calls: [{tool, workspace, actionId, ok}], audit: [...]}`) against the
54
+ registry and fails on missing, duplicate, unreadable or mis-scoped entries.
@@ -0,0 +1,56 @@
1
+ # Multi-tenant assistant bridge host
2
+
3
+ A bridge host runs many users' assistant sessions (an assistant CLI plus its
4
+ MCP servers and skills) in one container on a VPS, behind a reverse proxy.
5
+ Declare it in `maggie-bridge-host.v1`
6
+ ([example](../../../bundled-contracts/maggie-deployment/bridge-host-example-v1.json)) and check it:
7
+
8
+ ```bash
9
+ maggie deployment bridge-plan --plan bridge-host.json
10
+ maggie deployment bridge-collect-script --plan bridge-host.json > collect.sh
11
+ ssh <host> 'sh -s' < collect.sh > observed.json
12
+ maggie deployment bridge-check --plan bridge-host.json --observed observed.json
13
+ ```
14
+
15
+ ## Isolation
16
+
17
+ - One OS uid per tenant from a dedicated range (for example 20000+).
18
+ - Tenant folders `0700`, owned by the tenant uid. The tenants root (and any
19
+ bridge-owned parents) `0711`: tenants can traverse to their own folder but
20
+ cannot list others. With `0700` parents, tenant uids cannot reach their
21
+ folders at all.
22
+ - Start each session with a clean, allowlisted environment (no host tokens),
23
+ pin it to its owner, and mark it non-dumpable after dropping privileges.
24
+
25
+ ## Network
26
+
27
+ - Public API on a loopback port behind the proxy (`/t/<tenant>` routes).
28
+ - Admin API on a different loopback port, never proxied.
29
+
30
+ ## Capacity and recycling
31
+
32
+ - A session cap with LRU eviction of idle sessions, plus an idle timeout.
33
+ - Recycle sessions when MCP servers, skills or the CLI update: idle sessions
34
+ restart at once, busy ones after the current reply.
35
+
36
+ ## Images and rollout
37
+
38
+ - Label every image (`com.example.app=bridge-host`) and keep only current +
39
+ previous (`retain: 2`).
40
+ - Switch with a health check (`/health`, ~30 attempts) and roll back to the
41
+ previous container on failure. Run with a read-only root filesystem,
42
+ `cap-drop ALL`, `no-new-privileges` and a pids limit.
43
+
44
+ ## Third-party AI accounts
45
+
46
+ Record each provider's terms URL and review date. A shared account may serve
47
+ several users only when its terms allow hosted multi-user use; otherwise each
48
+ user brings their own account. Review terms again at least every six months.
49
+
50
+ ## Remote shell pitfalls
51
+
52
+ - Send scripts over stdin (`ssh host 'sh -s' < script.sh`) instead of quoting
53
+ JSON or lists into an ssh argument; quotes are lost one layer down.
54
+ - When an argument must be passed, escape each one with `printf %q`.
55
+ - zsh does not word-split unquoted variables, so `for x in $list` sees one
56
+ item; write remote scripts for `sh` and iterate explicitly.
@@ -0,0 +1,57 @@
1
+ # Publishing product CLIs and MCP servers
2
+
3
+ Maggie's own release gates cover `@topy-ai/maggie`. Apply the same discipline
4
+ to the CLI and MCP packages a product ships.
5
+
6
+ ## Package metadata — `maggie product release-check`
7
+
8
+ - `bin` targets exist, start with `#!/usr/bin/env node`, and are covered by
9
+ `files`; a bundled single-file CLI (esbuild with a shebang banner) is the
10
+ simplest shape.
11
+ - `license`, `repository` (with `directory` inside a monorepo), `engines.node`,
12
+ `publishConfig.access: "public"` for scoped names, and
13
+ `publishConfig.provenance: true` when publishing from CI with OIDC.
14
+ - The changelog's top entry equals the package version.
15
+ - For the official MCP registry: `package.json` `mcpName` (a namespace you can
16
+ prove, such as `io.github.<owner>/<name>`) equals `server.json` `name`, and
17
+ `server.json` `version` and its npm package `identifier`/`version` match.
18
+ - `--pack` inspects `npm pack --dry-run`: bins are in the tarball and no
19
+ `.env`, `.npmrc`, private keys or service-account files are.
20
+
21
+ ## Installed binary — `maggie product smoke`
22
+
23
+ Packs the package, installs the tarball into an empty folder, and runs each
24
+ binary with `--version` (must print the package version) and `--help`. Run it
25
+ before publishing; after publishing, the registry may take 30–60 seconds
26
+ before `npx <package>@<version>` resolves.
27
+
28
+ ## Remote MCP endpoint — `maggie product mcp-check`
29
+
30
+ Read-only checks of an OAuth-protected MCP server:
31
+
32
+ - `/.well-known/oauth-protected-resource[/<path>]` returns RFC 9728 metadata
33
+ with `resource` on this origin, `authorization_servers`, and `header` in
34
+ `bearer_methods_supported`;
35
+ - an unauthenticated `initialize` returns `401` with
36
+ `WWW-Authenticate: Bearer resource_metadata="…"` so clients can discover
37
+ the authorization server.
38
+
39
+ ## Third-party reviews — `maggie product review-status`
40
+
41
+ Track each surface in `reviews.json` (`maggie-product-reviews.v1`):
42
+
43
+ ```json
44
+ {"schemaVersion": "maggie-product-reviews.v1", "reviews": [
45
+ {"surface": "chatgpt-app", "status": "in-review", "version": "1.4.0", "submittedAt": "2026-10-01"},
46
+ {"surface": "claude-directory", "status": "changes-requested", "nextAction": "add privacy policy link"}
47
+ ]}
48
+ ```
49
+
50
+ Surfaces: `chatgpt-app`, `claude-directory`, `mcp-registry`, `app-store`,
51
+ `google-play`, `npm`. States: `draft`, `submitted`, `in-review`,
52
+ `changes-requested`, `approved`, `rejected`, `live`. The check warns after 14
53
+ days in review, requires a `nextAction` for changes-requested/rejected, flags
54
+ an approved version that differs from the release, and checks a ChatGPT app's
55
+ `review.test_cases` (at least 5 positive with `tools_triggered`, 3 negative,
56
+ each with description, prompt and expected behaviour). Keep a demo video
57
+ script and a review account with the submission; reviewers need both.
@@ -7,6 +7,19 @@ metadata:
7
7
 
8
8
  # Maggie Deployment
9
9
 
10
+ ## Product apps and assistant hosts
11
+
12
+ - An Expo / React Native app (web, iOS, Android) uses the
13
+ [`maggie-mobile-app`](../maggie-mobile-app/SKILL.md) lane:
14
+ `maggie mobile preflight` before any EAS build (auto-submit `ascAppId`,
15
+ channels, fingerprint runtime policy, cost notice) and `maggie mobile plan`.
16
+ Its web export deploys through this skill's Cloudflare target.
17
+ - A multi-tenant assistant bridge host on a VPS is declared and checked with
18
+ `maggie deployment bridge-plan`, `bridge-collect-script` and `bridge-check`;
19
+ see [bridge host](../maggie-assistant-tools/references/bridge-host.md).
20
+ - Product CLI and MCP packages: `maggie product release-check|smoke|mcp-check`
21
+ ([product release](../maggie-assistant-tools/references/product-release.md)).
22
+
10
23
  ## Edge and rendered canary
11
24
 
12
25
  After staging or production deployment, verify that the edge serves the
@@ -315,30 +315,64 @@ sitemap semantics from `maggie-service-booking`.
315
315
 
316
316
  ## Mobile app surfaces
317
317
 
318
- Use the app surface contract for camera, scan, inventory, valuation, or other
319
- authenticated app views. It is a general host contract, not a replacement for
320
- the project's auth or camera implementation:
321
-
322
- maggie design app-init --project . --route /app/valuation \
323
- --auth-mode email-password --confirm
324
-
325
- The initializer records the fixed header/footer, one-scroll-owner rule,
326
- camera permission/ready/gallery/scan/unavailable states, decision-critical UI,
327
- and desktop/tablet/mobile evidence requirements. It never collects credentials
328
- or copies private project data. Use `existing-session` only when the host
329
- already supplies a safe signed-in session; use `none` for public app surfaces.
330
-
331
- After implementation, validate sanitized runtime evidence and screenshots:
318
+ Use the app surface contract for authenticated app views (web, or an Expo /
319
+ React Native Web route). It is a general host contract, not a replacement for
320
+ the project's auth or device-capability implementation:
321
+
322
+ maggie design app-init --project . --route /inbox \
323
+ --auth-mode existing-session --capabilities none \
324
+ --pane list-detail:1024:2 --pattern site-switcher --confirm
325
+
326
+ - `--capabilities` takes `none` or a comma list of `camera`, `location`,
327
+ `notifications`, `media-library`; each adds its required states. The
328
+ default stays `camera` for older plans; `--camera none` is a shorthand.
329
+ Inbox, settings, and account routes need no camera states.
330
+ - `--pane NAME:MIN_WIDTH:OWNERS` declares an intentional multi-pane layout
331
+ (list + detail from 1024 px). Without one, every viewport must have exactly
332
+ one scroll owner.
333
+ - `--viewport tablet=768x1024` overrides a plan viewport; the evidence and
334
+ screenshots must then match it.
335
+ - `--pattern` attaches acceptance rules from
336
+ [app UI patterns](references/app-ui-patterns.md) to the QA scenarios.
337
+
338
+ Expo Router files (`app/<route>.tsx`, `app/<route>/index.tsx`) are detected as
339
+ the route source. The plan never collects credentials or copies private data.
340
+
341
+ Collect runtime evidence with the browser instead of hand-written scripts:
342
+
343
+ maggie design app-collect --plan .maggie/design/app-view/app-<id>/plan.json \
344
+ --base-url http://localhost:8081 --profile-dir ~/.maggie-qa-profile \
345
+ --read-only --allow-write /auth/refresh --confirm
346
+
347
+ `app-collect` renders each plan viewport in one tab, one at a time, at the
348
+ real viewport size, and writes `runtime-evidence.json` plus PNGs. It counts
349
+ scroll owners per viewport (skipping React Native Web wrappers that hold an
350
+ owner without overflowing), proves the header and footer stay put while every
351
+ owner scrolls, and records the tab bar position and pinned regions as
352
+ geometry only. Use `--cdp-url http://127.0.0.1:9222` to reuse a Chrome you are
353
+ already signed in to, or a dedicated `--profile-dir` (sign in once with
354
+ `--headed`). Apps that rotate refresh tokens must never be rendered in two
355
+ instances at once; see `maggie qa app-preflight`. `--read-only` fails every
356
+ non-GET request except `--allow-write` matches, for local servers that talk to
357
+ production APIs. Capability states (camera and others) still come from
358
+ scenario QA and are preserved when evidence is recollected.
359
+
360
+ Then validate:
332
361
 
333
362
  maggie design app-validate --project . \
334
- --plan .maggie/design/app-view/app-<id>/plan.json \
335
- --runtime-evidence ./qa/mobile-app-evidence.json \
336
- --rendered-dir ./qa/screenshots --confirm
337
-
338
- The evidence must prove the auth state, fixed shell, exactly one scroll owner,
339
- all required camera states, and valid PNGs at 390px, 768px, and desktop
340
- widths. The machine-readable contract is
363
+ --plan .maggie/design/app-view/app-<id>/plan.json --confirm
364
+
365
+ Validation reads per-viewport evidence only. Each viewport's recorded
366
+ width/height must equal the plan viewport, its `scrollOwners` must be 1 unless
367
+ a declared pane applies at that width, and each PNG's real width/height must
368
+ equal the plan viewport times the recorded `deviceScaleFactor` (taller only
369
+ when `fullPage: true`). A top-level `shell.scrollOwnerCount` is ignored with a
370
+ warning, and a signature-only or scaled screenshot fails. The machine-readable
371
+ contract is
341
372
  [mobile-app-surface-v1.schema.json](../../bundled-contracts/maggie-design/mobile-app-surface-v1.schema.json).
373
+ Keep `maggie design pressable-check` in the same loop for React Native Web
374
+ apps: together they caught nested pressables and shell regressions during
375
+ repeated sheet and modal changes.
342
376
 
343
377
  ### Onboarding wizards
344
378
 
@@ -0,0 +1,66 @@
1
+ # App UI patterns
2
+
3
+ Reusable patterns for signed-in product apps (Expo / React Native Web, or a
4
+ web SPA), alongside the onboarding-wizard and picker guidance in the
5
+ `maggie-design` skill. Each pattern has acceptance rules; `maggie design
6
+ app-init --pattern <id>` copies them into the route's QA scenarios so they
7
+ are checked with the rest of the surface.
8
+
9
+ Shared rules for every pattern:
10
+
11
+ - One scroll owner per screen region. A modal, sheet, or tab body owns its
12
+ own scroll; the screen behind it does not scroll while it is open.
13
+ - Breakpoints: phone layout below 768 px, card/dialog presentation from
14
+ 768 px, list + detail panes from 1024 px (declare them with
15
+ `--pane list-detail:1024:2`).
16
+ - Capture evidence at the real viewport (`maggie design app-collect`),
17
+ never in a scaled frame.
18
+
19
+ ## `tabbed-modal` — tabbed modal route
20
+
21
+ A route presented over the current screen (Expo Router
22
+ `presentation: "transparentModal"`, fade animation), used for multi-section
23
+ settings such as "Your business" or "What the assistant can do".
24
+
25
+ - Full screen below 768 px; from 768 px a centred card (about 720–820 px
26
+ wide, max 90% of the viewport height) over a dimmed backdrop.
27
+ - Pill tabs, optionally with counts, scroll sideways. The active pill
28
+ scrolls into view on open and on change.
29
+ - Each tab body is its own scroll owner and resets to the top when the tab
30
+ changes.
31
+ - Close button, backdrop tap (card mode) and Escape close it and return
32
+ focus to the element that opened it.
33
+
34
+ ## `editor-sheet-assistant` — editor sheet with an in-place assistant
35
+
36
+ An edit sheet (bottom sheet on phones, max ~85% height, one scroll owner,
37
+ backdrop closes) whose "Ask the assistant" action turns the same sheet into
38
+ a short contextual chat instead of navigating away.
39
+
40
+ - Every message carries a context line (what is being edited).
41
+ - The assistant never writes directly: a change arrives as an approval card
42
+ (summary, risk, Approve / No). Nothing changes until it is approved; see
43
+ `maggie-assistant-tools` for the approval token contract.
44
+ - After an approval, the screen behind refreshes; dismissing the chat
45
+ returns to the editor with any unsaved edit intact.
46
+
47
+ ## `usage-hero` — plan usage hero
48
+
49
+ The first block of an inbox or account screen when usage limits matter.
50
+
51
+ - Plan name, used and remaining quota are visible without scrolling.
52
+ - Meters sit in two columns from about 360 px of card width, one column
53
+ below. A meter turns amber at 80% and red at the limit.
54
+ - The over-limit state names the next action. Hide purchase links where the
55
+ store forbids them (for example on iOS, App Store guideline 3.1.1); the
56
+ rule belongs in one helper, not in each screen.
57
+
58
+ ## `site-switcher` — searchable site or workspace switcher
59
+
60
+ - Each row shows the site icon; a failed or tiny (under 32 px) favicon falls
61
+ back to the site's first letter. Cache icon results per domain.
62
+ - A search field appears from 5 sites; below that it is noise.
63
+ - The current site is marked, and every row is keyboard reachable and has an
64
+ accessible name.
65
+ - Account-level actions (add a site) are visually separated from per-site
66
+ rows, and are audited at account scope, not under the open site.
@@ -154,9 +154,26 @@ maggie feedback session-summary --project . \
154
154
  The helper reads commit subjects only (no diffs, paths, or file contents) and
155
155
  redacts secrets and local paths. `fix:` commits become fixed `bug` items with a
156
156
  `commit:<sha>` evidence reference; `feat:`, `perf:` and `refactor:` commits
157
- become `improvement` candidates; other commits are skipped and counted. It also
158
- adds one placeholder for an open ask. It writes a draft batch file under
159
- `.maggie/feedback/batches/` and does not create or submit feedback.
157
+ become `improvement` candidates. Plain-sentence subjects without a prefix are
158
+ classified by keywords ("no longer", "prevent", "crash" → bug; "add",
159
+ "replaces", "support", "show" → improvement); `docs:`, `chore:`, version bumps
160
+ and unclassified subjects are skipped and counted, or kept as `general` items
161
+ with `--all`. `--merges` includes merge commits and classifies a PR merge by
162
+ its branch name. It also adds one placeholder for an open ask. It writes a
163
+ draft batch file under `.maggie/feedback/batches/` and does not create or
164
+ submit feedback.
165
+
166
+ One session often spans several repositories (app, backend, edge). Repeat
167
+ `--repo` with a label and use a date, because revisions differ per repo:
168
+
169
+ ```bash
170
+ maggie feedback session-summary --project . \
171
+ --repo app=../app --repo api=../api --repo edge=../edge \
172
+ --since-date 2026-10-12 --batch-id product-session-2026-10-12
173
+ ```
174
+
175
+ Evidence then reads `commit:<label>@<sha>`; unlabeled repositories become
176
+ `repo1`, `repo2`, so local folder names never leave the machine.
160
177
 
161
178
  Review the file: delete items that concern the project rather than a Maggie
162
179
  skill or CLI, and replace every `REVIEW:` field (expected, actual, validation).
@@ -195,6 +195,34 @@ The local export is copied as the final homepage input before completion; the
195
195
  clone run still supplies responsive screenshots, source evidence, manifests,
196
196
  and `DESIGN.md`. No interactive approval is required during the command.
197
197
 
198
+ ## Third-party skill catalogs
199
+
200
+ A product that ships its own Agent Skills (tens or hundreds of them) can use
201
+ the same validation Maggie applies to its own skills, plus Claude Code plugin
202
+ packaging:
203
+
204
+ ```bash
205
+ maggie skills scaffold --root skills --category social --name cmo-thread \
206
+ --description "Turn an article into a social thread; use after an article is approved."
207
+ maggie skills validate --root skills [--catalog catalog.json] [--require-pinned]
208
+ maggie skills package --root skills --out dist/marketplace --prefix cmo --owner "Example Ltd" --version 1.0.0
209
+ maggie skills smoke --out dist/marketplace --claude
210
+ ```
211
+
212
+ - `validate` checks front matter (`name` equals its folder, lower-case,
213
+ ≤ 64 characters; `description` ≤ 1024, no tags), duplicate names,
214
+ placeholders, relative links, optional catalog parity, and with
215
+ `--require-pinned` that `references` entries pin a 40-character commit.
216
+ Maggie's own `skills/` pass the same validator.
217
+ - `package` writes one plugin per category (`metadata.category` or the
218
+ top-level folder) plus an all-in-one plugin, each with
219
+ `.claude-plugin/plugin.json`, and `.claude-plugin/marketplace.json`.
220
+ - `smoke` re-checks names, versions, sources and every packaged skill, and
221
+ with `--claude` runs `claude plugin validate`.
222
+
223
+ Nothing is published; push the output folder to the marketplace repository
224
+ yourself after review.
225
+
198
226
  ## Rules
199
227
 
200
228
  1. Extract the template detail page first and save title, description,
@@ -0,0 +1,122 @@
1
+ ---
2
+ name: maggie-mobile-app
3
+ description: Ship a cross-platform product app from one Expo / React Native codebase to web, iOS and Android. Use for the dev server, web deploy, EAS build profiles, TestFlight and Play internal testing, EAS Update channels and runtime versions, store-review rules, and a release preflight with a cost notice before every build.
4
+ metadata:
5
+ version: 1.0.0
6
+ ---
7
+
8
+ # Maggie Mobile App
9
+
10
+ ## Automatic memory hook
11
+
12
+ Follow [Maggie Memory Hook](../../references/memory-hook.md) at invocation and completion.
13
+
14
+ For builds, submissions and OTA updates, follow the shared [Maggie decision loop](../../references/decision-loop.md): inspect, propose, checkpoint, then confirm. Every cloud build spends quota; never start one without showing the cost notice and getting a yes.
15
+
16
+ This lane covers a product app the way `maggie-deployment` covers a website:
17
+ one Expo codebase serving web, iOS and Android. It does not own the app's
18
+ auth, payments, or data; the host app does.
19
+
20
+ ## 1. Dev server and browser QA
21
+
22
+ - Start Metro from the app folder (`apps/app` in a monorepo), never from the
23
+ repository root, and never with `CI=1`: CI mode disables file watching, so
24
+ the browser keeps the old bundle and a working change looks broken.
25
+ - Before browser QA, run `maggie qa app-preflight --project . --app-dir apps/app`.
26
+ It catches both mistakes and warns about rotating refresh tokens and
27
+ production-backed local servers (see `maggie-qa-workflow`).
28
+ - Design and validate signed-in routes with `maggie design app-init`,
29
+ `app-collect` and `app-validate` (see `maggie-design`, including the
30
+ [app UI patterns](../maggie-design/references/app-ui-patterns.md)).
31
+
32
+ ## 2. Web deploy
33
+
34
+ `npx expo export --platform web` writes a static single-page app to `dist/`.
35
+ Serve it with a single-page-app fallback (Cloudflare Workers static assets:
36
+ `"not_found_handling": "single-page-application"`), security headers in
37
+ `public/_headers`, and a custom domain. Use `maggie-deployment` for the
38
+ Cloudflare target, canaries and rollback.
39
+
40
+ ## 3. Release preflight (before any build)
41
+
42
+ ```bash
43
+ maggie mobile preflight --project . --app-dir apps/app \
44
+ --profile production --platform ios --auto-submit
45
+ ```
46
+
47
+ It reads `app.json` (or `npx expo config --json --type public` output passed
48
+ with `--config-json` when the config is dynamic), `eas.json` and
49
+ `package.json`, and fails before quota is spent when:
50
+
51
+ - `--auto-submit --non-interactive` would fail at submission: iOS needs
52
+ `submit.<profile>.ios.ascAppId` (the numeric App Store Connect app ID),
53
+ Android needs a service-account key path (kept out of git);
54
+ - EAS Update is installed but the profile has no `channel`, the update URL is
55
+ missing, or there is no `runtimeVersion`;
56
+ - `runtimeVersion` uses `appVersion`/`nativeVersion` while
57
+ `cli.appVersionSource` is `remote` and `expo.version` never changes: every
58
+ future binary would accept any JS update, including one that needs a new
59
+ native module. Use one top-level `{"policy": "fingerprint"}`.
60
+
61
+ It warns about missing export-compliance (`usesNonExemptEncryption`), an
62
+ unpinned `cli.version`, per-platform-only runtime versions (what
63
+ `eas update:configure` writes) and tab-indented `app.json` that
64
+ `update:configure` would reformat. Prefer editing these fields by hand.
65
+
66
+ Recommended `eas.json` shape:
67
+
68
+ ```json
69
+ {
70
+ "cli": {"version": ">= 16.0.0", "appVersionSource": "remote"},
71
+ "build": {
72
+ "preview": {"distribution": "internal", "channel": "preview"},
73
+ "production": {"autoIncrement": true, "channel": "production"}
74
+ },
75
+ "submit": {"production": {"ios": {"ascAppId": "<numeric id>"}, "android": {"track": "internal"}}}
76
+ }
77
+ ```
78
+
79
+ ## 4. Build, submit, update
80
+
81
+ ```bash
82
+ maggie mobile plan --project . --app-dir apps/app --platform ios --auto-submit
83
+ ```
84
+
85
+ prints the exact commands with the cost notice and runs nothing:
86
+
87
+ 1. `npx eas-cli build -p ios --profile production --non-interactive --auto-submit`
88
+ → TestFlight (iOS) or the Play internal track (Android). Add testers in
89
+ App Store Connect / Play Console; internal testing needs no review.
90
+ 2. Without `--auto-submit`: `npx eas-cli submit -p ios --profile production --latest`.
91
+ 3. JS-only fixes: `npx eas-cli update --channel production --platform ios --message "…"`.
92
+ A native change (new module, permission, SDK upgrade) needs a new build;
93
+ the fingerprint policy stops an incompatible update from reaching old
94
+ binaries.
95
+
96
+ Show the plan's `costNotice` and wait for confirmation before step 1.
97
+
98
+ ## 5. Store-review rules
99
+
100
+ - iOS (App Store guideline 3.1.1): no links or buttons to buy digital goods
101
+ outside in-app purchase. Keep the rule in one helper (for example
102
+ `canLinkToPurchase = Platform.OS !== "ios"`) and apply it to assistant
103
+ tools that return purchase links, not only to screens.
104
+ - Provide a working review account and notes; reviewers sign in.
105
+ - Declare export compliance, data collection (privacy labels / Data safety)
106
+ and every permission's purpose string.
107
+ - Account deletion must be reachable in the app when sign-up is.
108
+
109
+ ## 6. Readiness report
110
+
111
+ Before a store submission, record: preflight passed, app-validate passed for
112
+ each signed-in route, QA run summary (`maggie qa summary`), the build and
113
+ update commands that ran, and the review status
114
+ (`maggie product review-status`, surfaces `app-store` and `google-play`).
115
+
116
+ ## Hard boundaries
117
+
118
+ - Never run `eas build`, `eas submit` or `eas update` without an explicit yes
119
+ after the cost notice.
120
+ - Never commit App Store Connect API keys, Play service-account JSON, or
121
+ keystores; reference them by path or environment variable name.
122
+ - Do not change bundle identifiers or package names of a published app.