@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
@@ -73,7 +73,16 @@ def write(project: str | Path, kind: str, payload: dict[str, Any]) -> Path:
73
73
 
74
74
 
75
75
  def init(project: str | Path) -> dict[str, str]:
76
- return {kind: str(write(project, kind, read(project, kind))) for kind in KINDS}
76
+ paths: dict[str, str] = {}
77
+ for kind in KINDS:
78
+ path = memory_path(project, kind)
79
+ if path.exists():
80
+ # Validate existing state, but keep its bytes and mtime unchanged.
81
+ read(project, kind)
82
+ else:
83
+ write(project, kind, empty(kind))
84
+ paths[kind] = str(path)
85
+ return paths
77
86
 
78
87
 
79
88
  def _text(value: Any, field: str, required: bool = False) -> str:
@@ -176,11 +185,13 @@ def _active(item: dict[str, Any], project_id: str = "") -> bool:
176
185
  return not expires or expires > now()
177
186
 
178
187
 
179
- def relevant(project: str | Path, *, skill: str = "", query: str = "", project_id: str = "", status: str | None = None) -> dict[str, list[dict[str, Any]]]:
188
+ def relevant(project: str | Path, *, skill: str = "", query: str = "", project_id: str = "", status: str | None = None, include_shared: bool = False) -> dict[str, list[dict[str, Any]]]:
180
189
  terms = set(re.findall(r"[a-z0-9_-]+", f"{skill} {query}".lower()))
181
190
  result: dict[str, list[dict[str, Any]]] = {kind: [] for kind in KINDS}
182
191
  for kind in KINDS:
183
192
  for item in read(project, kind)["items"]:
193
+ if not include_shared and item.get("scope") != "project":
194
+ continue
184
195
  if status is not None:
185
196
  if item.get("status") != status:
186
197
  continue
@@ -194,6 +205,10 @@ def relevant(project: str | Path, *, skill: str = "", query: str = "", project_i
194
205
  return result
195
206
 
196
207
 
208
+ def initialized(project: str | Path) -> bool:
209
+ return all(memory_path(project, kind).is_file() for kind in KINDS)
210
+
211
+
197
212
  def transition(project: str | Path, kind: str, item_id: str, status: str) -> dict[str, Any]:
198
213
  if status not in STATUSES:
199
214
  raise ValueError(f"invalid status: {status}")
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@topy-ai/maggie",
3
- "version": "0.7.46",
3
+ "version": "0.7.48",
4
4
  "description": "Install and manage Maggie Skills for AI coding agents",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -75,3 +75,28 @@ appearance. For every stateful component capture state A and state B and
75
75
  record the trigger and transition. Keep screenshots and extracted data under
76
76
  the target's namespaced research root so multiple URLs cannot overwrite one
77
77
  another.
78
+
79
+ ## Network interception and write safety
80
+
81
+ Any skill that drives a browser against a running app (QA, clone, design
82
+ review) must assume the app may talk to a real API. A local development build
83
+ is often configured with the production API base URL, so a click in local QA
84
+ can change live accounts.
85
+
86
+ - Do not rely on page-level stubs such as overriding `window.fetch` from the
87
+ console or an injected script. Bundled API clients usually capture `fetch`
88
+ at module load, use `XMLHttpRequest`, or run in a service worker, so the
89
+ override never sees their requests.
90
+ - Intercept at the network layer instead: Playwright `page.route()` /
91
+ `context.route()`, Puppeteer request interception, or CDP `Fetch.enable`.
92
+ Deny by default every non-GET request to a production origin and let only
93
+ explicitly listed reads through.
94
+ - Verify the interception before any write flow: trigger one harmless request
95
+ and confirm in the browser's network log that it was intercepted, not sent.
96
+ - Without network-layer interception, run write flows only against a
97
+ non-production API, or after the user gives explicit consent naming the
98
+ account and the data that will change. Record a backup or restore path first.
99
+
100
+ `maggie qa start --api-base URL --production-api URL` records the API target.
101
+ Scenarios marked `"mutates": true` are blocked against a production API unless
102
+ `--allow-production-writes` is given. See the `maggie-qa-workflow` skill.
@@ -1,23 +1,36 @@
1
1
  # Maggie Memory Hook
2
2
 
3
- Every Maggie skill invocation has an automatic memory lifecycle when the host
4
- project contains `tools/clis/maggie_memory.py`.
3
+ Every Maggie skill invocation uses the current project's Maggie Memory by
4
+ default. Project initialization creates `.maggie/memory/` for that repository.
5
5
 
6
6
  ## Before work
7
7
 
8
- Run:
8
+ Use the project-local adapter when it is present:
9
9
 
10
10
  ```bash
11
11
  python3 tools/clis/maggie_memory.py context --project . --skill <current-skill>
12
12
  ```
13
13
 
14
+ If that adapter is absent, use the installed CLI:
15
+
16
+ ```bash
17
+ maggie memory context --project . --skill <current-skill>
18
+ ```
19
+
14
20
  Load the returned active preferences, conventions, lessons, and matching error
15
21
  history into the current decision context. Surface material rules and verify
16
22
  them against current project evidence. Memory never replaces inspection,
17
23
  approval, bootstrap, or production gates.
18
24
 
19
- If the command is unavailable, report that memory is unavailable and continue
20
- with the normal workflow. Do not invent or silently reconstruct memory.
25
+ The context response reports `status: "uninitialized"` when Maggie Memory is
26
+ available but the project has not initialized its store. In that case, explain
27
+ that `maggie init --scope project` initializes it; do not call memory
28
+ unavailable. Report unavailable only when neither the project adapter nor the
29
+ installed `maggie` CLI can run. Do not invent or silently reconstruct memory.
30
+
31
+ Context includes only active project-scope items for the current repository.
32
+ Include user/workspace entries only after a separate explicit opt-in with
33
+ `--include-shared`.
21
34
 
22
35
  ## After work
23
36
 
@@ -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/`.