@topy-ai/maggie 0.7.12 → 0.7.14

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.md CHANGED
@@ -58,7 +58,23 @@ Then invoke the installed skills from your coding agent, for example:
58
58
 
59
59
  Maggie keeps the existing project foundation and asks for decisions before
60
60
  shared routes, analytics, or publishing boundaries change. The current
61
- package ships 18 installable skills and a local-first MaggieDash foundation.
61
+ package ships 19 installable skills and a local-first MaggieDash foundation.
62
+
63
+ For repeatable browser QA, create a project-owned scenario manifest and record
64
+ the test, fix, and retest lifecycle:
65
+
66
+ ```bash
67
+ maggie qa start --project . \
68
+ --scenario-file .maggie/scenario-manifest.json \
69
+ --environment local --base-url http://localhost:4321
70
+ maggie qa record --project . --run <run-id> \
71
+ --scenario HOME-001 --phase test --status pass \
72
+ --summary "Homepage smoke passed" --evidence .maggie/qa/home.png
73
+ maggie qa summary --project . --run <run-id>
74
+ ```
75
+
76
+ The QA workflow stores secret-free run state under `.maggie/qa-runs/` and
77
+ keeps project-specific scenarios and evidence outside the npm package.
62
78
 
63
79
  For Google integrations, validate a redacted provider matrix before reporting
64
80
  access. The command fails closed on unknown scopes, missing Ads prerequisites,
@@ -104,7 +120,8 @@ maggie bootstrap interview | phase ...
104
120
  maggie dash install | init | status | migrate | cms ...
105
121
  maggie dash transition ... # explicit content approval transition
106
122
  maggie dash variant ... # service variant create/review/preview/publish
107
- maggie dash sections ... # validate/catalogue/identity keys
123
+ maggie dash sections ... # field fan-out, locale, binding, media, copy, identity keys
124
+ maggie dash inventory ... # disjoint published-page inventory
108
125
  maggie agent-content write ... # host-authorized, origin-bound content bridge
109
126
  maggie verification coverage ... # changed surface/locale evidence gate
110
127
  maggie clone ... # authorized homepage capture
@@ -113,12 +130,14 @@ maggie clone-to-template ... # URL → validated marketplace template
113
130
  maggie marketplace ... # catalog and on-demand template workflow
114
131
  maggie memory ... # confirmed preferences and lessons
115
132
  maggie feedback ... # redact, preview, submit, list
133
+ maggie qa ... # scenario browser QA, fix/retest, release gate
116
134
  maggie localization ... # plan, validate, review, publish, stale
117
135
  maggie service ... # import, sync, generate, validate
118
136
  maggie seo performance ... # sampled PageSpeed/CWV report and baseline
119
137
  maggie seo images ... # inventory, variants, confirmation, validate
120
138
  maggie seo sitemap ... # typed/semantic plan, agent-files, apply, rollback
121
139
  maggie deployment | migration | release | analytics | schedule
140
+ maggie migration identity --identity-file FILE [--expected-file FILE]
122
141
  maggie deployment canary --asset URL=SHA256 --render-report report.json
123
142
  maggie design icon-inventory --source-dir src --runtime assets/icons.css
124
143
  maggie api lifecycle | site-audit | ops audit
@@ -218,8 +237,8 @@ artifact schemas.
218
237
  Recommended upgrade sequence for the current release:
219
238
 
220
239
  ```bash
221
- npx @topy-ai/maggie@0.7.12 update --project . --force
222
- npx @topy-ai/maggie@0.7.12 cleanup --project .
240
+ npx @topy-ai/maggie@0.7.14 update --project . --force
241
+ npx @topy-ai/maggie@0.7.14 cleanup --project .
223
242
  ```
224
243
 
225
244
  Maintainers should pass npm credentials through the repository helper, never
@@ -229,7 +248,14 @@ as a command-line argument:
229
248
  node scripts/publish-npm.mjs --maggie-env-file ../.env
230
249
  ```
231
250
 
232
- The 0.7.12 workflow adds served-content equivalence checks, query-route
251
+ The 0.7.14 workflow adds the general `maggie-qa-workflow` skill and `maggie qa`
252
+ CLI for scenario manifests, secret-free browser evidence metadata, test/fix/
253
+ retest lifecycle, adjacent regression checks, and explicit release gates. The
254
+ 0.7.13 workflow adds field-aware section fan-out and locale coverage,
255
+ sibling-copy/media checks, disjoint page inventory, binding validation,
256
+ idempotency and database-target identity gates, full W3C sitemap lastmod
257
+ validation, and the accepted `X-Robots-Tag: noindex` response contract. The
258
+ 0.7.12 workflow adds served-content equivalence checks, query-route
233
259
  baseline exclusions, changed-surface render evidence gates, generated skill
234
260
  catalogs, component-binding audits, and icon-family noise filtering. It also
235
261
  includes the 0.7.9 nested section-field contracts, renderer-backed examples,
@@ -478,6 +504,7 @@ python3 tools/clis/maggie_design.py rebrand \
478
504
  | `maggie-memory` | Persist confirmed preferences, conventions, lessons, and errors |
479
505
  | `maggie-content-localization` | Manage locale-aware translation, review, provenance, stale state, and publication gates |
480
506
  | `maggie-feedback` | Collect redacted feedback drafts and explicitly submit them to the NoBlox feedback endpoint |
507
+ | `maggie-qa-workflow` | Run scenario-based browser QA with evidence, fix/retest lifecycle, and release gates |
481
508
  | `maggie-auth-reference` | Generate and validate traditional email/password auth with secure server-side sessions |
482
509
  | `maggie-blog` | Run a provider-neutral blog lifecycle with stable identity, topics, feeds, settings, and rollback |
483
510
 
@@ -514,16 +541,21 @@ maggie design section-validate --before before.json --after after.json \
514
541
  ```
515
542
 
516
543
  MaggieDash section contracts include a compact `pairs` band for factual
517
- label/value rows. Validate required values, registry fan-out, locale sidecars,
518
- and idempotent repairs with `maggie dash sections validate`,
519
- `fanout-validate`, `locale-validate`, and `reconcile`.
520
-
521
- The package includes all 18 installable skills: `maggie-blog-bootstrap`,
544
+ label/value rows. Validate required values, field-aware registry fan-out,
545
+ all locale copy fields, sibling copy/media, stored bindings, and idempotent
546
+ repairs with `maggie dash sections validate`, `fanout-validate`,
547
+ `locale-validate`, `variant-copy-validate`, `media-validate`,
548
+ `bindings-validate`, `idempotency-validate`, and `reconcile`. Use
549
+ `maggie dash inventory` to classify published pages once into disjoint kinds.
550
+ See the [quality contract examples](https://github.com/TOPY-AI-LTD/ai-cmo-skills/blob/main/contracts/maggiedash/quality-contracts.md).
551
+
552
+ The package includes all 19 installable skills: `maggie-blog-bootstrap`,
522
553
  `maggie-dash`, `maggie-clone`, `maggie-clone-to-template`, `maggie-marketplace`,
523
554
  `maggie-template`, `maggie-design`, `maggie-ops`, `maggie-deployment`,
524
555
  `maggie-project-context`, `maggie-seo-geo`, `maggie-social-share`,
525
556
  `maggie-service-booking`, `maggie-memory`, `maggie-content-localization`,
526
- `maggie-feedback`, `maggie-auth-reference`, and `maggie-blog`. Use the stable
557
+ `maggie-feedback`, `maggie-qa-workflow`, `maggie-auth-reference`, and
558
+ `maggie-blog`. Use the stable
527
559
  commands below after installation:
528
560
 
529
561
  ```bash
package/README.zh-TW.md CHANGED
@@ -2,13 +2,13 @@
2
2
 
3
3
  [English README](README.md) · [完整繁體中文 README](https://github.com/TOPY-AI-LTD/ai-cmo-skills/blob/main/README.zh-TW.md)
4
4
 
5
- `@topy-ai/maggie` 提供 18 個可安裝的 AI website workflow skills,支援
5
+ `@topy-ai/maggie` 提供 19 個可安裝的 AI website workflow skills,支援
6
6
  Codex、Claude Code 與相容的 coding agents。
7
7
 
8
8
  ## 安裝
9
9
 
10
10
  ```bash
11
- npx @topy-ai/maggie@0.7.8 init --agent all
11
+ npx @topy-ai/maggie@0.7.14 init --agent all
12
12
  npx @topy-ai/maggie doctor --project .
13
13
  ```
14
14
 
@@ -39,8 +39,24 @@ maggie deployment canary --project . \
39
39
  --asset https://example.com/assets/app.js=<sha256> \
40
40
  --render-report .maggie/rendered-canary.json \
41
41
  --output docs/deployment-canary.json
42
+
43
+ # MaggieDash section/page quality contracts
44
+ maggie dash sections fanout-validate --registry templates/maggiedash/section-registry.json \
45
+ --fanout-file templates/maggiedash/section-fanout.json
46
+ maggie dash sections variant-copy-validate --pages-file .maggie/variant-pages.json
47
+ maggie dash sections media-validate --pages-file .maggie/variant-pages.json --across-siblings
48
+ maggie dash inventory --pages-file .maggie/published-pages.json
49
+
50
+ # Migration target identity (never prints or stores a database URL)
51
+ maggie migration identity --identity-file .maggie/db-identity.json \
52
+ --expected-file .maggie/service-db-identity.json
53
+
54
+ # Scenario browser QA
55
+ maggie qa start --project . --scenario-file .maggie/scenario-manifest.json \
56
+ --environment local --base-url http://localhost:4321
57
+ maggie qa summary --project . --run <run-id>
42
58
  ```
43
59
 
44
- 完整中文說明、18 個 skills 清單和 roadmap:
60
+ 完整中文說明、19 個 skills 清單和 roadmap:
45
61
  [繁體中文 README](https://github.com/TOPY-AI-LTD/ai-cmo-skills/blob/main/README.zh-TW.md)
46
62
  · [Roadmap](https://github.com/TOPY-AI-LTD/ai-cmo-skills/blob/main/ROADMAP.md)
package/bin/maggie.js CHANGED
@@ -58,7 +58,8 @@ Usage:
58
58
  maggie doctor [--project PATH]
59
59
  maggie bootstrap interview [project]
60
60
  maggie dash init|install|status|migrate|transition|variant|cms --project PATH [options]
61
- maggie dash sections <validate|prompt|keys|remap-translations|fanout-validate|locale-validate|reconcile> [options]
61
+ maggie dash sections <validate|prompt|keys|remap-translations|fanout-validate|locale-validate|variant-copy-validate|media-validate|bindings-validate|idempotency-validate|reconcile> [options]
62
+ maggie dash inventory --pages-file FILE
62
63
  maggie dash components-audit --bindings-file FILE --sections-file FILE --pages-file FILE
63
64
  maggie dash status --project PATH
64
65
  maggie dash migrate --project PATH --confirm
@@ -104,6 +105,7 @@ Usage:
104
105
  maggie deployment --project PATH --target vps-with-cloudflare-dns
105
106
  maggie deployment canary --project PATH --asset URL=SHA256 --render-report report.json --output docs/deployment-canary.json
106
107
  maggie migration --project PATH --environment staging
108
+ maggie migration identity --identity-file FILE [--expected-file FILE]
107
109
  maggie schedule PATH/.maggie/schedule.json --project PATH
108
110
  maggie analytics [traffic-audit|release-gate] --project PATH --environment staging
109
111
  maggie release PATH --environment staging --target vps-with-cloudflare-dns
@@ -112,6 +114,7 @@ Usage:
112
114
  maggie localization <extract|plan|generate|preview|validate|review|publish|stale|glossary> [options]
113
115
  maggie seo performance|images|sitemap [options] (sitemap supports strict validate and agent-files)
114
116
  maggie feedback <collect|preview|submit|list> [options]
117
+ maggie qa <start|record|summary|export> [options]
115
118
  maggie site-audit URL [--crawl] [--access-log FILE] [--require-sitemap-request] [--languages en-GB,es-MX,ja-JP] [--check-hreflang]
116
119
  maggie site-audit URL --crawl --save-baseline FILE --reviewer NAME
117
120
  maggie site-audit URL --crawl --baseline FILE
@@ -404,6 +407,7 @@ try {
404
407
  else if (command === "memory") workflowCli("maggie_memory.py", args);
405
408
  else if (command === "localization") workflowCli("maggie_localization.py", args);
406
409
  else if (command === "feedback") workflowCli("maggie_feedback.py", args);
410
+ else if (command === "qa") workflowCli("maggie_qa_workflow.py", args);
407
411
  else if (command === "site-audit") workflowCli("site_audit.py", args);
408
412
  else if (command === "browser-audit") workflowCli("maggie_browser_audit.py", args);
409
413
  else if (command === "verification") workflowCli("maggie_verification.py", args);
@@ -24,6 +24,9 @@ frontend framework.
24
24
  for translation keys and ordered migration;
25
25
  - [`translation-cache-policy-v1.json`](translation-cache-policy-v1.json):
26
26
  restart-after-out-of-band-write evidence.
27
+ - [`quality-contracts.md`](quality-contracts.md): reviewable inputs for
28
+ disjoint page inventory, variant/media checks, binding resolution, repair
29
+ convergence, and database target identity.
27
30
 
28
31
  The section registry is an adapter input rather than a fixed six-band list.
29
32
  Each registry entry must describe its purpose and limits, include a
@@ -0,0 +1,58 @@
1
+ # MaggieDash quality contracts
2
+
3
+ These inputs are reviewable JSON evidence. They do not write a database or
4
+ publish content.
5
+
6
+ ## Page inventory
7
+
8
+ ```json
9
+ {
10
+ "pages": [
11
+ {"path": "/", "sections": [{"type": "hero"}]},
12
+ {"path": "/about", "source": "src/pages/about.astro"}
13
+ ]
14
+ }
15
+ ```
16
+
17
+ Run `maggie dash inventory --pages-file .maggie/published-pages.json`. The
18
+ result assigns each path exactly one kind and reports `bandCount` and
19
+ `codeRenderedCount`; unknown or duplicate paths fail.
20
+
21
+ ## Variant and media checks
22
+
23
+ Variant pages should provide `id`, `family`, `locale`, and either a `sections`
24
+ array or direct fields. Run `variant-copy-validate` with one or more copy field
25
+ names (the default is `faq`). Run `media-validate` for page duplicates and add
26
+ `--across-siblings` to catch shared media in one variant family.
27
+
28
+ ## Bindings
29
+
30
+ The sections file may contain a `binding` object or fields such as
31
+ `categorySlug`, `collectionId`, or `serviceRef`. The references file maps each
32
+ type to IDs, slugs, names, or values. `bindings-validate` fails when a stored
33
+ reference cannot be resolved.
34
+
35
+ ## Repair idempotency
36
+
37
+ ```json
38
+ {
39
+ "schemaVersion": "maggie-reconcile-contract.v1",
40
+ "candidateSelection": {"strategy": "all-candidates", "query": "SELECT all repair candidates"},
41
+ "compareFields": ["sections", "translations"],
42
+ "writesOnlyWhenChanged": true,
43
+ "report": {"changed": true, "unchanged": true},
44
+ "secondRun": {"convergent": true}
45
+ }
46
+ ```
47
+
48
+ `idempotency-validate` rejects a selection that only targets rows that look
49
+ unconverted. The actual adapter must still use a transaction and report its
50
+ real changed/unchanged counts.
51
+
52
+ ## Database identity
53
+
54
+ `maggie migration identity` accepts a `maggie-database-identity.v1` report with
55
+ environment, target/database name, server identity, service release identity,
56
+ row counts, and a matching SHA-256 fingerprint. It can compare a second
57
+ service-owned report. Reports must never contain a database URL, password, or
58
+ credential.
@@ -20,6 +20,7 @@ Skills are the agent-facing workflows. They compose with the tools in
20
20
  | `maggie-memory` | Persist confirmed preferences, project conventions, lessons, and error history across skill runs | local `.maggie/memory/` state |
21
21
  | `maggie-content-localization` | Plan, validate, review, publish, and age localized content with market, locale, provenance, and translation safeguards | localization contract, locale CLI |
22
22
  | `maggie-feedback` | Collect, redact, review, and explicitly submit feedback from skill runs | feedback CLI, hosted endpoint, GitHub Issue Forms |
23
+ | `maggie-qa-workflow` | Run scenario-based browser QA with evidence, fix/retest lifecycle, and release gates | browser adapter, QA workflow CLI, scenario manifest |
23
24
 
24
25
  Read only the selected skill and its linked references for a task. Do not load
25
26
  all skills as one undifferentiated prompt.
@@ -58,6 +58,10 @@
58
58
  "name": "maggie-project-context",
59
59
  "description": "Sync a site's safe AI CMO Project, selected brand voice, site settings, and CTA context into a local generated context file. Use when connecting a vibe-coded blog or existing website to AI CMO, refreshing brand context, or diagnosing missing CTA/project data."
60
60
  },
61
+ {
62
+ "name": "maggie-qa-workflow",
63
+ "description": "Run scenario-based browser QA with explicit evidence, fix/retest lifecycle, and release-gate decisions for web projects."
64
+ },
61
65
  {
62
66
  "name": "maggie-seo-geo",
63
67
  "description": "Plan, audit, create, rewrite, and measure content for AI CMO's paid SEO and GEO workflow. Use for topic opportunities, AI visibility, technical SEO, extractable article structure, sitemap-based rewrites, GSC readback, or SEO/GEO client reports."
@@ -182,15 +182,26 @@ maggie dash sections remap-translations \
182
182
  --mapping-file .maggie/section-translation-map.json \
183
183
  --output .maggie/translations-v2.json --confirm
184
184
 
185
- # Validate locale sidecars for stored image alt text before publishing:
185
+ # Validate every registry-declared translatable field for every locale before publishing:
186
186
  maggie dash sections locale-validate \
187
187
  --page-id <page-id> --sections-file .maggie/sections.json \
188
- --translations-file .maggie/translations-by-locale.json --locale zh-Hant
188
+ --translations-file .maggie/translations-by-locale.json \
189
+ --registry templates/maggiedash/section-registry.json --locale zh-Hant
189
190
 
190
191
  # Check that a host wired every registry type through all implementation surfaces:
191
192
  maggie dash sections fanout-validate \
192
193
  --registry templates/maggiedash/section-registry.json \
193
194
  --fanout-file templates/maggiedash/section-fanout.json
195
+
196
+ # Validate sibling copy, media uniqueness, references, and repair convergence:
197
+ maggie dash sections variant-copy-validate --pages-file .maggie/variant-pages.json --field faq
198
+ maggie dash sections media-validate --pages-file .maggie/variant-pages.json --across-siblings
199
+ maggie dash sections bindings-validate --sections-file .maggie/sections.json \
200
+ --references-file .maggie/reference-inventory.json
201
+ maggie dash sections idempotency-validate --contract-file .maggie/reconcile-contract.json
202
+
203
+ # Classify every published page exactly once:
204
+ maggie dash inventory --pages-file .maggie/published-pages.json
194
205
  ```
195
206
 
196
207
  The catalogue declares purpose, usage, placement, repeatability and layout
@@ -211,10 +222,13 @@ as a fixed number of bands.
211
222
  Required fields and repeated `pairs` values cannot be blank. The `pairs`
212
223
  starter band is intended for compact label/value facts such as opening hours;
213
224
  it is not a prose fallback. The registry fan-out manifest is a host integration
214
- contract: when a host adds a type, update its type union/schema, blank state,
215
- validation, readable-content extraction, renderer, and editor entry together,
216
- then run `fanout-validate`. `locale-validate` checks stored image-alt sidecars;
217
- the host adapter must write the section and all non-default locale rows in one
225
+ contract: when a host adds a type or field, update its type union/schema, blank
226
+ state, validation, readable-content extraction, renderer, and editor entry
227
+ together, then run `fanout-validate`. The check is field-aware and requires two
228
+ editor screens, so adding a field without wiring both editing surfaces fails
229
+ closed. `locale-validate --registry` checks every declared translatable scalar
230
+ and repeated item field; URLs and media sources can be marked non-translatable.
231
+ The host adapter must write the section and all non-default locale rows in one
218
232
  transaction. The JSON report is evidence, not a database write.
219
233
 
220
234
  Translation keys use stable section IDs, with an array-index fallback only
@@ -233,8 +247,17 @@ is the reviewable output form, not a substitute for the adapter's transaction.
233
247
  Keep data-owned values out of page copy. For example, a pricing band should
234
248
  store a service identifier or slug and let the live service/booking adapter
235
249
  render current options and prices. Inventory reports must classify each
236
- published page once into disjoint groups; price options, arrangements, and
237
- other child records are counts, not pages.
250
+ published page once into disjoint groups; `maggie dash inventory` reports band
251
+ and code-rendered counts. Price options, arrangements, and other child records
252
+ are counts, not pages. Run the variant-copy and media checks before publishing
253
+ localized sibling pages, and the bindings check whenever a section stores a
254
+ category, collection, or service reference; an unresolved binding is a publish
255
+ failure, not an empty state.
256
+
257
+ Repair scripts must select all candidates, compare every target field, write
258
+ only changed rows, and report both changed and unchanged rows. Validate that
259
+ contract with `idempotency-validate`; a query that selects only rows that look
260
+ unconverted cannot repair its own bad output.
238
261
 
239
262
  After any script or direct adapter write to translation data, invalidate the
240
263
  running process before verification. Record the restart and run the rendering
@@ -111,6 +111,21 @@ The manifest must reference `DATABASE_URL` (not a literal URL), declare an
111
111
  advancing version, forward-only/idempotent policy, backup and restore commands,
112
112
  and a tested restore artifact. The validator never runs those commands.
113
113
 
114
+ Before a write, prove that the migration target is the database used by the
115
+ running service. The identity report is intentionally secret-free and includes
116
+ the environment, target/database name, server identity, service release
117
+ identity, row counts, and a SHA-256 fingerprint. Compare it with the deployment
118
+ identity when available:
119
+
120
+ ```bash
121
+ maggie migration identity --identity-file .maggie/db-identity.json \
122
+ --expected-file .maggie/service-db-identity.json
123
+ ```
124
+
125
+ The gate fails on a missing or mismatched target identity and never executes a
126
+ migration. A successful connection alone is not proof that the intended
127
+ database was selected.
128
+
114
129
  If a release depends on existing rows or seeded data, set
115
130
  `dataDependencies: true` in `.maggie/migration-manifest.json` and provide
116
131
  `.maggie/deployment/data-release.json` before deployment. The checkpoint must
@@ -0,0 +1,102 @@
1
+ ---
2
+ name: maggie-qa-workflow
3
+ description: Run scenario-based browser QA with explicit evidence, fix/retest lifecycle, and release-gate decisions for web projects.
4
+ metadata:
5
+ version: 1.0.0
6
+ ---
7
+
8
+ # Maggie QA Workflow
9
+
10
+ Use this skill when a web project needs repeatable user-scenario testing that
11
+ connects browser evidence to a fix, a same-scenario retest, adjacent regression
12
+ checks, and an explicit Pass/Blocked/Fail release decision. It is framework
13
+ neutral and does not replace the project's browser-control or test tools.
14
+ Follow the shared [memory hook](../../references/memory-hook.md) before and
15
+ after the run; memory and feedback remain bounded by the privacy rules below.
16
+
17
+ ## Prepare a scenario manifest
18
+
19
+ Create `.maggie/scenario-manifest.json` or pass another JSON file with a
20
+ non-empty `scenarios` array. Each scenario needs a unique `id`; useful fields
21
+ include `title`, `group`, `priority`, `routes`, `persona`, `auth`, `browser`,
22
+ and `viewport`. Keep project-specific scenarios in the project; do not ship
23
+ them in the Maggie package.
24
+
25
+ ## Start and record a run
26
+
27
+ The CLI stores only secret-free run state under `.maggie/qa-runs/`. Screenshots
28
+ and logs stay in the project and are represented by relative paths and hashes.
29
+ Use a real browser adapter for visible interaction, computed layout,
30
+ console/network evidence, final URLs, and response status:
31
+
32
+ ```bash
33
+ maggie qa start --project . \
34
+ --scenario-file .maggie/scenario-manifest.json \
35
+ --run-id local-qa-001 --environment local \
36
+ --base-url http://localhost:4321 --browser chrome \
37
+ --commit "$(git rev-parse --short HEAD)"
38
+
39
+ maggie qa record --project . --run local-qa-001 \
40
+ --scenario HOME-001 --phase test --status pass \
41
+ --summary "Homepage navigation and consent passed" \
42
+ --evidence .maggie/qa-runs/local-qa-001/home.png
43
+ ```
44
+
45
+ For a failure, record expected behavior, actual behavior, and a stable error
46
+ fingerprint. A failed scenario cannot be silently changed to Pass:
47
+
48
+ ```bash
49
+ maggie qa record --project . --run local-qa-001 \
50
+ --scenario SEARCH-001 --phase test --status fail \
51
+ --summary "Search dialog did not open" \
52
+ --expected "Selecting a result opens its detail page" \
53
+ --actual "The click leaves the dialog open" \
54
+ --error-fingerprint search-dialog-click-stale \
55
+ --evidence .maggie/qa-runs/local-qa-001/search-console.txt
56
+
57
+ maggie qa record --project . --run local-qa-001 \
58
+ --scenario SEARCH-001 --phase fix \
59
+ --resolution "Guarded the dialog transition after the selected result is resolved" \
60
+ --validation "focused browser check and project build passed"
61
+
62
+ maggie qa record --project . --run local-qa-001 \
63
+ --scenario SEARCH-001 --phase retest --status pass \
64
+ --summary "Search result opens the detail page" \
65
+ --evidence .maggie/qa-runs/local-qa-001/search-retest.png
66
+ ```
67
+
68
+ `fix` must follow a recorded failure. `retest` must follow a test and, when
69
+ the test failed, a fix. After a fix, retest the original scenario and at least
70
+ one adjacent scenario affected by the same surface.
71
+
72
+ ## Gate and release evidence
73
+
74
+ The run gate is `fail` when any scenario fails, `blocked` when there is no
75
+ failure but pending/blocked/inconclusive scenarios remain, and `pass` only
76
+ when every scenario passes. Missing credentials, unsafe fixtures, a real
77
+ mobile viewport, a payment sandbox, or a fault-injection environment are
78
+ explicit blockers; never guess around them.
79
+
80
+ ```bash
81
+ maggie qa summary --project . --run local-qa-001
82
+ maggie qa summary --project . --run local-qa-001 --format markdown
83
+ maggie qa export --project . --run local-qa-001 \
84
+ --output docs/qa-runs/local-qa-001.md
85
+ ```
86
+
87
+ Before calling a release Pass, also run the relevant build, accessibility,
88
+ SEO, media, API, and deployment-canary checks. A green build, HTTP 200, source
89
+ class, or one guest smoke is not browser QA evidence.
90
+
91
+ ## Privacy and feedback
92
+
93
+ Do not put passwords, tokens, cookies, full private URLs, personal data,
94
+ provider response bodies, or secrets in run state, screenshots, or exported
95
+ reports. When the same workflow defect is reusable across projects, create a
96
+ privacy-safe draft through `maggie-feedback`; submitting it remains an explicit
97
+ user-confirmed action. Do not promote a project-specific preference directly
98
+ to active memory.
99
+
100
+ The implementation is `tools/clis/maggie_qa_workflow.py`; it is intentionally
101
+ small enough to run without a browser dependency and delegates browser
102
+ interaction to the host agent/browser capability.
@@ -62,7 +62,7 @@ advertising it are separate decisions.
62
62
  Generated sitemap XML uses the conventional readable shape by default: one
63
63
  `<url>`/`<sitemap>` entry per block, UTF-8 XML, and date-only `lastmod` evidence
64
64
  rendered as a full UTC W3C datetime. The plan also exposes the response
65
- contract (`text/xml; charset=utf-8` and `X-Robots-Tag: all`) for the framework
65
+ contract (`text/xml; charset=utf-8` and `X-Robots-Tag: noindex`) for the framework
66
66
  route or reverse proxy to apply; writing a file cannot set HTTP headers itself.
67
67
  When Search Console reports a valid sitemap as unfetched, probe success alone
68
68
  is not a diagnosis. Supply a sanitized local access log to distinguish
@@ -1,11 +1,87 @@
1
1
  {
2
2
  "schemaVersion": "maggiedash-section-fanout.v1",
3
- "description": "Starter host contract: every registry type must be wired through each implementation surface. Hosts extending the registry must regenerate this file.",
4
- "typeUnion": ["cards", "cta", "faq", "hero", "links", "pairs", "prose"],
5
- "sectionSchema": ["cards", "cta", "faq", "hero", "links", "pairs", "prose"],
6
- "blank": ["cards", "cta", "faq", "hero", "links", "pairs", "prose"],
7
- "validation": ["cards", "cta", "faq", "hero", "links", "pairs", "prose"],
8
- "textExtraction": ["cards", "cta", "faq", "hero", "links", "pairs", "prose"],
9
- "renderer": ["cards", "cta", "faq", "hero", "links", "pairs", "prose"],
10
- "editor": ["cards", "cta", "faq", "hero", "links", "pairs", "prose"]
3
+ "description": "Field-aware host contract: every registry type and declared field must be wired through each implementation surface and two editor screens.",
4
+ "typeUnion": {
5
+ "hero": ["title", "intro", "image", "imageAlt", "ctaLabel"],
6
+ "prose": ["heading", "paragraphs", "paragraphs.paragraph", "image", "imageAlt"],
7
+ "pairs": ["heading", "rows", "rows.label", "rows.value", "note"],
8
+ "cards": ["heading", "items", "items.title", "items.body"],
9
+ "links": ["heading", "items", "items.label", "items.href", "items.body"],
10
+ "faq": ["heading", "items", "items.question", "items.answer"],
11
+ "cta": ["heading", "body", "label"]
12
+ },
13
+ "sectionSchema": {
14
+ "hero": ["title", "intro", "image", "imageAlt", "ctaLabel"],
15
+ "prose": ["heading", "paragraphs", "paragraphs.paragraph", "image", "imageAlt"],
16
+ "pairs": ["heading", "rows", "rows.label", "rows.value", "note"],
17
+ "cards": ["heading", "items", "items.title", "items.body"],
18
+ "links": ["heading", "items", "items.label", "items.href", "items.body"],
19
+ "faq": ["heading", "items", "items.question", "items.answer"],
20
+ "cta": ["heading", "body", "label"]
21
+ },
22
+ "blank": {
23
+ "hero": ["title", "intro", "image", "imageAlt", "ctaLabel"],
24
+ "prose": ["heading", "paragraphs", "paragraphs.paragraph", "image", "imageAlt"],
25
+ "pairs": ["heading", "rows", "rows.label", "rows.value", "note"],
26
+ "cards": ["heading", "items", "items.title", "items.body"],
27
+ "links": ["heading", "items", "items.label", "items.href", "items.body"],
28
+ "faq": ["heading", "items", "items.question", "items.answer"],
29
+ "cta": ["heading", "body", "label"]
30
+ },
31
+ "validation": {
32
+ "hero": ["title", "intro", "image", "imageAlt", "ctaLabel"],
33
+ "prose": ["heading", "paragraphs", "paragraphs.paragraph", "image", "imageAlt"],
34
+ "pairs": ["heading", "rows", "rows.label", "rows.value", "note"],
35
+ "cards": ["heading", "items", "items.title", "items.body"],
36
+ "links": ["heading", "items", "items.label", "items.href", "items.body"],
37
+ "faq": ["heading", "items", "items.question", "items.answer"],
38
+ "cta": ["heading", "body", "label"]
39
+ },
40
+ "textExtraction": {
41
+ "hero": ["title", "intro", "image", "imageAlt", "ctaLabel"],
42
+ "prose": ["heading", "paragraphs", "paragraphs.paragraph", "image", "imageAlt"],
43
+ "pairs": ["heading", "rows", "rows.label", "rows.value", "note"],
44
+ "cards": ["heading", "items", "items.title", "items.body"],
45
+ "links": ["heading", "items", "items.label", "items.href", "items.body"],
46
+ "faq": ["heading", "items", "items.question", "items.answer"],
47
+ "cta": ["heading", "body", "label"]
48
+ },
49
+ "renderer": {
50
+ "hero": ["title", "intro", "image", "imageAlt", "ctaLabel"],
51
+ "prose": ["heading", "paragraphs", "paragraphs.paragraph", "image", "imageAlt"],
52
+ "pairs": ["heading", "rows", "rows.label", "rows.value", "note"],
53
+ "cards": ["heading", "items", "items.title", "items.body"],
54
+ "links": ["heading", "items", "items.label", "items.href", "items.body"],
55
+ "faq": ["heading", "items", "items.question", "items.answer"],
56
+ "cta": ["heading", "body", "label"]
57
+ },
58
+ "editor": {
59
+ "hero": ["title", "intro", "image", "imageAlt", "ctaLabel"],
60
+ "prose": ["heading", "paragraphs", "paragraphs.paragraph", "image", "imageAlt"],
61
+ "pairs": ["heading", "rows", "rows.label", "rows.value", "note"],
62
+ "cards": ["heading", "items", "items.title", "items.body"],
63
+ "links": ["heading", "items", "items.label", "items.href", "items.body"],
64
+ "faq": ["heading", "items", "items.question", "items.answer"],
65
+ "cta": ["heading", "body", "label"]
66
+ },
67
+ "editorScreens": {
68
+ "section-editor": {
69
+ "hero": ["title", "intro", "image", "imageAlt", "ctaLabel"],
70
+ "prose": ["heading", "paragraphs", "paragraphs.paragraph", "image", "imageAlt"],
71
+ "pairs": ["heading", "rows", "rows.label", "rows.value", "note"],
72
+ "cards": ["heading", "items", "items.title", "items.body"],
73
+ "links": ["heading", "items", "items.label", "items.href", "items.body"],
74
+ "faq": ["heading", "items", "items.question", "items.answer"],
75
+ "cta": ["heading", "body", "label"]
76
+ },
77
+ "document-detail": {
78
+ "hero": ["title", "intro", "image", "imageAlt", "ctaLabel"],
79
+ "prose": ["heading", "paragraphs", "paragraphs.paragraph", "image", "imageAlt"],
80
+ "pairs": ["heading", "rows", "rows.label", "rows.value", "note"],
81
+ "cards": ["heading", "items", "items.title", "items.body"],
82
+ "links": ["heading", "items", "items.label", "items.href", "items.body"],
83
+ "faq": ["heading", "items", "items.question", "items.answer"],
84
+ "cta": ["heading", "body", "label"]
85
+ }
86
+ }
11
87
  }
@@ -13,7 +13,7 @@
13
13
  "fields": [
14
14
  {"name": "title", "usage": "Plain words a visitor would search for.", "limit": 70, "required": true},
15
15
  {"name": "intro", "usage": "Who it is for and what it does.", "limit": 220},
16
- {"name": "image", "usage": "The hero image rendered beside or behind the copy.", "limit": 500},
16
+ {"name": "image", "usage": "The hero image rendered beside or behind the copy.", "limit": 500, "translatable": false},
17
17
  {"name": "imageAlt", "usage": "What the hero image shows for a reader who cannot see it.", "limit": 160},
18
18
  {"name": "ctaLabel", "usage": "The action as a verb.", "limit": 30}
19
19
  ],
@@ -28,7 +28,7 @@
28
28
  "fields": [
29
29
  {"name": "heading", "usage": "The argument in a sentence.", "limit": 90},
30
30
  {"name": "paragraphs", "usage": "Standalone paragraphs.", "limit": 0, "repeats": {"min": 1, "max": 4, "of": [{"name": "paragraph", "usage": "One paragraph of plain prose.", "limit": 400}]}},
31
- {"name": "image", "usage": "An optional supporting image.", "limit": 500},
31
+ {"name": "image", "usage": "An optional supporting image.", "limit": 500, "translatable": false},
32
32
  {"name": "imageAlt", "usage": "What the supporting image shows.", "limit": 160}
33
33
  ],
34
34
  "example": {"type": "prose", "heading": "Make the important part easier to understand", "paragraphs": ["Start with the decision your reader is trying to make.", "Then give them the context, evidence and next step in that order."]}
@@ -66,7 +66,7 @@
66
66
  "repeatable": true,
67
67
  "fields": [
68
68
  {"name": "heading", "usage": "What the links have in common.", "limit": 90},
69
- {"name": "items", "usage": "Real related pages on this site.", "limit": 0, "repeats": {"min": 2, "max": 6, "of": [{"name": "label", "usage": "The destination page name.", "limit": 60, "required": true}, {"name": "href", "usage": "A real path on this site.", "limit": 200, "required": true}, {"name": "body", "usage": "One sentence on what is there.", "limit": 160}]}}
69
+ {"name": "items", "usage": "Real related pages on this site.", "limit": 0, "repeats": {"min": 2, "max": 6, "of": [{"name": "label", "usage": "The destination page name.", "limit": 60, "required": true}, {"name": "href", "usage": "A real path on this site.", "limit": 200, "required": true, "translatable": false}, {"name": "body", "usage": "One sentence on what is there.", "limit": 160}]}}
70
70
  ],
71
71
  "example": {"type": "links", "heading": "Keep exploring", "items": [{"label": "How it works", "href": "/how-it-works/", "body": "See the process from start to finish."}, {"label": "Frequently asked questions", "href": "/faq/", "body": "Find concise answers to common questions."}]}
72
72
  },