@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 CHANGED
@@ -15,6 +15,7 @@ const SKILL_NAMES = [
15
15
  "maggie-blog-bootstrap",
16
16
  "maggie-clone",
17
17
  "maggie-design",
18
+ "maggie-ops",
18
19
  "maggie-deployment",
19
20
  "maggie-project-context",
20
21
  "maggie-seo-geo",
@@ -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` | Build authorized interior pages using the homepage header/footer as the shared shell | browser MCP, clone planner CLI, completed Maggie homepage |
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:** enable the complete private Maggie Ops dashboard, including
165
- content inventory/editor/preview, topics and FAQs, sitemap matching and
166
- history, rewrite/API Pull controls, reports, settings/integrations,
167
- migrations, calendar, media, redirects, tasks, agency scope, audit events,
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
- - a complete private Ops dashboard following
228
- [`ops-dashboard-contract.md`](../../references/ops-dashboard-contract.md),
229
- backed by the same repository as public reads; do not ship a mock-only Ops UI.
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
- - The clone is an additive homepage operation. Do not overwrite an existing route,
43
- component namespace, asset namespace, or research artifact without explicit
44
- approval.
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: Design or recreate authorized interior pages inside a Maggie blog while reusing the cloned homepage header and footer exactly. Use with /maggie-design plus one or more target URLs for pricing, about, feature, landing, or other non-homepage pages.
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.0.0
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-design companion to `maggie-clone`: the homepage establishes the
12
- global shell, and this skill designs only the content area between that shell.
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
- - Treat the homepage header and footer as immutable shared layout boundaries.
26
- Reuse their component, tokens, navigation, logo, fonts, breakpoints,
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 restyle, duplicate, or fork them for an interior page.
29
- - Clone only the target's content region: hero, sections, cards, forms,
30
- pricing/features, testimonials, FAQs, conversion blocks, and page-specific
31
- interactions. Do not copy credentials, private data, tracking IDs,
32
- authentication, checkout logic, or proprietary backend behavior.
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 unless
35
- the user explicitly approves a shared-shell change.
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
- Verify the homepage foundation exists and locate its actual shared shell. The
49
- plan must state, for every target:
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
- files preserved -> all existing public/blog/Ops routes
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
- ## Phase 1: Content-area reconnaissance
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. Inspect the target with the global
68
- header and footer excluded from the page scope after verifying their local
69
- equivalent. Record:
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 explicitly say: `header: reuse homepage`,
96
- `footer: reuse homepage`, and list the content-only target file and states.
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 content area
132
+ ## Phase 2: Build the complete first-pass page
99
133
 
100
- Build the page using the host framework and the homepage's shared layout
101
- component. Put page-specific output under an isolated namespace, for example:
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
- The page must:
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 3: Verify
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 local and target screenshots at 1440px, 768px, and 390px. Compare
131
- the header/footer separately to prove they are the same local components,
132
- then compare only the content region for page fidelity.
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, the reused homepage shell files, new
143
- content-only components, research/screenshots, assets, preserved routes,
144
- commands and test results, visual QA status, and any requested global changes
145
- that remain pending approval. Deployment, publishing, API Pull, and rewrite
146
- operations are separate actions.
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.
@@ -0,0 +1,4 @@
1
+ interface:
2
+ display_name: "Maggie Ops"
3
+ short_description: "Build and operate Maggie blog admin workflows"
4
+ default_prompt: "Use $maggie-ops to audit and connect this project's private blog operations dashboard."
@@ -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 bootstrap implement the complete private Maggie Ops dashboard?", ["enabled", "disabled"]),
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 "enabled"
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=True)
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())
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@topy-ai/maggie",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "description": "Install and manage Maggie Skills for AI coding agents",
5
5
  "license": "MIT",
6
6
  "type": "module",