@topy-ai/maggie 0.7.31 → 0.7.33
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README-zh-TW.md +2 -2
- package/README.md +101 -19
- package/bin/maggie.js +6 -0
- package/bundled-references/google-integrations-runbook.md +26 -0
- package/bundled-skills/maggie-blog/SKILL.md +18 -1
- package/bundled-skills/maggie-dash/SKILL.md +18 -3
- package/bundled-skills/maggie-deployment/SKILL.md +72 -0
- package/bundled-skills/maggie-deployment/references/vps.md +26 -0
- package/bundled-skills/maggie-design/SKILL.md +16 -0
- package/bundled-skills/maggie-feedback/SKILL.md +11 -2
- package/bundled-skills/maggie-seo-geo/SKILL.md +22 -1
- package/bundled-tools/clis/maggie.py +12 -0
- package/bundled-tools/clis/maggie_analytics.py +34 -0
- package/bundled-tools/clis/maggie_blog.py +13 -0
- package/bundled-tools/clis/maggie_dash.py +17 -0
- package/bundled-tools/clis/maggie_deployment.py +91 -7
- package/bundled-tools/clis/maggie_feedback.py +18 -4
- package/bundled-tools/clis/maggie_icon_release_gate.py +79 -0
- package/bundled-tools/clis/maggie_migration.py +71 -0
- package/bundled-tools/clis/maggie_release_manifest.py +81 -0
- package/bundled-tools/clis/maggie_runtime_preflight.py +76 -0
- package/bundled-tools/clis/site_audit.py +78 -5
- package/bundled-tools/integrations/analytics.md +20 -0
- package/bundled-tools/runtime/maggie_blog_publish.py +38 -0
- package/bundled-tools/runtime/maggie_dash_panels.py +111 -0
- package/bundled-tools/runtime/maggie_quality.py +1 -1
- package/bundled-tools/runtime/maggie_sections.py +39 -1
- package/bundled-tools/runtime/site_baseline.py +23 -2
- package/package.json +1 -1
- package/references/google-integrations-runbook.md +26 -0
package/README-zh-TW.md
CHANGED
|
@@ -8,7 +8,7 @@ Codex、Claude Code 與相容的 coding agents。
|
|
|
8
8
|
## 安裝
|
|
9
9
|
|
|
10
10
|
```bash
|
|
11
|
-
npx @topy-ai/maggie@0.7.
|
|
11
|
+
npx @topy-ai/maggie@0.7.33 init --agent all
|
|
12
12
|
npx @topy-ai/maggie doctor --project .
|
|
13
13
|
```
|
|
14
14
|
|
|
@@ -25,7 +25,7 @@ maggie doctor --project . --require-bootstrap --strict
|
|
|
25
25
|
deployment、memory、feedback 和 MaggieDash。內容先 draft/review,外部寫入、
|
|
26
26
|
publish 與 production deployment 需要明確確認。
|
|
27
27
|
|
|
28
|
-
目前 release 是 `0.7.31
|
|
28
|
+
目前 release 是 `0.7.33`,記錄並審查一筆更正回饋;確認 0.7.32 已正確處理 batch index,沒有修改已驗證的 shared behavior。0.7.32 加入 feedback 一基索引支援、MaggieDash panel 的 source/freshness/error evidence、Consent Mode 與實際 write/no-op reconciliation、SEO baseline recapture、sitemap origin rebasing、content-diff scope、migration ledger reconciliation、deployment credential preflight、release provenance/runtime preflight、icon release gate、opt-in blog auto-publish gate,以及 least-privilege VPS deployer。也修復 top-level `maggie feedback` dispatcher parity。0.7.31 加入 update 差異摘要、atomic installer copy、subset install manifest merge,以及 inventory drift 時 doctor non-zero。0.7.30 補上 feedback tracking issue closeout gate 與 batch 14/15 audit ledger。0.7.29 修正 npm package landing page 使用英文 README;0.7.28 加入 versioned Gemini model policy、明確 fallback 與 provenance、bundled-first CLI
|
|
29
29
|
dispatch、`maggie --version`、feedback batch review 聚合與重複偵測、marketplace enrichment evidence、booking
|
|
30
30
|
worker/resolver evidence,以及 read-only migration preflight。它也包含 host-owned mobile app surface contract、signed-in
|
|
31
31
|
camera-state QA、直接 Astro route resolution、correlated feedback batch,以及
|
package/README.md
CHANGED
|
@@ -60,21 +60,31 @@ Maggie keeps the existing project foundation and asks for decisions before
|
|
|
60
60
|
shared routes, analytics, or publishing boundaries change. The current
|
|
61
61
|
package ships 19 installable skills and a local-first MaggieDash foundation.
|
|
62
62
|
|
|
63
|
-
The current release is `0.7.
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
63
|
+
The current release is `0.7.33`. It records the reviewed correction for the
|
|
64
|
+
batch-index feedback workflow while keeping the verified 0.7.32 behavior
|
|
65
|
+
unchanged. The 0.7.32 release added explicit one-based feedback batch index
|
|
66
|
+
support, source/freshness/error evidence for MaggieDash measurement
|
|
67
|
+
panels, Consent Mode and actual-write reconciliation contracts, reviewed SEO
|
|
68
|
+
baseline recapture, requested-origin sitemap rebasing, explicit content-diff
|
|
69
|
+
scope, migration-ledger reconciliation, canonical deployment credential
|
|
70
|
+
preflight, unified release provenance, runtime preflight classification,
|
|
71
|
+
design icon-release gating, opt-in blog auto-publish gating, and a
|
|
72
|
+
least-privilege VPS deployer plan. It also restores top-level `maggie
|
|
73
|
+
feedback` dispatch parity. The 0.7.31 release added bounded update diff
|
|
74
|
+
evidence, atomic installer copies, subset-install manifest merge, and
|
|
75
|
+
non-zero doctor failures for inventory drift. The 0.7.30 release added the
|
|
76
|
+
internal feedback issue closeout gate. The 0.7.29 release fixed npm metadata
|
|
77
|
+
to render this English README as the package landing page. The 0.7.28
|
|
78
|
+
release added a versioned Gemini model policy with an explicit fallback and
|
|
79
|
+
provenance, bundled-CLI version discovery, a bundled-first dispatcher that
|
|
80
|
+
avoids stale project wrappers, privacy-safe feedback batch review/duplicate
|
|
81
|
+
detection, marketplace enrichment evidence, bounded booking worker/resolver
|
|
82
|
+
reports, and read-only migration preflight contracts. The release retains the
|
|
83
|
+
provider-neutral MaggieDash host adapter contract, idempotent PostgreSQL
|
|
84
|
+
starter schema, type-only backend boundary, runtime endpoint conformance
|
|
85
|
+
evidence, safe quota/error summaries, stale marketplace readiness
|
|
86
|
+
revalidation, explicit VPS port/origin planning, first-release rollback
|
|
87
|
+
evidence, and clean non-interactive bootstrap errors.
|
|
78
88
|
It retains the host-owned mobile app surface
|
|
79
89
|
contract (`maggie design app-init`/`app-validate`), direct Astro route
|
|
80
90
|
resolution, correlated feedback batches, and runtime package-version capture.
|
|
@@ -131,6 +141,16 @@ evidence proves that a dashboard screen mounted and executed its checks, so a
|
|
|
131
141
|
static component scan cannot pass by itself. MaggieDash hosts may also expose
|
|
132
142
|
the provider-neutral activity-log and managed-navigation contracts.
|
|
133
143
|
|
|
144
|
+
Measurement panels must report their source, capture time/freshness, and
|
|
145
|
+
independent warning/error state. Validate the host-produced report before
|
|
146
|
+
using it in a release decision:
|
|
147
|
+
|
|
148
|
+
```bash
|
|
149
|
+
maggie dash panels-validate \
|
|
150
|
+
--report .maggie/measurement-panels.json \
|
|
151
|
+
--output docs/measurement-panels-validation.json
|
|
152
|
+
```
|
|
153
|
+
|
|
134
154
|
The current package also includes reusable safeguards from the latest feedback
|
|
135
155
|
review: `maggie dash api-contract` checks declared request and 2xx response
|
|
136
156
|
shapes; `maggie blog check-gate`/`approve` enforces review before publish;
|
|
@@ -251,10 +271,17 @@ maggie ops favicon-check ... # served favicon behaviour check
|
|
|
251
271
|
maggie deployment | migration | release | analytics | schedule
|
|
252
272
|
maggie deployment readiness --project PATH
|
|
253
273
|
maggie deployment parity --project PATH --evidence FILE --output FILE
|
|
274
|
+
maggie deployment runtime-preflight --evidence FILE --output FILE
|
|
275
|
+
maggie deployment release-manifest --evidence FILE --output FILE
|
|
276
|
+
maggie deployment credential-preflight [--expected-host HOST]
|
|
254
277
|
maggie migration identity --identity-file FILE [--expected-file FILE]
|
|
255
278
|
maggie migration preflight --evidence FILE [--output FILE]
|
|
279
|
+
maggie migration reconcile --evidence FILE --migration-dir DIR [--output FILE]
|
|
256
280
|
maggie deployment canary --asset URL=SHA256 --render-report report.json
|
|
257
281
|
maggie design icon-inventory --source-dir src --runtime assets/icons.css
|
|
282
|
+
maggie design icon-release-gate --icon-report FILE --browser-report FILE --output FILE
|
|
283
|
+
maggie dash panels-validate --report FILE [--output FILE]
|
|
284
|
+
maggie blog auto-publish-gate --evidence FILE --output FILE
|
|
258
285
|
maggie api lifecycle | site-audit | ops audit
|
|
259
286
|
maggie marketplace enrichment-report --project PATH --input FILE [--output FILE]
|
|
260
287
|
maggie service worker-health --project PATH --evidence FILE [--output FILE]
|
|
@@ -320,6 +347,16 @@ The adapter is an argv array, receives a versioned request on stdin, and must
|
|
|
320
347
|
print only the three review-policy fields. Provider stderr is suppressed and a
|
|
321
348
|
missing local store without an adapter fails closed.
|
|
322
349
|
|
|
350
|
+
Automated blog publishing stays human-reviewed by default. If a host opts in,
|
|
351
|
+
the gate requires explicit review bypass evidence plus locale, image-alt, SEO,
|
|
352
|
+
sitemap, indexing-notification, and audit checks:
|
|
353
|
+
|
|
354
|
+
```bash
|
|
355
|
+
maggie blog auto-publish-gate \
|
|
356
|
+
--evidence .maggie/blog/auto-publish-evidence.json \
|
|
357
|
+
--output docs/blog-auto-publish-gate.json
|
|
358
|
+
```
|
|
359
|
+
|
|
323
360
|
### Design and deployment release gates
|
|
324
361
|
|
|
325
362
|
Check source-to-runtime icon coverage before shipping a design:
|
|
@@ -334,6 +371,17 @@ and is only static name coverage. Pair changed icon controls with a
|
|
|
334
371
|
browser-runtime `icon-rendered` assertion so the host adapter proves that the
|
|
335
372
|
glyph is visible, has positive dimensions, and has an accessible label.
|
|
336
373
|
|
|
374
|
+
For a design release, compose the static inventory with browser-painted glyph
|
|
375
|
+
evidence. Every tested icon must be visible, have positive dimensions, expose
|
|
376
|
+
an accessible name, and load successfully:
|
|
377
|
+
|
|
378
|
+
```bash
|
|
379
|
+
maggie design icon-release-gate \
|
|
380
|
+
--icon-report docs/icon-inventory.json \
|
|
381
|
+
--browser-report .maggie/icon-browser-evidence.json \
|
|
382
|
+
--output docs/icon-release-gate.json
|
|
383
|
+
```
|
|
384
|
+
|
|
337
385
|
After deployment, compare an immutable asset fingerprint and validate the
|
|
338
386
|
browser adapter's rendered report:
|
|
339
387
|
|
|
@@ -362,6 +410,37 @@ privileges, route API status, stale resident processes, source-job IDs, and
|
|
|
362
410
|
browser/driver compatibility. Add the resulting report to readiness with
|
|
363
411
|
`--runtime-parity`; a failed report blocks the gate.
|
|
364
412
|
|
|
413
|
+
Use the runtime preflight to classify dependency, browser, worker, database,
|
|
414
|
+
and route failures independently. A non-pass check must include remediation:
|
|
415
|
+
|
|
416
|
+
```bash
|
|
417
|
+
maggie deployment runtime-preflight \
|
|
418
|
+
--evidence .maggie/verification/runtime-preflight-input.json \
|
|
419
|
+
--output .maggie/verification/runtime-preflight.json
|
|
420
|
+
```
|
|
421
|
+
|
|
422
|
+
Before activation, reconcile the host's `maggie_schema_migrations` ledger with
|
|
423
|
+
local SQL files. This is read-only and produces an ordered missing-migration
|
|
424
|
+
plan. Deployment credential checks similarly verify only the presence of the
|
|
425
|
+
canonical names, never their values:
|
|
426
|
+
|
|
427
|
+
```bash
|
|
428
|
+
maggie migration reconcile \
|
|
429
|
+
--evidence .maggie/migration/ledger.json \
|
|
430
|
+
--migration-dir migrations \
|
|
431
|
+
--output docs/migration-reconcile.json
|
|
432
|
+
maggie deployment credential-preflight --expected-host example.com
|
|
433
|
+
```
|
|
434
|
+
|
|
435
|
+
Finally, combine route, migration, runtime, asset/icon, edge-cache,
|
|
436
|
+
browser/render, and rollback evidence into one release provenance manifest:
|
|
437
|
+
|
|
438
|
+
```bash
|
|
439
|
+
maggie deployment release-manifest \
|
|
440
|
+
--evidence .maggie/verification/release-evidence.json \
|
|
441
|
+
--output docs/release-manifest.json
|
|
442
|
+
```
|
|
443
|
+
|
|
365
444
|
Unit regression does not establish runtime release readiness. Produce unit
|
|
366
445
|
evidence and then validate all required release evidence slots; add
|
|
367
446
|
`--runtime-parity` when the deployment uses the worker/browser surfaces above:
|
|
@@ -421,8 +500,8 @@ artifact schemas.
|
|
|
421
500
|
Recommended upgrade sequence for the current release:
|
|
422
501
|
|
|
423
502
|
```bash
|
|
424
|
-
npx @topy-ai/maggie@0.7.
|
|
425
|
-
npx @topy-ai/maggie@0.7.
|
|
503
|
+
npx @topy-ai/maggie@0.7.33 update --project . --force
|
|
504
|
+
npx @topy-ai/maggie@0.7.33 cleanup --project .
|
|
426
505
|
```
|
|
427
506
|
|
|
428
507
|
Maintainers should pass npm credentials through the repository helper, never
|
|
@@ -588,10 +667,13 @@ For related observations, create 1–50 local drafts with shared correlation
|
|
|
588
667
|
metadata and review them before submitting:
|
|
589
668
|
|
|
590
669
|
```bash
|
|
591
|
-
maggie feedback batch --project . --batch-file ./feedback-batch.json
|
|
670
|
+
maggie feedback batch --project . --batch-file ./feedback-batch.json \
|
|
671
|
+
--batch-base 0
|
|
592
672
|
```
|
|
593
673
|
|
|
594
|
-
The batch command never submits automatically or writes active memory.
|
|
674
|
+
The batch command never submits automatically or writes active memory. External
|
|
675
|
+
one-based runners can pass `--batch-base 1`; Maggie stores canonical indexes
|
|
676
|
+
zero-based and validates the final item boundary explicitly.
|
|
595
677
|
|
|
596
678
|
Aggregate a correlated batch before reviewing individual drafts:
|
|
597
679
|
|
package/bin/maggie.js
CHANGED
|
@@ -91,6 +91,7 @@ Usage:
|
|
|
91
91
|
maggie design app-init --project PATH --route /app/valuation --auth-mode email-password --confirm
|
|
92
92
|
maggie design app-validate --project PATH --plan PATH --runtime-evidence FILE --rendered-dir PATH --confirm
|
|
93
93
|
maggie design icon-inventory --project PATH --source-dir src --runtime assets/icons.css --output docs/icon-inventory.json
|
|
94
|
+
maggie design icon-release-gate --icon-report FILE --browser-report FILE --output FILE
|
|
94
95
|
maggie design author --project PATH --route /about --purpose TEXT --audience TEXT --confirm
|
|
95
96
|
maggie design in-place --project PATH --route /pricing [--content-source PATH]
|
|
96
97
|
maggie design section --project PATH --route /pricing --section-id ID
|
|
@@ -117,6 +118,8 @@ Usage:
|
|
|
117
118
|
maggie deployment readiness --project PATH
|
|
118
119
|
maggie deployment parity --project PATH --evidence FILE --output FILE
|
|
119
120
|
maggie deployment canary --project PATH --asset URL=SHA256 --render-report report.json --output docs/deployment-canary.json
|
|
121
|
+
maggie deployment release-manifest --evidence FILE --output FILE
|
|
122
|
+
maggie deployment runtime-preflight --evidence FILE --output FILE
|
|
120
123
|
maggie migration preflight --evidence FILE --output FILE
|
|
121
124
|
maggie migration --project PATH --environment staging
|
|
122
125
|
maggie migration identity --identity-file FILE [--expected-file FILE]
|
|
@@ -504,6 +507,7 @@ try {
|
|
|
504
507
|
else if (command === "clone") workflowCli("maggie_clone.py", args);
|
|
505
508
|
else if (command === "clone-to-template") workflowCli("maggie_clone_to_template.py", args);
|
|
506
509
|
else if (command === "design" && args[0] === "icon-inventory") workflowCli("maggie_icon_inventory.py", args.slice(1));
|
|
510
|
+
else if (command === "design" && args[0] === "icon-release-gate") workflowCli("maggie_icon_release_gate.py", args.slice(1));
|
|
507
511
|
else if (command === "design") workflowCli("maggie_design.py", args);
|
|
508
512
|
else if (command === "auth") workflowCli("maggie_auth.py", args);
|
|
509
513
|
else if (command === "blog") workflowCli("maggie_blog.py", args);
|
|
@@ -514,6 +518,8 @@ try {
|
|
|
514
518
|
else if (command === "deployment" && args[0] === "canary") workflowCli("maggie_deployment_canary.py", args.slice(1));
|
|
515
519
|
else if (command === "deployment" && args[0] === "readiness") workflowCli("maggie_deployment_readiness.py", args.slice(1));
|
|
516
520
|
else if (command === "deployment" && args[0] === "parity") workflowCli("maggie_deployment_parity.py", args.slice(1));
|
|
521
|
+
else if (command === "deployment" && args[0] === "release-manifest") workflowCli("maggie_release_manifest.py", args.slice(1));
|
|
522
|
+
else if (command === "deployment" && args[0] === "runtime-preflight") workflowCli("maggie_runtime_preflight.py", args.slice(1));
|
|
517
523
|
else if (command === "deployment") workflowCli("maggie_deployment.py", args);
|
|
518
524
|
else if (command === "migration") workflowCli("maggie_migration.py", args);
|
|
519
525
|
else if (command === "schedule") workflowCli("maggie_schedule.py", args);
|
|
@@ -52,6 +52,32 @@ The validator accepts the complete provider allowlist, but a capability is
|
|
|
52
52
|
verified only when its corresponding required scope is present. Scope presence
|
|
53
53
|
alone never proves product access.
|
|
54
54
|
|
|
55
|
+
### GTM operation scope matrix
|
|
56
|
+
|
|
57
|
+
Request the union of the rows needed by one operation; do not use a broad
|
|
58
|
+
scope merely because a later operation might need it:
|
|
59
|
+
|
|
60
|
+
| GTM operation | Minimum OAuth scope |
|
|
61
|
+
|---|---|
|
|
62
|
+
| List/read account, container, tag, trigger, or variable | `https://www.googleapis.com/auth/tagmanager.readonly` |
|
|
63
|
+
| Edit container configuration | `https://www.googleapis.com/auth/tagmanager.edit.containers` |
|
|
64
|
+
| Create or update a container version | `https://www.googleapis.com/auth/tagmanager.edit.containerversions` |
|
|
65
|
+
| Publish a container version | `https://www.googleapis.com/auth/tagmanager.publish` |
|
|
66
|
+
|
|
67
|
+
An operation that edits a container and creates a version must request both
|
|
68
|
+
edit scopes; publishing additionally requires the publish scope. Record the
|
|
69
|
+
operation name and exact scope union in the capability evidence so a successful
|
|
70
|
+
read cannot be mistaken for edit or publish access.
|
|
71
|
+
|
|
72
|
+
### Missing fields are unknown
|
|
73
|
+
|
|
74
|
+
Google APIs can omit fields, especially when a proto3 field is absent from the
|
|
75
|
+
response or was not selected by the request. An omitted boolean is not
|
|
76
|
+
`false`, and an absent schema field is not evidence that the capability is
|
|
77
|
+
disabled. Reports must use `unknown`/`not_observed` in the provider adapter's
|
|
78
|
+
evidence and obtain a corroborating read or time-series observation before
|
|
79
|
+
making a negative claim. Never silently coerce a missing field to `false`.
|
|
80
|
+
|
|
55
81
|
## Provider setup and read-only preflight
|
|
56
82
|
|
|
57
83
|
1. Select one provider and one resource. Enable only that provider API in the
|
|
@@ -54,7 +54,24 @@ explicit `approve` transition before `publish`. Stable `contentId` is the
|
|
|
54
54
|
ingest identity and a published slug must not change during a rewrite.
|
|
55
55
|
Search/sort views are not indexable; drafts never appear in public routes, RSS,
|
|
56
56
|
or sitemap output. Provider keys remain server-side. Public publication and
|
|
57
|
-
|
|
57
|
+
migrations always require explicit confirmation.
|
|
58
|
+
|
|
59
|
+
Automatic publication is an opt-in host policy, not the default. Keep human
|
|
60
|
+
review enabled unless the owner explicitly chooses otherwise. If a host has
|
|
61
|
+
that approval, validate its evidence before its scheduler calls the host's
|
|
62
|
+
publish path:
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
maggie blog auto-publish-gate \
|
|
66
|
+
--evidence .maggie/blog-auto-publish-evidence.json \
|
|
67
|
+
--output .maggie/blog-auto-publish-gate.json
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
The `maggie-blog-auto-publish.v1` evidence must explicitly set `optIn: true`
|
|
71
|
+
and `reviewDisabledExplicitly: true`, then pass locale variants, feature image
|
|
72
|
+
and alt text, SEO fields, sitemap generation, indexing notification, and audit
|
|
73
|
+
checks. The gate never publishes; missing evidence keeps content in human
|
|
74
|
+
review and remains non-indexable.
|
|
58
75
|
|
|
59
76
|
The adapter runs as an argv array without a shell, receives a versioned request
|
|
60
77
|
on stdin, and must print only an object containing
|
|
@@ -80,6 +80,14 @@ This is a runtime contract gate, not a source-only check; it fails when a
|
|
|
80
80
|
declared endpoint is missing, uses the wrong route/method, returns a non-2xx
|
|
81
81
|
status or omits required fields.
|
|
82
82
|
|
|
83
|
+
For analytics panels and Consent Mode, keep the same evidence boundary: the
|
|
84
|
+
default consent state must be written before the container loads, first-party
|
|
85
|
+
storage behavior must be explicitly `stop` or `degrade`, and intentional form
|
|
86
|
+
events must be declared separately as `record` or `omit`. A browser report must
|
|
87
|
+
prove each decision; an absent field is unknown and must not be interpreted as
|
|
88
|
+
false. Run the analytics release gate when the dashboard or host measurement
|
|
89
|
+
contract changes.
|
|
90
|
+
|
|
83
91
|
MaggieDash 0.2.4 adds two reusable operator workspaces. Activity is a read-only
|
|
84
92
|
view backed by `/api/maggie/activity.json`; it supports actor/action filters,
|
|
85
93
|
refresh, and a safe unavailable state. Navigation is an ordered,
|
|
@@ -255,6 +263,10 @@ maggie dash schema-audit --inventory .maggie/schema-inventory.json \
|
|
|
255
263
|
# Prove a browser check mounted the screen and executed its data calls:
|
|
256
264
|
maggie dash ui runtime-validate --evidence .maggie/dashboard-runtime.json
|
|
257
265
|
|
|
266
|
+
# Validate independent dashboard measurement panels and freshness evidence:
|
|
267
|
+
maggie dash panels-validate --report .maggie/measurement-panels.json \
|
|
268
|
+
--output .maggie/measurement-panels-result.json
|
|
269
|
+
|
|
258
270
|
# Classify docs, show inbound references and completed progress trackers:
|
|
259
271
|
maggie docs audit --project . --docs-dir docs \
|
|
260
272
|
--output docs/documentation-audit.json
|
|
@@ -339,9 +351,12 @@ category, collection, or service reference; an unresolved binding is a publish
|
|
|
339
351
|
failure, not an empty state.
|
|
340
352
|
|
|
341
353
|
Repair scripts must select all candidates, compare every target field, write
|
|
342
|
-
only changed rows, and report both changed and unchanged rows.
|
|
343
|
-
|
|
344
|
-
|
|
354
|
+
only changed rows, and report both changed and unchanged rows. Each step must
|
|
355
|
+
also return a boolean `wrote`; the summary's `writes` count is the number of
|
|
356
|
+
true outcomes, not the number of executed steps. The shared section reconcile
|
|
357
|
+
command exposes `writeCount`, `unchangedCount`, and `writeOutcome` for this
|
|
358
|
+
purpose. Validate the repair contract with `idempotency-validate`; a query
|
|
359
|
+
that selects only rows that look unconverted cannot repair its own bad output.
|
|
345
360
|
|
|
346
361
|
After any script or direct adapter write to translation data, invalidate the
|
|
347
362
|
running process before verification. Record the restart and run the rendering
|
|
@@ -88,6 +88,36 @@ not fabricate browser, rendered, or deployment evidence and does not deploy
|
|
|
88
88
|
from this command. See
|
|
89
89
|
[`readiness-v1.schema.json`](../../bundled-contracts/maggie-deployment/readiness-v1.schema.json).
|
|
90
90
|
|
|
91
|
+
Classify host/runtime failures before a release can move:
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
maggie deployment runtime-preflight \
|
|
95
|
+
--evidence .maggie/verification/runtime-preflight-input.json \
|
|
96
|
+
--output .maggie/verification/runtime-preflight.json
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
The `maggie-runtime-preflight.v1` input has independent checks for
|
|
100
|
+
dependencies, browser/driver compatibility, worker configuration, database
|
|
101
|
+
privileges, and routes/API. Each non-pass status must include an actionable
|
|
102
|
+
remediation. Missing checks are `unknown` and fail closed; the command never
|
|
103
|
+
connects to a host or mutates runtime state.
|
|
104
|
+
|
|
105
|
+
Before production approval, compose one cross-workflow manifest from the
|
|
106
|
+
sanitized outputs of the route, migration, runtime, asset/icon, edge-cache,
|
|
107
|
+
browser/render, and rollback checks:
|
|
108
|
+
|
|
109
|
+
```bash
|
|
110
|
+
maggie deployment release-manifest \
|
|
111
|
+
--evidence .maggie/release-evidence.json \
|
|
112
|
+
--output .maggie/release-manifest.json
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
The `maggie-release-evidence.v1` input links the release commit and Maggie
|
|
116
|
+
version to every required evidence slot and release fingerprint. The validator
|
|
117
|
+
fails if any slot is missing or not passed, keeps only normalized metadata, and
|
|
118
|
+
records `mutation: "not executed"`; it does not deploy or claim that a check
|
|
119
|
+
was run.
|
|
120
|
+
|
|
91
121
|
## Automatic memory hook
|
|
92
122
|
|
|
93
123
|
Follow [Maggie Memory Hook](../../references/memory-hook.md) at invocation and completion.
|
|
@@ -115,6 +145,22 @@ This command never deploys. Production execution still requires the shared
|
|
|
115
145
|
decision loop, explicit confirmation, migration/rollback details, and the
|
|
116
146
|
provider-specific deploy command.
|
|
117
147
|
|
|
148
|
+
For a VPS adapter, check the project `.env` by variable name before reporting
|
|
149
|
+
credentials as unavailable:
|
|
150
|
+
|
|
151
|
+
```bash
|
|
152
|
+
maggie deployment credential-preflight \
|
|
153
|
+
--env-file .env --expected-host example-host \
|
|
154
|
+
--output .maggie/deployment/credentials.json
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
The preflight checks `DEPLOY_SERVER_IP`, `DEPLOY_SERVER_SSH_USER`,
|
|
158
|
+
`DEPLOY_SERVER_SSH_PASSWORD`, and `DEPLOY_SERVER_SSH_SUDOER` by presence only.
|
|
159
|
+
It never prints or stores values. `--expected-host` is optional, but should be
|
|
160
|
+
used for production to prevent deploying to an unintended server. SSH-key
|
|
161
|
+
adapters may use their own named secret contract; map it explicitly in their
|
|
162
|
+
local plan.
|
|
163
|
+
|
|
118
164
|
When deployment verification depends on Google properties or accounts, use
|
|
119
165
|
the shared [Google integrations runbook](../../references/google-integrations-runbook.md).
|
|
120
166
|
Keep provider auth and capability evidence separate from deployment health;
|
|
@@ -146,6 +192,15 @@ carries `.agents`/`.claude` state, restarts before verification, and prunes to
|
|
|
146
192
|
the current release plus one rollback candidate. It never
|
|
147
193
|
contains credentials and never SSHs, changes DNS, restarts systemd or deploys.
|
|
148
194
|
|
|
195
|
+
VPS plans use a dedicated deployer account by default:
|
|
196
|
+
`--deployer-user maggie-deploy`. The generated sudoers contract permits only
|
|
197
|
+
the exact `/bin/systemctl restart <service>` and
|
|
198
|
+
`/bin/systemctl is-active <service>` commands for the named service. Release
|
|
199
|
+
files and the application remain separated (`maggie-deploy` versus
|
|
200
|
+
`www-data`); no wildcard, shell, `sudo su`, or broad root command is generated.
|
|
201
|
+
Install and review that narrow sudoers policy on the host before executing a
|
|
202
|
+
runner.
|
|
203
|
+
|
|
149
204
|
VPS plans include a bounded retention policy: keep two immutable releases,
|
|
150
205
|
preserve the `current` target and rollback target, and review prune candidates
|
|
151
206
|
before any operator executes cleanup. Generate a read-only candidate report:
|
|
@@ -186,6 +241,23 @@ The gate fails on a missing or mismatched target identity and never executes a
|
|
|
186
241
|
migration. A successful connection alone is not proof that the intended
|
|
187
242
|
database was selected.
|
|
188
243
|
|
|
244
|
+
Before activation, reconcile the host's migration ledger rather than relying
|
|
245
|
+
on a remembered local migration list:
|
|
246
|
+
|
|
247
|
+
```bash
|
|
248
|
+
maggie migration reconcile \
|
|
249
|
+
--evidence .maggie/migration/server-ledger.json \
|
|
250
|
+
--migration-dir migrations \
|
|
251
|
+
--output .maggie/migration/ledger-reconcile.json
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
The host adapter must query `maggie_schema_migrations` and emit only the
|
|
255
|
+
version identifiers and environment. The read-only command orders local
|
|
256
|
+
numbered SQL files, reports `missing`, and remains `mutation: "not executed"`.
|
|
257
|
+
Apply every missing file through the host migration runner, re-read the ledger,
|
|
258
|
+
and only then continue to the release switch; a missing version is a failed
|
|
259
|
+
deployment preflight, not evidence that activation can proceed.
|
|
260
|
+
|
|
189
261
|
If a release depends on existing rows or seeded data, set
|
|
190
262
|
`dataDependencies: true` in `.maggie/migration-manifest.json` and provide
|
|
191
263
|
`.maggie/deployment/data-release.json` before deployment. The checkpoint must
|
|
@@ -39,6 +39,19 @@ owner before any remote mutation.
|
|
|
39
39
|
|
|
40
40
|
### SSH and secret-source contract
|
|
41
41
|
|
|
42
|
+
First run the shared credential presence check against the project `.env`:
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
maggie deployment credential-preflight --env-file .env \
|
|
46
|
+
--expected-host example-host
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
The canonical password-based names are `DEPLOY_SERVER_IP`,
|
|
50
|
+
`DEPLOY_SERVER_SSH_USER`, `DEPLOY_SERVER_SSH_PASSWORD`, and
|
|
51
|
+
`DEPLOY_SERVER_SSH_SUDOER`. The command reports only presence and an optional
|
|
52
|
+
host match; it never prints a value. A provider may instead use an SSH key, but
|
|
53
|
+
must state that alternate name and source in its plan.
|
|
54
|
+
|
|
42
55
|
Use these canonical project variables when a VPS adapter is configured:
|
|
43
56
|
|
|
44
57
|
| Variable | Meaning | Precedence |
|
|
@@ -86,6 +99,19 @@ The generated Nginx/Astro boundary keeps `checkOrigin` enabled and requires
|
|
|
86
99
|
canonical HTTPS `allowedDomains` plus trusted `X-Forwarded-Host`/
|
|
87
100
|
`X-Forwarded-Proto` handling when TLS terminates at the proxy.
|
|
88
101
|
|
|
102
|
+
Use a dedicated least-privilege deployer when generating the plan:
|
|
103
|
+
|
|
104
|
+
```bash
|
|
105
|
+
python3 tools/clis/maggie_deployment.py . --vps-plan \
|
|
106
|
+
--domain example.co.uk --service example --node-port 4321 \
|
|
107
|
+
--deployer-user maggie-deploy
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
The plan separates the SSH/deploy account from the `www-data` application
|
|
111
|
+
account and allowlists only the exact service restart and status commands.
|
|
112
|
+
The runner uses non-interactive `sudo -n`; it never requires broad sudo or a
|
|
113
|
+
shell escalation. Review/install the host sudoers entry separately.
|
|
114
|
+
|
|
89
115
|
Review the generated systemd and Nginx files, then obtain explicit approval
|
|
90
116
|
before installing them on a host.
|
|
91
117
|
|
|
@@ -68,6 +68,22 @@ cannot render the icon, add an approved runtime definition or inline SVG
|
|
|
68
68
|
fallback and rerun both checks. Never release a source token solely because
|
|
69
69
|
typecheck or build succeeded.
|
|
70
70
|
|
|
71
|
+
Compose the static inventory with browser-painted evidence before declaring a
|
|
72
|
+
design release complete:
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
maggie design icon-release-gate \
|
|
76
|
+
--icon-report docs/icon-inventory.json \
|
|
77
|
+
--browser-report .maggie/icon-browser-evidence.json \
|
|
78
|
+
--output docs/icon-release-gate.json
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
The browser evidence must use `maggie-icon-browser-evidence.v1`, include at
|
|
82
|
+
least one route, and report each glyph as visible with positive dimensions,
|
|
83
|
+
a successful `assetStatus` (2xx), and a non-empty accessible name. This
|
|
84
|
+
gate is independent from typecheck/build and is read-only apart from its
|
|
85
|
+
explicit output.
|
|
86
|
+
|
|
71
87
|
## Automatic memory hook
|
|
72
88
|
|
|
73
89
|
Follow [Maggie Memory Hook](../../references/memory-hook.md) at invocation and completion.
|
|
@@ -57,8 +57,17 @@ fields and supplies the normal `type`, `summary`, `expected`, `actual`,
|
|
|
57
57
|
`errorFingerprint`, reproduction, resolution, validation, and screenshot
|
|
58
58
|
metadata fields. It may also provide bounded `routeIds` and
|
|
59
59
|
`validationEvidence` identifiers. Each generated draft stores only the safe
|
|
60
|
-
batch ID, zero-based index, and bounded size.
|
|
61
|
-
|
|
60
|
+
batch ID, canonical zero-based index, and bounded size. Direct `collect` calls
|
|
61
|
+
use zero-based `--batch-index` by default. If an external runner reports
|
|
62
|
+
one-based positions, pass `--batch-base 1`; the final item is then accepted and
|
|
63
|
+
normalized before it is stored. The batch command still creates local drafts
|
|
64
|
+
only.
|
|
65
|
+
|
|
66
|
+
For example, the third item in a three-item, one-based batch is collected as:
|
|
67
|
+
|
|
68
|
+
maggie feedback collect --project . --batch-id run-review-001 \
|
|
69
|
+
--batch-index 3 --batch-size 3 --batch-base 1 \
|
|
70
|
+
--summary "Final item" --type bug
|
|
62
71
|
|
|
63
72
|
Aggregate a batch before manual review:
|
|
64
73
|
|
|
@@ -118,6 +118,22 @@ with a reviewer. Commit the approved change and new contract together; never
|
|
|
118
118
|
automatically replace the baseline following failure. Dynamic dates, class
|
|
119
119
|
names and copy can produce legitimate differences requiring review.
|
|
120
120
|
|
|
121
|
+
To approve an intentional drift, write a new file and require a reason for
|
|
122
|
+
every changed, added, removed, or content-changed URL:
|
|
123
|
+
|
|
124
|
+
```bash
|
|
125
|
+
maggie site-audit https://example.com --crawl --json \
|
|
126
|
+
--baseline docs/seo-baseline-v1.json \
|
|
127
|
+
--recapture-baseline docs/seo-baseline-v2.json \
|
|
128
|
+
--baseline-id seo-v2 --reviewer maintainer \
|
|
129
|
+
--reason 'https://example.com/pricing=approved pricing refresh'
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
The command fails closed when the current crawl is incomplete, a drift has no
|
|
133
|
+
reason, a reason names a URL without a reported drift, or the destination file
|
|
134
|
+
already exists. The new contract records its `baselineId`, `supersedes` value,
|
|
135
|
+
reviewer, and approved reasons; the old baseline is never overwritten.
|
|
136
|
+
|
|
121
137
|
This covers server-rendered sitemap pages, not CSS rendering, JavaScript-only
|
|
122
138
|
content, database translation keys or browser interactions. Query-string URLs
|
|
123
139
|
are recorded as excluded from byte baselines because they often represent
|
|
@@ -256,7 +272,12 @@ metadata, valid entity JSON-LD, and image alt text. Non-HTML endpoints such as
|
|
|
256
272
|
RSS must not be included in the HTML page sitemap. Sitemap `<loc>` values must
|
|
257
273
|
be absolute HTTP(S) URLs; the audit reports relative values as a failure even
|
|
258
274
|
when it can resolve them for continued crawling, so one malformed entry cannot
|
|
259
|
-
hide a protocol violation.
|
|
275
|
+
hide a protocol violation. Absolute sitemap locations are rebased to the
|
|
276
|
+
origin passed to `site-audit` by default, so `--crawl` cannot silently audit
|
|
277
|
+
production from a staging/local command. The JSON crawl evidence records
|
|
278
|
+
`requestedOrigin` and `sitemapOriginPolicy: "requested-origin"`. Use
|
|
279
|
+
`--preserve-sitemap-origin` only when an explicitly reviewed cross-origin crawl
|
|
280
|
+
is intended; the report then says `"declared-origin"`.
|
|
260
281
|
Use `--output <project>/docs/site-audit.json` to persist the evidence used by
|
|
261
282
|
the release review.
|
|
262
283
|
|
|
@@ -933,6 +933,13 @@ def command_fixture(args: argparse.Namespace) -> int:
|
|
|
933
933
|
return 0
|
|
934
934
|
|
|
935
935
|
|
|
936
|
+
def command_feedback(args: argparse.Namespace) -> int:
|
|
937
|
+
"""Dispatch feedback subcommands through the canonical feedback CLI."""
|
|
938
|
+
cli = Path(__file__).with_name("maggie_feedback.py")
|
|
939
|
+
completed = subprocess.run([sys.executable, str(cli), *args.feedback_args], cwd=Path.cwd(), check=False)
|
|
940
|
+
return completed.returncode
|
|
941
|
+
|
|
942
|
+
|
|
936
943
|
def parser() -> argparse.ArgumentParser:
|
|
937
944
|
p = argparse.ArgumentParser(prog="maggie", description=__doc__)
|
|
938
945
|
sub = p.add_subparsers(dest="command", required=True)
|
|
@@ -984,6 +991,9 @@ def parser() -> argparse.ArgumentParser:
|
|
|
984
991
|
item = fixture_sub.add_parser(fixture_name)
|
|
985
992
|
item.add_argument("project", nargs="?", default=".")
|
|
986
993
|
item.set_defaults(func=command_fixture)
|
|
994
|
+
feedback = sub.add_parser("feedback", help="collect, review, and submit privacy-safe feedback")
|
|
995
|
+
feedback.add_argument("feedback_args", nargs=argparse.REMAINDER, help="arguments for maggie_feedback.py")
|
|
996
|
+
feedback.set_defaults(func=command_feedback)
|
|
987
997
|
doctor = sub.add_parser("doctor", help="check blog routes and SEO output invariants")
|
|
988
998
|
doctor.add_argument("project", nargs="?", default=".")
|
|
989
999
|
doctor.add_argument("--require-bootstrap", action="store_true")
|
|
@@ -1121,5 +1131,7 @@ def parser() -> argparse.ArgumentParser:
|
|
|
1121
1131
|
|
|
1122
1132
|
|
|
1123
1133
|
if __name__ == "__main__":
|
|
1134
|
+
if sys.argv[1:2] == ["feedback"]:
|
|
1135
|
+
raise SystemExit(command_feedback(argparse.Namespace(feedback_args=sys.argv[2:])))
|
|
1124
1136
|
arguments = parser().parse_args()
|
|
1125
1137
|
raise SystemExit(arguments.func(arguments))
|
|
@@ -67,6 +67,18 @@ def release_gate(args: argparse.Namespace) -> int:
|
|
|
67
67
|
check("referral-contract", set(contract["referralSources"]).issubset({"search", "partner", "social", "email", "direct", "unknown"}), "referral categories use the redacted taxonomy", checks)
|
|
68
68
|
else:
|
|
69
69
|
check("referral-contract", False, "contract must declare referralSources", checks)
|
|
70
|
+
consent = contract.get("consent")
|
|
71
|
+
valid_consent = (
|
|
72
|
+
isinstance(consent, dict)
|
|
73
|
+
and consent.get("defaultBeforeContainer") is True
|
|
74
|
+
and consent.get("firstPartyStorageMode") in {"stop", "degrade"}
|
|
75
|
+
and consent.get("intentionalFormMode") in {"record", "omit"}
|
|
76
|
+
)
|
|
77
|
+
check(
|
|
78
|
+
"consent-contract", valid_consent,
|
|
79
|
+
"consent defaults precede the container and first-party/form behavior is explicit",
|
|
80
|
+
checks,
|
|
81
|
+
)
|
|
70
82
|
browser, browser_errors = load_json(Path(args.render_report).resolve(), "render-report")
|
|
71
83
|
errors.extend(browser_errors)
|
|
72
84
|
network, network_errors = load_json(Path(args.network_report).resolve(), "network-report")
|
|
@@ -79,6 +91,28 @@ def release_gate(args: argparse.Namespace) -> int:
|
|
|
79
91
|
check("browser-schema", browser.get("schemaVersion") == "maggie-analytics-browser.v1", "versioned browser evidence", checks)
|
|
80
92
|
check("browser-render", browser.get("passed") is True and isinstance(browser.get("routes"), list) and bool(browser["routes"]), "routes rendered without a browser failure", checks)
|
|
81
93
|
check("browser-console", isinstance(browser.get("consoleErrors"), list) and not browser["consoleErrors"], "no browser console errors", checks)
|
|
94
|
+
consent = contract.get("consent") if contract else None
|
|
95
|
+
browser_consent = browser.get("consent")
|
|
96
|
+
check(
|
|
97
|
+
"consent-ordering", isinstance(consent, dict) and isinstance(browser_consent, dict)
|
|
98
|
+
and browser_consent.get("defaultBeforeContainer") is True
|
|
99
|
+
and browser_consent.get("containerLoadedAfterDefault") is True,
|
|
100
|
+
"browser evidence proves default consent precedes container loading",
|
|
101
|
+
checks,
|
|
102
|
+
)
|
|
103
|
+
check(
|
|
104
|
+
"first-party-scope", isinstance(consent, dict) and isinstance(browser_consent, dict)
|
|
105
|
+
and browser_consent.get("firstPartyStorageMode") == consent.get("firstPartyStorageMode")
|
|
106
|
+
and browser_consent.get("firstPartyStorageObserved") is True,
|
|
107
|
+
"browser evidence proves the declared first-party storage behavior",
|
|
108
|
+
checks,
|
|
109
|
+
)
|
|
110
|
+
check(
|
|
111
|
+
"intentional-form-scope", isinstance(consent, dict) and isinstance(browser_consent, dict)
|
|
112
|
+
and browser_consent.get("intentionalFormMode") == consent.get("intentionalFormMode"),
|
|
113
|
+
"browser evidence records the declared intentional-form behavior",
|
|
114
|
+
checks,
|
|
115
|
+
)
|
|
82
116
|
if network:
|
|
83
117
|
pre = network.get("preConsentRequests")
|
|
84
118
|
check("pre-consent-network", isinstance(pre, list) and not pre, "no analytics requests before consent", checks)
|