@topy-ai/maggie 0.1.1 → 0.1.2
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/bin/maggie.js +1 -0
- package/bundled-skills/README.md +2 -1
- package/bundled-skills/maggie-blog-bootstrap/SKILL.md +7 -10
- package/bundled-skills/maggie-clone/SKILL.md +6 -3
- package/bundled-skills/maggie-design/SKILL.md +104 -36
- package/bundled-skills/maggie-ops/SKILL.md +163 -0
- package/bundled-skills/maggie-ops/agents/openai.yaml +4 -0
- package/bundled-tools/clis/maggie.py +3 -3
- package/bundled-tools/clis/maggie_design.py +153 -0
- package/package.json +1 -1
package/bin/maggie.js
CHANGED
package/bundled-skills/README.md
CHANGED
|
@@ -7,7 +7,8 @@ Skills are the agent-facing workflows. They compose with the tools in
|
|
|
7
7
|
|---|---|---|
|
|
8
8
|
| `maggie-blog-bootstrap` | Build a complete blog in an existing project | site audit, analytics, API Pull |
|
|
9
9
|
| `maggie-clone` | Reverse-engineer authorized URLs into namespaced blog-project pages | browser MCP, clone planner CLI, bootstrap state |
|
|
10
|
-
| `maggie-design` |
|
|
10
|
+
| `maggie-design` | Fully clone authorized interior pages, then reconcile them to the homepage header/footer shell | browser MCP, clone planner CLI, completed Maggie homepage |
|
|
11
|
+
| `maggie-ops` | Build, connect, operate, upgrade, and verify the private blog operations dashboard | Ops dashboard contract, authenticated API bridge, host tests |
|
|
11
12
|
| `maggie-deployment` | Deploy and verify a dynamic Maggie blog, Cloudflare-first | Cloudflare Workers, D1, R2, KV, Wrangler |
|
|
12
13
|
| `maggie-project-context` | Sync Project, voice, site and CTA context | project-context CLI/API |
|
|
13
14
|
| `maggie-seo-geo` | Plan, audit, create/rewrite and measure SEO/GEO | visibility, SEO audit, GSC/GA4, content quality |
|
|
@@ -161,13 +161,10 @@ separate final confirmation. Use the following groups for the conversation:
|
|
|
161
161
|
4. **Content and publishing:** initial routes, API Pull, sitemap matching,
|
|
162
162
|
rewrite approval, analytics, GSC, and whether the first run is dry-run.
|
|
163
163
|
|
|
164
|
-
5. **Operations:**
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
authentication, role checks, and noindex/robots protection. This is enabled
|
|
169
|
-
by default and is required for a completed bootstrap unless the user
|
|
170
|
-
explicitly chooses a different operating model.
|
|
164
|
+
5. **Operations handoff:** decide whether the project needs the private Maggie
|
|
165
|
+
Ops dashboard now. If yes, hand off to `maggie-ops`; do not silently build a
|
|
166
|
+
partial admin surface inside bootstrap. If no, record Ops as pending while
|
|
167
|
+
completing the public blog foundation.
|
|
171
168
|
|
|
172
169
|
Show the proposed choices, detected evidence, files likely to change, and
|
|
173
170
|
unknowns for each gate. If the user confirms only part of a gate, implement
|
|
@@ -224,9 +221,9 @@ Implement the host project's equivalent of:
|
|
|
224
221
|
- JSON-LD `Article` or `BlogPosting` with valid dates and image URLs;
|
|
225
222
|
- GA4 page view/event hooks that do nothing when analytics is disabled;
|
|
226
223
|
- GSC verification via a public token or DNS instruction, never a private key.
|
|
227
|
-
-
|
|
228
|
-
|
|
229
|
-
|
|
224
|
+
- an explicit Ops decision and handoff to `maggie-ops` when private content
|
|
225
|
+
operations are requested; the Ops dashboard is not satisfied by a mock or
|
|
226
|
+
partial bootstrap screen.
|
|
230
227
|
|
|
231
228
|
### Phase 6: Optional AI CMO integration
|
|
232
229
|
|
|
@@ -39,9 +39,12 @@ variant. If the user supplies an interior page, stop and route the request to
|
|
|
39
39
|
- Use real public assets only when the user is authorized to reproduce them.
|
|
40
40
|
Preserve attribution or licensing requirements and report assets that could
|
|
41
41
|
not be safely reused.
|
|
42
|
-
-
|
|
43
|
-
component namespace, asset namespace, or research artifact
|
|
44
|
-
|
|
42
|
+
- A supplied homepage URL is always a create or update request. If the
|
|
43
|
+
homepage route, component namespace, asset namespace, or research artifact
|
|
44
|
+
already exists, inspect it and reconcile/regenerate the requested target;
|
|
45
|
+
never silently skip it because output exists. Preserve unrelated local
|
|
46
|
+
changes and report changed, preserved, and conflicted files. Explicit
|
|
47
|
+
approval is still required for unrelated shared-foundation changes.
|
|
45
48
|
- The homepage header and footer become the shared shell source of truth. Record
|
|
46
49
|
their component paths, tokens, breakpoints, states, and asset dependencies so
|
|
47
50
|
later design pages never fork them.
|
|
@@ -1,15 +1,18 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: maggie-design
|
|
3
|
-
description:
|
|
3
|
+
description: Fully clone authorized interior pages, then reconcile their header and footer to the Maggie homepage shell. Use with /maggie-design plus one or more target URLs for pricing, about, feature, landing, or other non-homepage pages.
|
|
4
4
|
metadata:
|
|
5
|
-
version: 1.
|
|
5
|
+
version: 1.1.0
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
# Maggie Design
|
|
9
9
|
|
|
10
10
|
Create authorized interior pages inside an existing Maggie project. This is
|
|
11
|
-
the page
|
|
12
|
-
|
|
11
|
+
the interior-page companion to `maggie-clone`, but it is not a shortened
|
|
12
|
+
content-only clone. For every supplied URL, first execute the complete clone
|
|
13
|
+
workflow and create a full first-pass page, including the target's header and
|
|
14
|
+
footer. Then reconcile the page to the already-cloned homepage shell so that
|
|
15
|
+
only the page-specific content remains different.
|
|
13
16
|
|
|
14
17
|
Invoke it as:
|
|
15
18
|
|
|
@@ -17,22 +20,40 @@ Invoke it as:
|
|
|
17
20
|
/maggie-design <target-url1> [<target-url2> ...]
|
|
18
21
|
```
|
|
19
22
|
|
|
23
|
+
Create the execution contract before browser research:
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
python3 tools/clis/maggie_design.py <target-url1> [<target-url2> ...] \\
|
|
27
|
+
--project <project-root> --save
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
The contract is non-skippable. For every supplied URL, execute every phase in
|
|
31
|
+
`required_phases` in order. `operation` is `create` or `update-regenerate`;
|
|
32
|
+
existing routes, artifacts, or screenshots never change a URL into a skip.
|
|
33
|
+
|
|
34
|
+
Every URL is a required work item. A URL that already has a route, component,
|
|
35
|
+
or research directory means update/regenerate that target; it must never be
|
|
36
|
+
silently skipped because output already exists.
|
|
37
|
+
|
|
20
38
|
## Hard boundaries
|
|
21
39
|
|
|
22
40
|
- Require a completed `.maggie/bootstrap-state.json` and a completed homepage
|
|
23
41
|
foundation from `maggie-clone`. If either is missing, stop and request it.
|
|
24
42
|
- Reject the origin homepage as a target. Use `maggie-clone` for that job.
|
|
25
|
-
-
|
|
26
|
-
|
|
43
|
+
- The target is initially cloned as a complete page. After that first pass,
|
|
44
|
+
replace its header and footer with the homepage's canonical shared shell.
|
|
45
|
+
Reuse the homepage component, tokens, navigation, logo, fonts, breakpoints,
|
|
27
46
|
responsive behavior, accessibility behavior, analytics hooks, and footer
|
|
28
|
-
links. Do not
|
|
29
|
-
-
|
|
30
|
-
pricing/features, testimonials, FAQs,
|
|
31
|
-
interactions. Do not copy credentials,
|
|
32
|
-
authentication, checkout logic, or proprietary
|
|
47
|
+
links. Do not leave a target-specific shell in the final route.
|
|
48
|
+
- The final page-specific scope is the content between the shared shell:
|
|
49
|
+
hero, sections, cards, forms, pricing/features, testimonials, FAQs,
|
|
50
|
+
conversion blocks, and page-specific interactions. Do not copy credentials,
|
|
51
|
+
private data, tracking IDs, authentication, checkout logic, or proprietary
|
|
52
|
+
backend behavior.
|
|
33
53
|
- Keep each page in its own route and component namespace. Existing blog,
|
|
34
|
-
homepage, metadata, sitemap, robots, and Ops routes remain unchanged
|
|
35
|
-
the
|
|
54
|
+
homepage, metadata, sitemap, robots, and Ops routes remain unchanged except
|
|
55
|
+
for the explicitly requested target route update. Preserve unrelated local
|
|
56
|
+
changes, but do not convert an existing target route into a no-op.
|
|
36
57
|
|
|
37
58
|
## Phase 0: Preflight and decision loop
|
|
38
59
|
|
|
@@ -45,8 +66,9 @@ python3 tools/clis/maggie.py doctor <project-root> --require-bootstrap --strict
|
|
|
45
66
|
python3 tools/clis/maggie_clone.py plan <target-url1> [<target-url2> ...] --project <project-root>
|
|
46
67
|
```
|
|
47
68
|
|
|
48
|
-
|
|
49
|
-
|
|
69
|
+
Read and follow the complete `maggie-clone` workflow before proceeding. Verify
|
|
70
|
+
the homepage foundation exists and locate its actual shared shell. The plan
|
|
71
|
+
must state, for every target:
|
|
50
72
|
|
|
51
73
|
```text
|
|
52
74
|
source URL -> destination route
|
|
@@ -54,20 +76,31 @@ homepage shell component/layout -> reused unchanged
|
|
|
54
76
|
content component namespace -> new isolated namespace
|
|
55
77
|
research and screenshots -> page-scoped directories
|
|
56
78
|
assets -> page-scoped directory; shared assets remain shared
|
|
57
|
-
|
|
79
|
+
operation -> create or update/regenerate (never skip)
|
|
80
|
+
files preserved -> all unrelated public/blog/Ops routes
|
|
58
81
|
```
|
|
59
82
|
|
|
60
83
|
Ask for confirmation of destination routes, page scope, asset reuse, and any
|
|
61
84
|
requested CTA/form behavior before mutation. Interior pages do not silently
|
|
62
|
-
become published posts or sitemap entries.
|
|
85
|
+
become published posts or sitemap entries. Confirmation authorizes processing
|
|
86
|
+
each listed URL, including an existing route; it does not authorize unrelated
|
|
87
|
+
route changes.
|
|
88
|
+
|
|
89
|
+
## Phase 1: Complete clone reconnaissance
|
|
63
90
|
|
|
64
|
-
|
|
91
|
+
This phase is the full `maggie-clone` reconnaissance contract applied to the
|
|
92
|
+
interior URL. Do not replace it with a content-only scrape. The target header
|
|
93
|
+
and footer are deliberately captured and implemented in the first pass even
|
|
94
|
+
though they will be replaced later.
|
|
65
95
|
|
|
66
96
|
Use the available browser/Chrome/Playwright capability. Capture desktop
|
|
67
|
-
1440px, tablet 768px, and mobile 390px.
|
|
68
|
-
|
|
69
|
-
|
|
97
|
+
1440px, tablet 768px, and mobile 390px. Run the same full reconnaissance
|
|
98
|
+
contract as `maggie-clone`, including the target header and footer. They must
|
|
99
|
+
be captured because the first-pass clone needs complete evidence before the
|
|
100
|
+
shell is reconciled. Record:
|
|
70
101
|
|
|
102
|
+
- full page topology, including header, footer, sticky layers, and shell
|
|
103
|
+
transitions;
|
|
71
104
|
- content topology and section order;
|
|
72
105
|
- exact visible copy, links, labels, images, forms, and public states;
|
|
73
106
|
- content-area typography, spacing, colors, borders, radii, shadows, and
|
|
@@ -92,13 +125,29 @@ docs/design-references/<site-key>/<page-key>/
|
|
|
92
125
|
desktop.png tablet.png mobile.png
|
|
93
126
|
```
|
|
94
127
|
|
|
95
|
-
Every new component spec must
|
|
96
|
-
|
|
128
|
+
Every new component spec must initially document the full target component,
|
|
129
|
+
then include a reconciliation note naming the homepage shell source file and
|
|
130
|
+
the final content-only target file and states.
|
|
97
131
|
|
|
98
|
-
## Phase 2: Build the
|
|
132
|
+
## Phase 2: Build the complete first-pass page
|
|
99
133
|
|
|
100
|
-
|
|
101
|
-
|
|
134
|
+
The first pass is a real full clone, not a mock, analysis-only artifact, or
|
|
135
|
+
shell-free approximation. It must contain the target header, target footer,
|
|
136
|
+
page content, responsive behavior, assets, and observed interactions.
|
|
137
|
+
|
|
138
|
+
Build the target page from the full clone evidence, including its observed
|
|
139
|
+
header, footer, responsive shell, assets, and interactions. This first pass is
|
|
140
|
+
required even when the final result will replace the shell. For an existing
|
|
141
|
+
target route, inspect the current implementation, calculate the update plan,
|
|
142
|
+
and regenerate/reconcile that route; report changed and preserved files.
|
|
143
|
+
|
|
144
|
+
Do not report `already exists` as a completion state and do not skip browser
|
|
145
|
+
research, asset checks, or verification for an existing URL.
|
|
146
|
+
|
|
147
|
+
## Phase 3: Reconcile to the homepage shell
|
|
148
|
+
|
|
149
|
+
After the complete first pass, make the homepage shell the sole source of
|
|
150
|
+
truth. Put page-specific output under an isolated namespace, for example:
|
|
102
151
|
|
|
103
152
|
```text
|
|
104
153
|
src/components/sites/<site-key>/<page-key>/
|
|
@@ -106,7 +155,25 @@ src/pages/<approved-route>.*
|
|
|
106
155
|
public/sites/<site-key>/<page-key>/
|
|
107
156
|
```
|
|
108
157
|
|
|
109
|
-
|
|
158
|
+
Perform this reconciliation explicitly:
|
|
159
|
+
|
|
160
|
+
1. Identify the generated target header/footer and the homepage header/footer
|
|
161
|
+
components, layout wrappers, tokens, assets, and behavior contracts.
|
|
162
|
+
2. Replace the generated target shell with imports/composition from the
|
|
163
|
+
homepage source of truth. Do not copy its markup into the page namespace.
|
|
164
|
+
3. Remove target-only shell styles, duplicate logo/font/icon assets, and
|
|
165
|
+
duplicate navigation/footer links from the final page bundle.
|
|
166
|
+
4. Keep the target's route-specific content and interactions inside the
|
|
167
|
+
content region. A global token or shared-shell change requires explicit
|
|
168
|
+
approval.
|
|
169
|
+
5. Verify the resulting DOM has one header and one footer, with the target
|
|
170
|
+
content between them and no hidden duplicate shell.
|
|
171
|
+
|
|
172
|
+
This is a replacement step after the first pass, never a substitute for it.
|
|
173
|
+
The final implementation must not retain the target header/footer as an
|
|
174
|
+
alternative path or silently fall back to them when the homepage shell exists.
|
|
175
|
+
|
|
176
|
+
The final page must:
|
|
110
177
|
|
|
111
178
|
- render inside the exact homepage shell and use its skip link, landmarks,
|
|
112
179
|
navigation, footer, fonts, and responsive breakpoints;
|
|
@@ -120,16 +187,16 @@ The page must:
|
|
|
120
187
|
If a page needs a new global navigation item, footer link, font, token, or
|
|
121
188
|
shared component change, stop, show the impact, and obtain explicit approval.
|
|
122
189
|
|
|
123
|
-
## Phase
|
|
190
|
+
## Phase 4: Verify
|
|
124
191
|
|
|
125
192
|
For every target:
|
|
126
193
|
|
|
127
194
|
1. Run the host build, typecheck/lint, and `maggie doctor --strict` gates.
|
|
128
195
|
2. Verify the exact destination route, homepage route, blog routes, 404,
|
|
129
196
|
robots, sitemap exclusion/inclusion, canonical metadata, and JSON-LD.
|
|
130
|
-
3. Compare
|
|
131
|
-
|
|
132
|
-
|
|
197
|
+
3. Compare the complete first-pass clone to the target at 1440px, 768px, and
|
|
198
|
+
390px. Then compare the final page shell to the homepage and compare only
|
|
199
|
+
the final content region to the target for page fidelity.
|
|
133
200
|
4. Sweep keyboard focus, links, forms, hover, tabs/dialogs, scroll behavior,
|
|
134
201
|
mobile menu, and reduced-motion behavior.
|
|
135
202
|
5. Run `python3 tools/clis/site_audit.py <local-or-production-url> --json`.
|
|
@@ -139,8 +206,9 @@ target could not be inspected. Report measured differences and limitations.
|
|
|
139
206
|
|
|
140
207
|
## Completion report
|
|
141
208
|
|
|
142
|
-
Report target-to-route mappings,
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
209
|
+
Report every input URL and its create/update result, target-to-route mappings,
|
|
210
|
+
the full first-pass artifacts, reused homepage shell files, removed duplicate
|
|
211
|
+
shell artifacts, final content-only components, research/screenshots, assets,
|
|
212
|
+
preserved unrelated routes, commands and test results, visual QA status, and
|
|
213
|
+
any requested global changes pending approval. Deployment, publishing, API
|
|
214
|
+
Pull, and rewrite operations are separate actions.
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: maggie-ops
|
|
3
|
+
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.
|
|
4
|
+
metadata:
|
|
5
|
+
version: 1.0.0
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Maggie Ops
|
|
9
|
+
|
|
10
|
+
Manage the private operational surface for a Maggie blog. This skill is
|
|
11
|
+
separate from `maggie-blog-bootstrap`: bootstrap establishes the public blog
|
|
12
|
+
contract, while Maggie Ops establishes the authenticated editor and operations
|
|
13
|
+
contract around it.
|
|
14
|
+
|
|
15
|
+
Invoke it as:
|
|
16
|
+
|
|
17
|
+
```text
|
|
18
|
+
/maggie-ops <audit|install|connect|operate|upgrade|verify>
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
If the user does not name a mode, inspect the project and propose the smallest
|
|
22
|
+
mode that satisfies the request. Do not rebuild the public blog or change its
|
|
23
|
+
framework just to add Ops.
|
|
24
|
+
|
|
25
|
+
## Required preflight
|
|
26
|
+
|
|
27
|
+
1. Inspect `.maggie/analysis.json` and `.maggie/bootstrap-state.json`.
|
|
28
|
+
2. Read [`ops-dashboard-contract.md`](../../references/ops-dashboard-contract.md).
|
|
29
|
+
3. Inventory existing private routes, session/auth middleware, role checks,
|
|
30
|
+
API proxy routes, content tables, audit events, robots, and deployment
|
|
31
|
+
configuration.
|
|
32
|
+
4. Run the host's existing typecheck, test, and build commands before editing.
|
|
33
|
+
5. State which mode is being run, which routes/API resources it will touch,
|
|
34
|
+
and whether any operation can consume quota or change production state.
|
|
35
|
+
|
|
36
|
+
Do not proceed with a production mutation when authentication, ownership,
|
|
37
|
+
role authorization, secret configuration, or rollback information is unknown.
|
|
38
|
+
|
|
39
|
+
## Modes
|
|
40
|
+
|
|
41
|
+
### Audit
|
|
42
|
+
|
|
43
|
+
Produce a gap report against the Ops contract. Check the actual rendered
|
|
44
|
+
screens and server routes, not just documentation. Classify every item as
|
|
45
|
+
implemented, partial, missing, or unverifiable. Include:
|
|
46
|
+
|
|
47
|
+
- dashboard/list/editor/detail screens and responsive states;
|
|
48
|
+
- session authentication, role authorization, CSRF/input validation, and
|
|
49
|
+
server-only secret handling;
|
|
50
|
+
- content inventory and identity editing;
|
|
51
|
+
- API Pull status, project context, delivery state, and idempotency;
|
|
52
|
+
- sitemap sources, matching runs, unmatched URLs, matched assets, and history;
|
|
53
|
+
- rewrite queue, preview quota reservation, approval/rejection transitions;
|
|
54
|
+
- reports, GSC/GA4/provider health, audit events, noindex, and robots rules.
|
|
55
|
+
|
|
56
|
+
### Install
|
|
57
|
+
|
|
58
|
+
Add or complete the private Ops surface in the existing project. Follow the
|
|
59
|
+
host's UI system and routing conventions, but use the EmDash-style information
|
|
60
|
+
architecture as the baseline:
|
|
61
|
+
|
|
62
|
+
```text
|
|
63
|
+
/ops dashboard and pending actions
|
|
64
|
+
/ops/posts paginated content list
|
|
65
|
+
/ops/posts/[id]/edit validated editor
|
|
66
|
+
/ops/posts/[id]/preview noindex preview
|
|
67
|
+
/ops/sitemap sources, match runs, history, eligibility
|
|
68
|
+
/ops/reports SEO, GEO, visibility, analytics
|
|
69
|
+
/ops/settings/integrations Maggie API and provider health
|
|
70
|
+
/ops/operations calendar, tasks, media, redirects, agency work
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
Use a clean list → detail/editor journey, outlined cards, clear status
|
|
74
|
+
chips, predictable spacing, explicit loading/empty/error states, and a
|
|
75
|
+
desktop/mobile layout consistent with the reference admin product. Do not
|
|
76
|
+
ship a mock table whose buttons do not reach a server route.
|
|
77
|
+
|
|
78
|
+
### Connect
|
|
79
|
+
|
|
80
|
+
Wire the dashboard to real backend contracts. Prefer the first-party Maggie
|
|
81
|
+
API or a narrowly scoped server-side Ops bridge. The browser may call only
|
|
82
|
+
the project's authenticated proxy; Maggie/API secrets must remain server-side.
|
|
83
|
+
|
|
84
|
+
At minimum, verify real readbacks for:
|
|
85
|
+
|
|
86
|
+
- content assets and versions/identity;
|
|
87
|
+
- pull runs and delivery status;
|
|
88
|
+
- sitemap sources and matching runs;
|
|
89
|
+
- rewrite jobs and action state;
|
|
90
|
+
- project context and CTA/settings data.
|
|
91
|
+
|
|
92
|
+
Every mutation must validate the session, role, resource ownership/project
|
|
93
|
+
scope, input schema, legal state transition, and idempotency/correlation key.
|
|
94
|
+
Record actor, timestamp, previous state, next state, reason, and result.
|
|
95
|
+
|
|
96
|
+
### Operate
|
|
97
|
+
|
|
98
|
+
Use the dashboard or API to perform an explicitly requested operation. Show an
|
|
99
|
+
impact preview before bulk or quota-consuming work. Keep these actions
|
|
100
|
+
separate:
|
|
101
|
+
|
|
102
|
+
```text
|
|
103
|
+
read status → inspect impact → run/mutate → read back result → record audit
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
Sitemap matching must report total sitemap documents, total URLs, matched
|
|
107
|
+
posts, already matched/queued posts, not-tracked URLs, newly eligible posts,
|
|
108
|
+
and matching time. Rewrite preview reserves quota; approval is a separate
|
|
109
|
+
human action. Never silently publish, overwrite content, or enqueue a whole
|
|
110
|
+
site because a list endpoint returned data.
|
|
111
|
+
|
|
112
|
+
### Upgrade
|
|
113
|
+
|
|
114
|
+
Upgrade an existing Ops installation without losing local work:
|
|
115
|
+
|
|
116
|
+
1. read the installed version and local modifications;
|
|
117
|
+
2. compare the target contract, frontend routes, backend routes, and schema;
|
|
118
|
+
3. apply additive changes first and write migrations only when required;
|
|
119
|
+
4. preserve local UI customizations unless the user explicitly requests a
|
|
120
|
+
replacement;
|
|
121
|
+
5. run read-only verification before enabling new mutations;
|
|
122
|
+
6. report changed, preserved, conflicting, and deprecated files.
|
|
123
|
+
|
|
124
|
+
For an installed Maggie package, use:
|
|
125
|
+
|
|
126
|
+
```bash
|
|
127
|
+
npx @topy-ai/maggie update --project .
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
Use `--force` only after the user explicitly approves replacing locally
|
|
131
|
+
modified managed files. An npm skill update does not automatically deploy the
|
|
132
|
+
dashboard or migrate a production database.
|
|
133
|
+
|
|
134
|
+
### Verify
|
|
135
|
+
|
|
136
|
+
Run the host build/test/typecheck gates and verify the actual private routes
|
|
137
|
+
with an authenticated session. Test at least:
|
|
138
|
+
|
|
139
|
+
- unauthenticated and non-admin denial;
|
|
140
|
+
- list, detail, editor save, and validation errors;
|
|
141
|
+
- API Pull readback and stale/error states;
|
|
142
|
+
- sitemap matching with zero, partial, and complete matches;
|
|
143
|
+
- rewrite preview, approval, rejection, retry, and quota failure;
|
|
144
|
+
- refresh/idempotency behavior and audit records;
|
|
145
|
+
- `noindex`, robots blocking, and exclusion from public sitemap;
|
|
146
|
+
- desktop and mobile layout against the EmDash-style design baseline.
|
|
147
|
+
|
|
148
|
+
Do not claim an API is connected because a frontend button rendered. Show the
|
|
149
|
+
endpoint, response status, persisted state, and verification command.
|
|
150
|
+
|
|
151
|
+
## Stop conditions
|
|
152
|
+
|
|
153
|
+
Stop before a write when the user has not authorized it, the project scope is
|
|
154
|
+
ambiguous, the endpoint is only proposed/documented rather than reachable,
|
|
155
|
+
the admin identity cannot be verified, the operation would expose a secret,
|
|
156
|
+
or a migration/rollback plan is missing.
|
|
157
|
+
|
|
158
|
+
## Completion report
|
|
159
|
+
|
|
160
|
+
Report the mode, screens and endpoints implemented, authentication/ownership
|
|
161
|
+
boundary, quota impact, database/migration status, audit behavior, preserved
|
|
162
|
+
local changes, commands and live/readback checks, remaining gaps, and whether
|
|
163
|
+
deployment was actually performed.
|
|
@@ -408,7 +408,7 @@ BOOTSTRAP_QUESTIONS = [
|
|
|
408
408
|
("content_source", "Where should posts be stored?", ["preserve", "local-content", "database", "api-pull"]),
|
|
409
409
|
("posts_per_page", "How many posts should appear on each blog page?", ["9", "12", "6", "custom"]),
|
|
410
410
|
("grid_columns", "How many columns should the default post grid use?", ["3", "2", "4", "custom"]),
|
|
411
|
-
("ops_dashboard", "Should
|
|
411
|
+
("ops_dashboard", "Should the project add the private Maggie Ops dashboard after bootstrap?", ["disabled", "enabled"]),
|
|
412
412
|
]
|
|
413
413
|
|
|
414
414
|
|
|
@@ -416,7 +416,7 @@ def question_default(key: str, analysis: dict) -> str:
|
|
|
416
416
|
detected = analysis.get(key, {}).get("value") if isinstance(analysis.get(key), dict) else None
|
|
417
417
|
if key == "posts_per_page": return "9"
|
|
418
418
|
if key == "grid_columns": return "3"
|
|
419
|
-
if key == "ops_dashboard": return "
|
|
419
|
+
if key == "ops_dashboard": return "disabled"
|
|
420
420
|
return detected or {"ui_system": "preserve-or-tailwind", "icon_set": "preserve-or-heroicons", "font": "preserve-or-system", "database": "preserve-or-sqlite"}.get(key, "detected")
|
|
421
421
|
|
|
422
422
|
|
|
@@ -703,7 +703,7 @@ def parser() -> argparse.ArgumentParser:
|
|
|
703
703
|
complete.add_argument("--" + name, dest=name.replace("-", "_"), default=default)
|
|
704
704
|
complete.add_argument("--posts-per-page", type=int, default=9)
|
|
705
705
|
complete.add_argument("--grid-columns", type=int, default=3)
|
|
706
|
-
complete.add_argument("--ops-dashboard", action=argparse.BooleanOptionalAction, default=
|
|
706
|
+
complete.add_argument("--ops-dashboard", action=argparse.BooleanOptionalAction, default=False)
|
|
707
707
|
complete.set_defaults(func=command_complete)
|
|
708
708
|
generate = sub.add_parser("generate", help="generate stable contract or fixture files")
|
|
709
709
|
generate.add_argument("target", choices=["contract", "fixture", "post", "topic", "author", "migration", "seo", "ops-page"])
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Create a non-skippable execution contract for Maggie interior-page design.
|
|
3
|
+
|
|
4
|
+
This command does not fetch a site or edit the host project. It gives an
|
|
5
|
+
agent a machine-readable checklist so an interior URL cannot accidentally be
|
|
6
|
+
treated as a content-only clone or skipped because output already exists.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
import argparse
|
|
12
|
+
import json
|
|
13
|
+
from pathlib import Path
|
|
14
|
+
from urllib.parse import urlsplit
|
|
15
|
+
|
|
16
|
+
from maggie_clone import normalized, plan
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
PHASES = [
|
|
20
|
+
{
|
|
21
|
+
"id": "preflight",
|
|
22
|
+
"required": [
|
|
23
|
+
"bootstrap-state",
|
|
24
|
+
"homepage-shell",
|
|
25
|
+
"host-inventory",
|
|
26
|
+
"baseline-validation",
|
|
27
|
+
],
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
"id": "full-research",
|
|
31
|
+
"required": [
|
|
32
|
+
"desktop-1440",
|
|
33
|
+
"tablet-768",
|
|
34
|
+
"mobile-390",
|
|
35
|
+
"target-header",
|
|
36
|
+
"target-footer",
|
|
37
|
+
"assets",
|
|
38
|
+
"interactions",
|
|
39
|
+
"component-specs",
|
|
40
|
+
],
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
"id": "full-first-pass",
|
|
44
|
+
"required": [
|
|
45
|
+
"target-header",
|
|
46
|
+
"target-footer",
|
|
47
|
+
"page-content",
|
|
48
|
+
"responsive-behavior",
|
|
49
|
+
"target-interactions",
|
|
50
|
+
],
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
"id": "shell-reconciliation",
|
|
54
|
+
"required": [
|
|
55
|
+
"replace-target-header-with-homepage-shell",
|
|
56
|
+
"replace-target-footer-with-homepage-shell",
|
|
57
|
+
"remove-duplicate-shell-assets-and-styles",
|
|
58
|
+
"one-header-and-one-footer",
|
|
59
|
+
],
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
"id": "verification",
|
|
63
|
+
"required": [
|
|
64
|
+
"build-typecheck-lint",
|
|
65
|
+
"route-and-404",
|
|
66
|
+
"metadata-robots-sitemap-jsonld",
|
|
67
|
+
"shell-regression",
|
|
68
|
+
"desktop-tablet-mobile-comparison",
|
|
69
|
+
"site-audit",
|
|
70
|
+
],
|
|
71
|
+
},
|
|
72
|
+
]
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def existing_evidence(project: Path, target: dict[str, str]) -> list[str]:
|
|
76
|
+
"""Return evidence paths without deciding that any work can be skipped."""
|
|
77
|
+
|
|
78
|
+
candidates = [
|
|
79
|
+
Path(target["artifact_root"]),
|
|
80
|
+
Path(target["screenshot_root"]),
|
|
81
|
+
Path(target["component_root"]),
|
|
82
|
+
Path(target["asset_root"]),
|
|
83
|
+
]
|
|
84
|
+
route = target["destination_route"].strip("/") or "root"
|
|
85
|
+
for base in (project / "src" / "app", project / "src" / "pages"):
|
|
86
|
+
if base.exists():
|
|
87
|
+
candidates.extend(
|
|
88
|
+
path
|
|
89
|
+
for path in base.rglob("*")
|
|
90
|
+
if path.is_file() and route.lower() in str(path).lower()
|
|
91
|
+
)
|
|
92
|
+
return sorted({str(path) for path in candidates if path.exists()})
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def design_plan(urls: list[str], project: Path) -> dict[str, object]:
|
|
96
|
+
targets = []
|
|
97
|
+
for target in plan(urls, project):
|
|
98
|
+
parsed = urlsplit(target["source_url"])
|
|
99
|
+
if parsed.path in {"", "/"}:
|
|
100
|
+
raise ValueError(
|
|
101
|
+
f"homepage URL is not valid for maggie-design: {target['source_url']} "
|
|
102
|
+
"(use maggie-clone)"
|
|
103
|
+
)
|
|
104
|
+
evidence = existing_evidence(project, target)
|
|
105
|
+
targets.append(
|
|
106
|
+
{
|
|
107
|
+
**target,
|
|
108
|
+
"operation": "update-regenerate" if evidence else "create",
|
|
109
|
+
"input_url_is_required_work_item": True,
|
|
110
|
+
"skip_allowed": False,
|
|
111
|
+
"existing_evidence": evidence,
|
|
112
|
+
"required_phases": PHASES,
|
|
113
|
+
"shell_source_of_truth": {
|
|
114
|
+
"must_resolve_before_build": True,
|
|
115
|
+
"must_be_reused_in_final_page": True,
|
|
116
|
+
"target_shell_allowed_in_final_page": False,
|
|
117
|
+
},
|
|
118
|
+
}
|
|
119
|
+
)
|
|
120
|
+
return {
|
|
121
|
+
"workflow": "maggie-design",
|
|
122
|
+
"contract_version": "1.0",
|
|
123
|
+
"project_root": str(project),
|
|
124
|
+
"non_skippable": True,
|
|
125
|
+
"rule": "Every supplied URL is processed through all required phases; existing output changes the operation to update-regenerate, never skip.",
|
|
126
|
+
"targets": targets,
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
def main() -> int:
|
|
131
|
+
parser = argparse.ArgumentParser(description=__doc__)
|
|
132
|
+
parser.add_argument("urls", nargs="+", help="authorized interior-page URLs")
|
|
133
|
+
parser.add_argument("--project", type=Path, default=Path.cwd())
|
|
134
|
+
parser.add_argument("--save", action="store_true", help="save .maggie/design-plan.json")
|
|
135
|
+
args = parser.parse_args()
|
|
136
|
+
try:
|
|
137
|
+
project = args.project.resolve()
|
|
138
|
+
result = design_plan(args.urls, project)
|
|
139
|
+
except ValueError as error:
|
|
140
|
+
parser.error(str(error))
|
|
141
|
+
encoded = json.dumps(result, indent=2, ensure_ascii=False) + "\n"
|
|
142
|
+
if args.save:
|
|
143
|
+
destination = project / ".maggie" / "design-plan.json"
|
|
144
|
+
destination.parent.mkdir(parents=True, exist_ok=True)
|
|
145
|
+
destination.write_text(encoded, encoding="utf-8")
|
|
146
|
+
result["saved_to"] = str(destination)
|
|
147
|
+
encoded = json.dumps(result, indent=2, ensure_ascii=False) + "\n"
|
|
148
|
+
print(encoded, end="")
|
|
149
|
+
return 0
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
if __name__ == "__main__":
|
|
153
|
+
raise SystemExit(main())
|