@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
@@ -30,6 +30,17 @@ maggie tool maggie_social_share.py validate .maggie/social-share-plan.json
30
30
  The CLI does not generate copy or publish. It validates identity, canonical
31
31
  URL, channel limits, UTM links, approval state, and provider post state.
32
32
 
33
+ Before connecting providers or scheduling, check the adapter, connection,
34
+ campaign, and queue contracts (shapes and rules in
35
+ [queue and connections](references/queue-and-connections.md)):
36
+
37
+ ```bash
38
+ maggie tool maggie_social_share.py adapters .maggie/social-adapters.json
39
+ maggie tool maggie_social_share.py connections .maggie/social-connections.json
40
+ maggie tool maggie_social_share.py campaigns .maggie/social-campaigns.json
41
+ maggie tool maggie_social_share.py queue .maggie/social-queue.json --slots 14
42
+ ```
43
+
33
44
  1. Select an approved or explicitly shareable source article/content asset.
34
45
  2. Read Project Context and the selected social tone/template.
35
46
  3. Extract one clear content atom: insight, statistic, process, story, or
@@ -37,8 +48,11 @@ URL, channel limits, UTM links, approval state, and provider post state.
37
48
  4. Create platform-native variants with the platform's current limits and a
38
49
  clear CTA. Preserve the source canonical URL and apply the configured UTM
39
50
  policy.
40
- 5. Store drafts as calendar items with source ID, platform, version, approval,
41
- scheduled time, and local/remote status.
51
+ 5. Store drafts as queue items with source ID, platform, version, approval,
52
+ optional `not_before`, and local/remote status. Posting hours are slots;
53
+ do not persist a fixed `scheduled_at` per post (it goes stale and strands
54
+ overdue posts). Campaign ideas stay in the idea stage until written, and a
55
+ campaign starts only through the Start gate.
42
56
  6. Publish only after the required approval and entitlement checks. Record the
43
57
  publication attempt and provider ID; retry only with bounded idempotency.
44
58
  7. Read back clicks, engagement, assisted conversions, and failures separately
@@ -48,12 +62,30 @@ URL, channel limits, UTM links, approval state, and provider post state.
48
62
 
49
63
  ```text
50
64
  source_content_id, canonical_url, platform, format, hook, body, cta,
51
- hashtags_or_mentions, scheduled_at, approval_state, tracking_url
65
+ hashtags_or_mentions, not_before, queue_position, campaign_id, approval_state,
66
+ tracking_url
52
67
  ```
53
68
 
69
+ `not_before` is optional and only a lower bound; the slot planner assigns the
70
+ actual publish slot.
71
+
54
72
  Start with LinkedIn and Facebook adapters. Add other platforms only when the
55
- adapter can declare limits, auth scope, media requirements, idempotency, and
56
- delete/republish behavior.
73
+ adapter can declare limits, one canonical auth scope set, media requirements,
74
+ idempotency, and delete/republish behavior.
75
+
76
+ ## Connections
77
+
78
+ - Every connect path (dashboard, mobile, CLI) requests the adapter's canonical
79
+ scope set. LinkedIn revokes a member's earlier tokens when a sign-in asks
80
+ for a different set; a shared OAuth client used by other products can do
81
+ the same. `adapters` fails on scope drift and warns on shared clients.
82
+ - A connection whose token the provider revoked, or that a serving host cannot
83
+ decrypt, shows **Reconnect** before anything is scheduled on it. Run the
84
+ decrypt check on every host that serves social routes.
85
+ - Provider avatar URLs are signed and expire; cache the bytes or refresh on
86
+ readback.
87
+ - Keep model structured-output enums small and validate large vocabularies
88
+ server-side; see [provider adapter contract](../../references/provider-adapter-contract.md#structured-model-output).
57
89
 
58
90
  ## Safety and commercial boundary
59
91
 
@@ -0,0 +1,101 @@
1
+ # Social Share queue, campaigns, and connections
2
+
3
+ All commands read one redacted JSON document, make no provider or model calls,
4
+ and print a JSON report. Validation commands exit `1` when the contract fails.
5
+
6
+ ## Adapter scope contract — `adapters`
7
+
8
+ ```json
9
+ {
10
+ "adapters": [{
11
+ "provider": "linkedin",
12
+ "canonical_scopes": ["openid", "profile", "email", "w_member_social"],
13
+ "client_id_ref": "linkedin-app-main",
14
+ "connect_paths": [
15
+ {"id": "dashboard", "scopes": ["openid", "profile", "email", "w_member_social"]},
16
+ {"id": "mobile", "scopes": ["openid", "profile", "email", "w_member_social"]}
17
+ ],
18
+ "redirect_uris": ["https://app.example.com/oauth/linkedin/callback"],
19
+ "client_shared_with": []
20
+ }]
21
+ }
22
+ ```
23
+
24
+ - Fails when any connect path requests a scope set different from
25
+ `canonical_scopes` (order is ignored). LinkedIn revokes a member's earlier
26
+ tokens when a sign-in requests a different scope set.
27
+ - Fails when secret fields (`client_secret`, tokens) appear in the manifest.
28
+ `client_id_ref` is a label, not the credential.
29
+ - Warns when the OAuth client is shared with other products, or redirect URIs
30
+ span several hosts without a `client_shared_with` record.
31
+
32
+ ## Connection health — `connections`
33
+
34
+ ```json
35
+ {"connections": [{
36
+ "id": "conn-1", "provider": "linkedin", "status": "active",
37
+ "token_decryptable": true,
38
+ "provider_check": {"status": "valid", "checked_at": "2026-10-10T08:00:00Z"},
39
+ "avatar_url": "https://media.licdn.com/dms/image/...?...&e=1790000000",
40
+ "avatar_cached": false, "avatar_refresh_on_read": false,
41
+ "scheduled_items": 4
42
+ }]}
43
+ ```
44
+
45
+ - `status` is derived: `needs_reconnect` when the token cannot be decrypted on
46
+ the serving host or the provider reports it `revoked`/`invalid`/`expired`.
47
+ A stored `active` that should be `needs_reconnect` fails, and the report
48
+ counts scheduled items that would otherwise fail at publish time.
49
+ - Run the decrypt check on every host that serves social routes; a missing
50
+ encryption key on a failover host looks exactly like an undecryptable token.
51
+ - A signed, expiring avatar URL (LinkedIn `e=`, Meta `oe=`, S3/GCS signed
52
+ URLs) fails unless `avatar_cached` (bytes in owned storage) or
53
+ `avatar_refresh_on_read` is true. Use `--now` for deterministic checks.
54
+
55
+ ## Campaign idea stage — `campaigns`
56
+
57
+ ```text
58
+ idea (planned, no copy) --write (1 credit)--> written (draft_id) --all written + start_day + posts_per_day--> Start
59
+ ```
60
+
61
+ - Ideas are visible and manageable on every client (dashboard and mobile), not
62
+ only where they were planned. Written drafts keep their `campaign_id`.
63
+ - A campaign can start only when every idea is `written` with a `draft_id`,
64
+ orders are unique integers, `start_day` is a date, and `posts_per_day >= 1`.
65
+ The report lists blockers; a `started` campaign with blockers fails.
66
+
67
+ ## Slot-based posting queue — `queue`
68
+
69
+ Posts do not carry a fixed publish time. The person's posting hours are slots:
70
+
71
+ ```json
72
+ {
73
+ "timezone": "Europe/London",
74
+ "posting_hours": {"mon": ["09:00", "17:00"], "wed": ["12:30"]},
75
+ "queue": [{"id": "post-7", "queued_at": "2026-10-09T10:00:00Z", "not_before": null}],
76
+ "campaigns": [{"id": "autumn", "status": "started", "start_day": "2026-10-12", "posts_per_day": 1,
77
+ "ideas": [{"id": "i1", "order": 1, "status": "written", "draft_id": "post-31"}],
78
+ "posted_idea_ids": []}]
79
+ }
80
+ ```
81
+
82
+ ```bash
83
+ maggie tool maggie_social_share.py queue queue.json --from 2026-10-12T00:00:00Z --slots 14
84
+ ```
85
+
86
+ Rules the planner applies, in order:
87
+
88
+ 1. Each slot (local wall time in `timezone`) posts at most one item.
89
+ 2. The standalone queue is newest-first: a new post goes to the front.
90
+ 3. A stored time is `not_before` only. An overdue item is simply eligible; it
91
+ is never stranded behind a past `scheduled_at`.
92
+ 4. A started campaign publishes written ideas in idea order from `start_day`,
93
+ at most `posts_per_day` per local day.
94
+ 5. The standalone queue and each started campaign take turns (round-robin);
95
+ a source with nothing eligible is skipped for that slot.
96
+ 6. Wall times keep their local meaning across DST. A time that does not exist
97
+ (spring-forward gap) is skipped and reported; an ambiguous time uses its
98
+ first occurrence.
99
+
100
+ The plan is advisory output for the host scheduler, which re-plans after every
101
+ publish, approval, or queue edit instead of persisting stale per-post times.
@@ -28,9 +28,10 @@ maggie tool maggie_marketplace.py apply \
28
28
  --id medical-spa-landing-001 --project /path/to/astro-project
29
29
  ```
30
30
 
31
- `list` shows ID, lifecycle status, industries, and style tags. `suggest`
32
- matches the user's brief against those fields and ranks published entries
33
- first. `inspect` returns metadata and available artifacts. `apply` validates
31
+ `list` shows ID, the neutral `displayName`, lifecycle status, industries, and
32
+ style tags. Show customers the `displayName` and `displayDescription`, never the
33
+ source title in `sourceMetadata`. `suggest` matches the user's brief against
34
+ those fields and ranks published entries first. `inspect` returns metadata and available artifacts. `apply` validates
34
35
  the template, writes a namespaced reference to `.maggie/marketplace/<id>/`,
35
36
  copies the homepage, assets, screenshots, and `DESIGN.md`, and records
36
37
  `.maggie/template-selection.json`. It does not silently overwrite application
@@ -39,6 +40,59 @@ routes.
39
40
  Draft entries are for review only. Use `--allow-draft` only when the user
40
41
  explicitly wants to preview an unpublished template.
41
42
 
43
+ ## Preview studio
44
+
45
+ Compare a template across viewports and palettes before applying it:
46
+
47
+ ```bash
48
+ maggie tool maggie_marketplace.py measure-design <id> --palette-roles /tmp/<id>-palettes.json
49
+ maggie tool maggie_design.py palette generate --roles /tmp/<id>-palettes.json \
50
+ --template <id> --output /tmp/<id>-palettes.json # optional: contrast-safe variants
51
+ maggie tool maggie_marketplace.py studio <id> --palettes /tmp/<id>-palettes.json
52
+ maggie tool maggie_marketplace.py studio <id> --palettes /tmp/<id>-palettes.json --check-overflow [--palette <variant-id>]
53
+ ```
54
+
55
+ `studio` writes `.maggie/template-studio/<id>/index.html` under the
56
+ marketplace root: the homepage in scaled frames at 390, 768, 1024, and
57
+ 1440 px, a palette dropdown fed by a `maggie-palette-roles-v1` file (the
58
+ measured signature when none is given), and labels on sample copy. Each label
59
+ links to `content-fields.html`, which names the `maggie-template-content-v1`
60
+ field and where the owner replaces it. Elements marked
61
+ `data-maggie-sample="hero.headline"` are labelled exactly; otherwise headings,
62
+ contact links, and section headings are matched heuristically. A palette is
63
+ applied by swapping the signature role colours for the variant's and by
64
+ setting `--maggie-<role>` CSS variables. Open `#<palette-id>` to link a variant.
65
+
66
+ Serve the marketplace root over HTTP (`python3 -m http.server`) to view it.
67
+ `--check-overflow` serves it locally, renders it with headless Chrome, writes
68
+ `overflow-report.json`, and exits non-zero when any viewport has horizontal
69
+ overflow, naming up to five offending elements. Templates that load Tailwind or
70
+ fonts from a CDN need network access for a faithful render.
71
+
72
+ ## Data-driven component export
73
+
74
+ A template reused across many businesses must render data, not hand-edited
75
+ copy. The neutral content contract is
76
+ [`contracts/maggie-marketplace/template-content-v1.schema.json`](../../bundled-contracts/maggie-marketplace/template-content-v1.schema.json)
77
+ (`brand`, `contact`, `hero`, `categories` with `services`, `about`, `gallery`,
78
+ `reviews`, `hours`, `faqs`, plus `samples` and an optional palette). An example
79
+ is in [`references/template-content-v1.example.json`](references/template-content-v1.example.json).
80
+
81
+ ```bash
82
+ maggie tool maggie_marketplace.py content-validate --input content.json
83
+ maggie tool maggie_marketplace.py content-css --input content.json # :root { --maggie-<role>: … }
84
+ ```
85
+
86
+ `content-validate` enforces the business rules the schema cannot: service
87
+ prices and durations, `HH:MM` opening hours, reviews that carry a `source` or
88
+ are explicitly `sample: true` (never invent reviews), and `samples` paths that
89
+ resolve. Export path: build one Astro component per template that takes the
90
+ content object as props, maps each `[data-maggie-sample]` region to its
91
+ content field, and reads colours from the `--maggie-<role>` variables emitted
92
+ by `content-css`. Converting the existing marketplace templates into such
93
+ components is not automated yet; do it per template and keep the static
94
+ `homepage.html` as the visual reference.
95
+
42
96
  ## Selection workflow
43
97
 
44
98
  Use the deterministic marketplace CLI for listing, recommendation, inspection,
@@ -0,0 +1,34 @@
1
+ {
2
+ "schemaVersion": "maggie-template-content-v1",
3
+ "brand": { "name": "Maggie Studio", "tagline": "Considered care in London", "logo": { "src": "assets/maggie-mark.png", "alt": "Maggie Studio" } },
4
+ "contact": { "phone": "020 0000 0000", "email": "hello@example.co.uk", "address": "1 Example Street, London", "bookingUrl": "/book" },
5
+ "hero": {
6
+ "headline": "Calm, personalised treatments",
7
+ "subheadline": "Book facials, massage and body treatments online.",
8
+ "image": { "src": "assets/maggie-hero.png", "alt": "Treatment room" },
9
+ "cta": { "label": "Book now", "href": "/book" }
10
+ },
11
+ "categories": [
12
+ {
13
+ "name": "Facials",
14
+ "services": [
15
+ { "name": "Signature facial", "price": 85, "currency": "GBP", "durationMinutes": 60, "bookingRef": null },
16
+ { "name": "Express facial", "price": 50, "currency": "GBP", "durationMinutes": 30, "bookingRef": null }
17
+ ]
18
+ }
19
+ ],
20
+ "about": { "heading": "About us", "body": "A small team offering unhurried appointments.", "image": null },
21
+ "gallery": [{ "src": "assets/maggie-care-team.png", "alt": "Care team" }],
22
+ "reviews": [{ "quote": "Thoughtful and relaxing.", "author": "A. Client", "rating": 5, "sample": true }],
23
+ "hours": [
24
+ { "day": "mon", "opens": "09:00", "closes": "18:00" },
25
+ { "day": "sun", "closed": true }
26
+ ],
27
+ "faqs": [{ "question": "Do you take walk-ins?", "answer": "Please book online so we can prepare your room." }],
28
+ "samples": ["brand.name", "contact.phone", "contact.email", "contact.address", "hero.headline", "reviews.0"],
29
+ "palette": {
30
+ "id": "signature",
31
+ "name": "Signature",
32
+ "roles": { "canvas": "#FDFBF7", "panel": "#FFFFFF", "soft": "#F2EFE9", "text": "#2A241E", "accent": "#2D5A27", "accentText": "#2D5A27", "onAccent": "#FFFFFF", "dark": "#2D5A27", "deep": "#000000" }
33
+ }
34
+ }