@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.
- package/README-zh-TW.md +12 -4
- package/README.md +55 -11
- package/bin/maggie.js +26 -4
- package/bundled-contracts/maggie-design/palette-roles-v1.schema.json +47 -0
- package/bundled-contracts/maggie-marketplace/template-content-v1.schema.json +103 -0
- package/bundled-contracts/maggiedash/booking-browser-evidence-v1.json +21 -0
- package/bundled-contracts/maggiedash/booking-browser-evidence-v2.json +191 -0
- package/bundled-contracts/maggiedash/booking-email-templates-v1.json +3 -1
- package/bundled-contracts/maggiedash/booking-voucher-lifecycle-v1.json +85 -0
- package/bundled-contracts/maggiedash/execution-board.json +4629 -1553
- package/bundled-contracts/maggiedash/stripe-booking-capabilities-v1.json +1 -0
- package/bundled-marketplace/README.md +17 -0
- package/bundled-marketplace/catalog.json +56 -7
- package/bundled-references/browser-inspection.md +25 -0
- package/bundled-references/maggiedash-booking/CURRENT-STATE.md +128 -10
- package/bundled-references/maggiedash-booking/EXECUTION-BOARD.json +4629 -1553
- package/bundled-references/maggiedash-booking/HOST-ADAPTER.md +5 -0
- package/bundled-references/maggiedash-booking/ORAWELLNESS-INTEGRATION-AUDIT.md +64 -21
- package/bundled-references/maggiedash-booking/PRD.md +9 -1
- package/bundled-references/maggiedash-booking/PROGRESS.md +244 -2399
- package/bundled-references/maggiedash-booking/QA-TEST-PLAN.md +37 -6
- package/bundled-references/maggiedash-booking/README.md +23 -6
- package/bundled-references/maggiedash-booking/RUNTIME-OPERATIONS.md +64 -8
- package/bundled-references/maggiedash-booking/SKILLS-AND-CLI.md +11 -2
- package/bundled-references/maggiedash-booking/STRIPE-INTEGRATION.md +66 -2
- package/bundled-references/maggiedash-booking/TASK-RUNBOOK.md +1 -1
- package/bundled-references/maggiedash-booking/TASKS.md +44 -3
- package/bundled-references/maggiedash-booking/VOUCHERS.md +47 -0
- package/bundled-references/memory-hook.md +18 -5
- package/bundled-references/provider-adapter-contract.md +33 -0
- package/bundled-skills/maggie-booking/SKILL.md +8 -0
- package/bundled-skills/maggie-clone-to-template/SKILL.md +26 -0
- package/bundled-skills/maggie-deployment/SKILL.md +59 -1
- package/bundled-skills/maggie-deployment/references/vps.md +41 -0
- package/bundled-skills/maggie-design/SKILL.md +99 -0
- package/bundled-skills/maggie-feedback/SKILL.md +41 -2
- package/bundled-skills/maggie-marketplace/SKILL.md +91 -0
- package/bundled-skills/maggie-memory/SKILL.md +10 -1
- package/bundled-skills/maggie-qa-workflow/SKILL.md +41 -1
- package/bundled-skills/maggie-service-booking/SKILL.md +23 -0
- package/bundled-skills/maggie-social-share/SKILL.md +37 -5
- package/bundled-skills/maggie-social-share/references/queue-and-connections.md +101 -0
- package/bundled-skills/maggie-template/SKILL.md +57 -3
- package/bundled-skills/maggie-template/references/template-content-v1.example.json +34 -0
- package/bundled-tools/clis/maggie_booking.py +199 -26
- package/bundled-tools/clis/maggie_booking_vouchers.py +185 -0
- package/bundled-tools/clis/maggie_clone_to_template.py +14 -0
- package/bundled-tools/clis/maggie_deployment.py +295 -0
- package/bundled-tools/clis/maggie_design.py +9 -0
- package/bundled-tools/clis/maggie_design_lint.py +277 -0
- package/bundled-tools/clis/maggie_feedback.py +107 -3
- package/bundled-tools/clis/maggie_marketplace.py +199 -5
- package/bundled-tools/clis/maggie_memory.py +10 -3
- package/bundled-tools/clis/maggie_palette.py +280 -0
- package/bundled-tools/clis/maggie_qa_workflow.py +156 -1
- package/bundled-tools/clis/maggie_social_queue.py +338 -0
- package/bundled-tools/clis/maggie_social_share.py +42 -9
- package/bundled-tools/clis/maggie_template_package.py +1141 -0
- package/bundled-tools/runtime/maggie_memory.py +17 -2
- package/package.json +1 -1
- package/references/browser-inspection.md +25 -0
- package/references/memory-hook.md +18 -5
- 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
|
|
41
|
-
|
|
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,
|
|
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,
|
|
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
|
|
32
|
-
|
|
33
|
-
|
|
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
|
+
}
|