@topy-ai/maggie 0.7.48 → 0.7.50
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 +37 -4
- package/bin/maggie.js +34 -16
- package/bundled-contracts/google-integrations/capability-report-v2.schema.json +2 -1
- package/bundled-contracts/maggie-content/email-localization-v1.schema.json +89 -0
- package/bundled-contracts/maggie-content/lifecycle-email-v1.schema.json +76 -0
- package/bundled-contracts/maggie-deployment/readiness-v1.schema.json +6 -1
- package/bundled-contracts/maggie-ops/marketing-run-v1.schema.json +89 -0
- package/bundled-contracts/maggie-ops/notification-catalogue-example-v1.json +941 -0
- package/bundled-contracts/maggie-ops/notification-catalogue-v1.schema.json +273 -0
- package/bundled-contracts/maggie-service-booking/fact-provenance-v1.schema.json +128 -0
- package/bundled-contracts/maggie-service-booking/import-stages-v1.schema.json +191 -0
- package/bundled-references/google-integrations-runbook.md +54 -0
- package/bundled-skills/maggie-content-localization/SKILL.md +17 -1
- package/bundled-skills/maggie-content-localization/references/email-and-lifecycle.md +83 -0
- package/bundled-skills/maggie-deployment/SKILL.md +89 -7
- package/bundled-skills/maggie-deployment/references/vps.md +38 -6
- package/bundled-skills/maggie-design/SKILL.md +55 -0
- package/bundled-skills/maggie-feedback/SKILL.md +29 -0
- package/bundled-skills/maggie-ops/SKILL.md +37 -0
- package/bundled-skills/maggie-ops/references/notifications-operations.md +154 -0
- package/bundled-skills/maggie-service-booking/SKILL.md +59 -0
- package/bundled-skills/maggie-social-share/SKILL.md +19 -2
- package/bundled-skills/maggie-social-share/references/marketing-run.md +57 -0
- package/bundled-skills/maggie-social-share/references/queue-and-connections.md +51 -0
- package/bundled-tools/clis/maggie_deployment.py +58 -17
- package/bundled-tools/clis/maggie_deployment_auth_canary.py +216 -0
- package/bundled-tools/clis/maggie_deployment_collect.py +225 -0
- package/bundled-tools/clis/maggie_deployment_readiness.py +53 -3
- package/bundled-tools/clis/maggie_design.py +8 -0
- package/bundled-tools/clis/maggie_design_verify.py +359 -0
- package/bundled-tools/clis/maggie_docs.py +82 -4
- package/bundled-tools/clis/maggie_email_localization.py +382 -0
- package/bundled-tools/clis/maggie_feedback.py +9 -2
- package/bundled-tools/clis/maggie_icon_glyph_check.py +382 -0
- package/bundled-tools/clis/maggie_icon_release_gate.py +28 -1
- package/bundled-tools/clis/maggie_localization.py +5 -0
- package/bundled-tools/clis/maggie_marketing_run.py +272 -0
- package/bundled-tools/clis/maggie_notifications.py +528 -0
- package/bundled-tools/clis/maggie_ops.py +87 -0
- package/bundled-tools/clis/maggie_schedule.py +12 -2
- package/bundled-tools/clis/maggie_service_import.py +520 -0
- package/bundled-tools/clis/maggie_social_queue.py +104 -0
- package/bundled-tools/clis/maggie_social_share.py +6 -2
- package/bundled-tools/runtime/google_ads.py +306 -0
- package/bundled-tools/runtime/google_capabilities.py +18 -2
- package/bundled-tools/runtime/google_remediation.py +152 -0
- package/package.json +1 -1
- package/references/google-integrations-runbook.md +54 -0
package/README-zh-TW.md
CHANGED
|
@@ -29,7 +29,7 @@ npx @topy-ai/maggie init --scope project --agent all
|
|
|
29
29
|
npx @topy-ai/maggie doctor --scope project --project .
|
|
30
30
|
```
|
|
31
31
|
|
|
32
|
-
目前 npm 版本為 `0.7.48
|
|
32
|
+
目前 npm 版本為 `0.7.50`:`maggie update` 改為 idempotent,內容已與套件相同的檔案不再改寫(保留時間戳),摘要分別列出 changed/unchanged/preserved 數量,只有真的保留了本機修改時才顯示 preserved 提示。前一版 `0.7.49` 完成 batch 27:33 條 2026-09-09 至 09-16 建立但從未提交的本機 feedback drafts,已逐條對照目前程式碼(其中兩條已被既有功能滿足)。新增離線 `maggie ops notifications`(通知 catalogue 合約、consent/retention/durable lead delivery 規則、provider template drift、只檢查變數名稱的 Resend preflight、queue health 門檻與 operator alerts、dry-run retention plan);`maggie localization email-matrix` 與 `maggie localization lifecycle`(locale 優先順序、未翻譯/缺漏 locale、變數與 HTML/text 一致、market CTA route、consent-aware 行銷 email 預設不發送);Deployment 的 `--keep-releases` 統一 retention policy、`auth-canary`、資料庫 owner 無法讀取 release 路徑時的 streamed migration、`collect` 單一 readiness report;Google failure remediation(`maggie ops google-diagnose`)與唯讀 `google-ads-preflight`/`google-ads-keyword-ideas`;Social Share `reconcile`(timeout 後不重複發文)、`maggie-marketing-run-v1` 合約、命名排程層與只管制對外發布的 regulated-content review;`maggie design icon-glyph-check`、`maggie design verify`、`maggie service import-stages-validate`/`import-readiness`/`fact-provenance`;以及 `--release-metadata` 版本一致性檢查、`maggie docs rollout-status` 與 stdin batch 輸入。前一版 `0.7.48` 處理 2026-10-10 的 27 條 hosted feedback(batch 26):Social Share 新增 `adapters`(每個 provider 一組 canonical OAuth scope,LinkedIn 不同 scope 會撤銷舊 token;共用 OAuth client 警告)、`connections`(撤銷或無法解密的 token 標為 `needs_reconnect`,偵測會過期的簽名頭像 URL)、`queue`(slot-based 排程:not-before、最新優先、campaign 輪流與每日上限、DST-safe)與 `campaigns`(idea stage Start gate);Deployment 新增 hash-only `secret-fingerprint`/`secret-parity`、`env-isolation`(本機 `.env` 指向 production database 時警告)、release retention 與 worker-before-enqueue 發布順序;QA 在未明確同意時阻擋對 production API 的寫入情境,並以 `maggie qa cors-preflight` 只用 OPTIONS 檢查每個 HTTP method;Design 新增 `pressable-check`、`layer-check`(Tailwind v4 unlayered CSS)、onboarding wizard/picker 模式與 `maggie-palette-roles-v1` palette generate/validate;Marketplace 加入 screenshot 完整性與像素預算、從 CSS 量測 palette、asset provenance、中性 `displayName`(全部模板已補齊)、template studio、`maggie-template-content-v1` 合約與圖片生成成本/無文字審查 gate;Booking 新增唯讀 Stripe live setup runbook 與 gift voucher lifecycle 合約(`maggie booking voucher-contract --ledger`);Feedback 新增 `improvement` 類型與 `maggie feedback session-summary`。MaggieDash 0.2.11 會保留尚未部署 template 的 outbox email 而不是 dead-letter,並從 ORA host 上游通用修正。本版也包含 Booking 十個 email events 合約與 CLI validator 同步及安全輸出的 `arrivalNote`。前一版 `0.7.47` 處理 2026-09-26 五條新 feedback:project-scope
|
|
33
33
|
`maggie init` 會建立本地 memory store;context 預設只讀取本 project scope;memory hook
|
|
34
34
|
在 local Python adapter 不存在時 fallback 到已安裝 CLI;重複 init 保留既有檔案與時間戳;
|
|
35
35
|
`maggie feedback list` 的 `--project` 可放在子命令前或後。Generated VPS runner 現在記錄
|
|
@@ -113,7 +113,7 @@ structure drift 或重複 treatment product 時 fail closed。
|
|
|
113
113
|
deployment、memory、feedback 和 MaggieDash。內容先 draft/review,外部寫入、
|
|
114
114
|
publish 與 production deployment 需要明確確認。
|
|
115
115
|
|
|
116
|
-
目前 npm 版本為 `0.7.
|
|
116
|
+
目前 npm 版本為 `0.7.50`,包含 batch 26、27 feedback 修正與 idempotent `maggie update`與 Booking email-template 合約/CLI validator 同步。本版完成 2026-09-24 booking feedback batch:Calendar grid/free-slot entry 與 host modal focus-restoration evidence。本版新增 Starter marketplace provisioning plan;本版完成 feedback batches 22、23:加入 declarative browser interaction evidence、design markup/style/content-key gate、compiler source anchoring、entity double-escape protection、`update --help` read-only、noindex hypothetical indexability、可過期 baseline acknowledgement、DOM-only link extraction regression,以及 MaggieDash 0.2.10 的 content override、短期 browser session、CDN-safe public-session cache contracts。authentication 和 isolated dev server 仍由 host 負責。`maggie-booking` workflow、傳統 email/password、Stripe、Resend、public booking flow 及既有安全邊界維持不變;provider-bound video generation 與 transactional delivery 仍記錄在 issue #39,前一批延後功能仍在 issue #38,不會直接成為 active memory。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
|
|
117
117
|
dispatch、`maggie --version`、feedback batch review 聚合與重複偵測、marketplace enrichment evidence、booking
|
|
118
118
|
worker/resolver evidence,以及 read-only migration preflight。它也包含 host-owned mobile app surface contract、signed-in
|
|
119
119
|
camera-state QA、直接 Astro route resolution、correlated feedback batch,以及
|
package/README.md
CHANGED
|
@@ -89,8 +89,41 @@ Maggie keeps the existing project foundation and asks for decisions before
|
|
|
89
89
|
shared routes, analytics, or publishing boundaries change. The current
|
|
90
90
|
package ships 20 installable skills and a local-first MaggieDash foundation.
|
|
91
91
|
|
|
92
|
-
This package is `0.7.
|
|
93
|
-
|
|
92
|
+
This package is `0.7.50`. `0.7.50` makes `maggie update` idempotent: files whose content already
|
|
93
|
+
matches the package are left untouched (timestamps included) and counted as
|
|
94
|
+
unchanged, the summary reports changed/unchanged/preserved counts, and the
|
|
95
|
+
"local files were preserved" notice appears only when a file was actually
|
|
96
|
+
preserved.
|
|
97
|
+
|
|
98
|
+
The 0.7.49 release closed batch 27: 33 local feedback
|
|
99
|
+
drafts from 2026-09-09 to 09-16 that were never submitted, reconciled against
|
|
100
|
+
the current code (two were already satisfied):
|
|
101
|
+
|
|
102
|
+
- Notifications: offline `maggie ops notifications` — catalogue contract with
|
|
103
|
+
consent, retention and durable lead-delivery rules, template drift against
|
|
104
|
+
paginated provider exports, Resend preflight by variable name, queue health
|
|
105
|
+
thresholds with operator alerts, and a dry-run retention plan.
|
|
106
|
+
- Email localization: `maggie localization email-matrix` (locale precedence,
|
|
107
|
+
untranslated/missing locales, variable and HTML/text parity, market CTA
|
|
108
|
+
routes) and `maggie localization lifecycle` (consent-aware marketing email
|
|
109
|
+
with a no-send default until approved).
|
|
110
|
+
- Deployment: one `--keep-releases` retention policy shared by plan, runner,
|
|
111
|
+
preflight and rollback evidence; `auth-canary` for role-scoped
|
|
112
|
+
authenticated API probes; streamed migrations for a database owner that
|
|
113
|
+
cannot read the release path; `collect` for one readiness report.
|
|
114
|
+
- Google: failure remediation (`maggie ops google-diagnose`) and read-only
|
|
115
|
+
`google-ads-preflight` / `google-ads-keyword-ideas`.
|
|
116
|
+
- Marketing: Social Share `reconcile` (no duplicate post after a timeout), the
|
|
117
|
+
`maggie-marketing-run-v1` contract, named schedule layers, and opt-in
|
|
118
|
+
regulated-content review that gates only external publication.
|
|
119
|
+
- Design and imports: `maggie design icon-glyph-check`, `maggie design
|
|
120
|
+
verify`, and `maggie service import-stages-validate`, `import-readiness`
|
|
121
|
+
and `fact-provenance`.
|
|
122
|
+
- Feedback and release: `validate_docs_freshness.py --release-metadata`,
|
|
123
|
+
`maggie docs rollout-status`, and stdin batch input.
|
|
124
|
+
|
|
125
|
+
The 0.7.48 release remains included: it processed the 27 hosted feedback
|
|
126
|
+
records of 2026-10-10 (batch 26) and added the Booking email-template
|
|
94
127
|
contract/CLI sync with escaped `arrivalNote` rendering:
|
|
95
128
|
|
|
96
129
|
- Social Share: `adapters` enforces one canonical OAuth scope set per provider
|
|
@@ -701,8 +734,8 @@ artifact schemas.
|
|
|
701
734
|
Recommended upgrade sequence for the current release:
|
|
702
735
|
|
|
703
736
|
```bash
|
|
704
|
-
npx @topy-ai/maggie@0.7.
|
|
705
|
-
npx @topy-ai/maggie@0.7.
|
|
737
|
+
npx @topy-ai/maggie@0.7.50 update --scope project --project . --force
|
|
738
|
+
npx @topy-ai/maggie@0.7.50 cleanup --scope project --project .
|
|
706
739
|
```
|
|
707
740
|
|
|
708
741
|
Maintainers should pass npm credentials through the repository helper, never
|
package/bin/maggie.js
CHANGED
|
@@ -130,6 +130,8 @@ Usage:
|
|
|
130
130
|
maggie design app-validate --project PATH --plan PATH --runtime-evidence FILE --rendered-dir PATH --confirm
|
|
131
131
|
maggie design icon-inventory --project PATH --source-dir src --runtime assets/icons.css --output docs/icon-inventory.json
|
|
132
132
|
maggie design icon-release-gate --icon-report FILE --browser-report FILE --output FILE
|
|
133
|
+
maggie design icon-glyph-check (--base-url URL | --dist DIR) --route / --output FILE
|
|
134
|
+
maggie design verify JOB_ID (--base-url URL | --dist DIR) [--stage before|after] [--build-command CMD]
|
|
133
135
|
maggie design author --project PATH --route /about --purpose TEXT --audience TEXT --confirm
|
|
134
136
|
maggie design markup-check --html FILE [--require-content-keys]
|
|
135
137
|
maggie design in-place --project PATH --route /pricing [--content-source PATH]
|
|
@@ -151,6 +153,9 @@ Usage:
|
|
|
151
153
|
maggie service inspect --project PATH
|
|
152
154
|
maggie service status --project PATH
|
|
153
155
|
maggie service orchestration-validate --project PATH --manifest FILE
|
|
156
|
+
maggie service import-stages-validate --project PATH --manifest FILE
|
|
157
|
+
maggie service import-readiness --project PATH [--python-module M] [--browser] [--webdriver] [--env NAME] [--country LABEL]
|
|
158
|
+
maggie service fact-provenance --project PATH --facts FILE [--output FILE]
|
|
154
159
|
maggie service convert-page <page-path> --project PATH
|
|
155
160
|
maggie service match-pages --project PATH --pages-dir src/pages
|
|
156
161
|
maggie deployment --project PATH --target vps-with-cloudflare-dns
|
|
@@ -158,6 +163,8 @@ Usage:
|
|
|
158
163
|
maggie deployment secret-parity --manifest api-1.json --manifest api-2.json --required KEY
|
|
159
164
|
maggie deployment env-isolation --project PATH --production-env .env.production
|
|
160
165
|
maggie deployment readiness --project PATH
|
|
166
|
+
maggie deployment collect --project PATH --config .maggie/deployment/collector.json
|
|
167
|
+
maggie deployment auth-canary --plan auth-canary-plan.json [--allow-mutations] --output FILE
|
|
161
168
|
maggie deployment parity --project PATH --evidence FILE --output FILE
|
|
162
169
|
maggie deployment canary --project PATH --asset URL=SHA256 --render-report report.json --output docs/deployment-canary.json
|
|
163
170
|
maggie deployment release-manifest --evidence FILE --output FILE
|
|
@@ -177,7 +184,7 @@ Usage:
|
|
|
177
184
|
maggie release PATH --profile .maggie/release-profile.json --environment staging --target vps-with-cloudflare-dns
|
|
178
185
|
maggie api lifecycle --project PATH [--execute --allow-quota]
|
|
179
186
|
maggie memory <init|list|search|context|add|record-error|transition|export> --project PATH
|
|
180
|
-
maggie localization <extract|plan|generate|preview|validate|review|publish|stale|glossary> [options]
|
|
187
|
+
maggie localization <extract|plan|generate|preview|validate|review|publish|stale|glossary|email-matrix|lifecycle> [options]
|
|
181
188
|
maggie seo performance|images|sitemap|indexnow|social-cards|head-tags [options] (sitemap supports strict validate and agent-files)
|
|
182
189
|
maggie feedback <collect|preview|batch|batch-review|session-summary|submit|list> [options]
|
|
183
190
|
maggie qa <start|record|summary|export|assertion-audit|cors-preflight> [options]
|
|
@@ -188,6 +195,9 @@ Usage:
|
|
|
188
195
|
maggie verification coverage --contract FILE --evidence FILE
|
|
189
196
|
maggie ops audit|preflight|verify|lockfiles|seed-manifest|google-capabilities|favicon-check --project PATH
|
|
190
197
|
maggie ops google-capabilities --project PATH --report FILE [--output FILE]
|
|
198
|
+
maggie ops google-diagnose --code CODE [--reason TEXT] [--http-status N] [--provider P]
|
|
199
|
+
maggie ops google-ads-preflight|google-ads-keyword-ideas --customer-id ID [--login-customer-id ID]
|
|
200
|
+
maggie ops notifications catalogue|templates|preflight|health|retention|alerts --project PATH ...
|
|
191
201
|
maggie ops preflight --project PATH --write
|
|
192
202
|
|
|
193
203
|
Examples:
|
|
@@ -378,13 +388,13 @@ function diffSummary(source, target) {
|
|
|
378
388
|
return `${added} local additions, ${removed} package lines removed across ${blocks} changed blocks (${localLines.length} local lines vs ${packageLines.length} package lines)`;
|
|
379
389
|
}
|
|
380
390
|
|
|
381
|
-
function syncTree(source, target, force, root = null, managedFiles = {}) {
|
|
391
|
+
function syncTree(source, target, force, root = null, managedFiles = {}, stats = { unchanged: 0, preserved: 0 }) {
|
|
382
392
|
let changed = 0;
|
|
383
393
|
for (const entry of readdirSync(source, { withFileTypes: true })) {
|
|
384
394
|
const sourcePath = join(source, entry.name);
|
|
385
395
|
const targetPath = join(target, entry.name);
|
|
386
396
|
if (entry.isDirectory()) {
|
|
387
|
-
changed += syncTree(sourcePath, targetPath, force, root, managedFiles);
|
|
397
|
+
changed += syncTree(sourcePath, targetPath, force, root, managedFiles, stats);
|
|
388
398
|
continue;
|
|
389
399
|
}
|
|
390
400
|
const managedPath = root ? relative(root, targetPath) : targetPath;
|
|
@@ -396,12 +406,16 @@ function syncTree(source, target, force, root = null, managedFiles = {}) {
|
|
|
396
406
|
writeFileSync(targetPath, readFileSync(sourcePath));
|
|
397
407
|
console.log(`installed ${targetPath}`);
|
|
398
408
|
changed++;
|
|
399
|
-
} else if (
|
|
409
|
+
} else if (packageDigest === localDigest) {
|
|
410
|
+
// Identical content: leave the file and its timestamps untouched.
|
|
411
|
+
stats.unchanged++;
|
|
412
|
+
} else if (force || wasManaged) {
|
|
400
413
|
writeFileSync(targetPath, readFileSync(sourcePath));
|
|
401
414
|
console.log(`updated ${targetPath}`);
|
|
402
415
|
changed++;
|
|
403
416
|
} else {
|
|
404
417
|
console.log(`preserved ${targetPath} (local changes; ${diffSummary(sourcePath, targetPath)}; use --force to replace)`);
|
|
418
|
+
stats.preserved++;
|
|
405
419
|
}
|
|
406
420
|
}
|
|
407
421
|
return changed;
|
|
@@ -535,6 +549,7 @@ function update(args) {
|
|
|
535
549
|
const previousManagedFiles = previousManifest.managedFiles && typeof previousManifest.managedFiles === "object" ? previousManifest.managedFiles : {};
|
|
536
550
|
if (!existsSync(SKILLS_ROOT)) throw new Error("bundled skills are missing; run npm pack from the package source");
|
|
537
551
|
let updated = 0;
|
|
552
|
+
const stats = { unchanged: 0, preserved: 0 };
|
|
538
553
|
const managedRoot = scope === USER_SCOPE ? "/" : root;
|
|
539
554
|
for (const agentRoot of roots) {
|
|
540
555
|
for (const skill of skills) {
|
|
@@ -544,22 +559,22 @@ function update(args) {
|
|
|
544
559
|
console.log(`absent ${target} (run install to add it)`);
|
|
545
560
|
continue;
|
|
546
561
|
}
|
|
547
|
-
updated += syncTree(source, target, force, managedRoot, previousManagedFiles);
|
|
562
|
+
updated += syncTree(source, target, force, managedRoot, previousManagedFiles, stats);
|
|
548
563
|
}
|
|
549
|
-
if (existsSync(REFERENCES_ROOT) && existsSync(join(agentRoot, "references"))) updated += syncTree(REFERENCES_ROOT, join(agentRoot, "references"), force, managedRoot, previousManagedFiles);
|
|
564
|
+
if (existsSync(REFERENCES_ROOT) && existsSync(join(agentRoot, "references"))) updated += syncTree(REFERENCES_ROOT, join(agentRoot, "references"), force, managedRoot, previousManagedFiles, stats);
|
|
550
565
|
}
|
|
551
566
|
if (scope === PROJECT_SCOPE) {
|
|
552
567
|
const tools = join(root, "tools");
|
|
553
568
|
if (existsSync(TOOLS_ROOT)) for (const group of ["clis", "runtime", "integrations"]) if (existsSync(join(TOOLS_ROOT, group))) {
|
|
554
569
|
const target = join(tools, group);
|
|
555
|
-
if (existsSync(target)) updated += syncTree(join(TOOLS_ROOT, group), target, force, root, previousManagedFiles);
|
|
570
|
+
if (existsSync(target)) updated += syncTree(join(TOOLS_ROOT, group), target, force, root, previousManagedFiles, stats);
|
|
556
571
|
}
|
|
557
572
|
if (existsSync(join(DESIGN_ROOT, "SPA-DESIGN.md")) && existsSync(join(root, ".maggie", "design-reference"))) {
|
|
558
|
-
updated += syncTree(DESIGN_ROOT, join(root, ".maggie", "design-reference"), force, root, previousManagedFiles);
|
|
573
|
+
updated += syncTree(DESIGN_ROOT, join(root, ".maggie", "design-reference"), force, root, previousManagedFiles, stats);
|
|
559
574
|
}
|
|
560
|
-
if (existsSync(MARKETPLACE_ROOT) && existsSync(join(root, "marketplace"))) updated += syncTree(MARKETPLACE_ROOT, join(root, "marketplace"), force, root, previousManagedFiles);
|
|
561
|
-
if (existsSync(CONTRACTS_ROOT) && existsSync(join(root, "contracts"))) updated += syncTree(CONTRACTS_ROOT, join(root, "contracts"), force, root, previousManagedFiles);
|
|
562
|
-
if (existsSync(join(TEMPLATES_ROOT, "maggiedash")) && existsSync(join(root, "templates", "maggiedash"))) updated += syncTree(join(TEMPLATES_ROOT, "maggiedash"), join(root, "templates", "maggiedash"), force, root, previousManagedFiles);
|
|
575
|
+
if (existsSync(MARKETPLACE_ROOT) && existsSync(join(root, "marketplace"))) updated += syncTree(MARKETPLACE_ROOT, join(root, "marketplace"), force, root, previousManagedFiles, stats);
|
|
576
|
+
if (existsSync(CONTRACTS_ROOT) && existsSync(join(root, "contracts"))) updated += syncTree(CONTRACTS_ROOT, join(root, "contracts"), force, root, previousManagedFiles, stats);
|
|
577
|
+
if (existsSync(join(TEMPLATES_ROOT, "maggiedash")) && existsSync(join(root, "templates", "maggiedash"))) updated += syncTree(join(TEMPLATES_ROOT, "maggiedash"), join(root, "templates", "maggiedash"), force, root, previousManagedFiles, stats);
|
|
563
578
|
}
|
|
564
579
|
const manifestRoots = scope === USER_SCOPE ? allUserAgentRoots() : roots;
|
|
565
580
|
const updatedUserSkills = scope === USER_SCOPE ? mergedUserSkillNames(manifestRoots) : [];
|
|
@@ -567,8 +582,8 @@ function update(args) {
|
|
|
567
582
|
? { scope, version: PACKAGE_VERSION, agents: manifestRoots, skills: updatedUserSkills, skillsByAgent: userSkillInventory(manifestRoots), managedFiles: userManagedFileDigests(manifestRoots, updatedUserSkills, previousManagedFiles), updated_at: new Date().toISOString() }
|
|
568
583
|
: { scope, version: PACKAGE_VERSION, agents: roots.map((item) => item.slice(root.length + 1)), skills: mergedSkillNames(root, skills), managedFiles: managedFileDigests(root, roots, skills, previousManagedFiles), updated_at: new Date().toISOString() };
|
|
569
584
|
writeInstallManifest(root, manifest, scope);
|
|
570
|
-
console.log(`Maggie ${scope} update complete: ${updated} files changed`);
|
|
571
|
-
if (
|
|
585
|
+
console.log(`Maggie ${scope} update complete: ${updated} files changed, ${stats.unchanged} unchanged, ${stats.preserved} preserved`);
|
|
586
|
+
if (stats.preserved) console.log("Local files with changes were preserved. Review the output and rerun with --force only when replacement is intended.");
|
|
572
587
|
}
|
|
573
588
|
|
|
574
589
|
function list() {
|
|
@@ -588,16 +603,17 @@ function marketplace(args) {
|
|
|
588
603
|
|
|
589
604
|
function service(args) {
|
|
590
605
|
const root = projectRoot(args);
|
|
591
|
-
const
|
|
606
|
+
const importCommands = ["import-stages-validate", "import-readiness", "fact-provenance"];
|
|
607
|
+
const scriptName = args[0] === "orchestration-validate" ? "maggie_service_onboarding.py" : importCommands.includes(args[0]) ? "maggie_service_import.py" : "maggie_service_booking.py";
|
|
592
608
|
const script = toolScript(scriptName, root);
|
|
593
609
|
if (!existsSync(script)) throw new Error(`service booking CLI is missing: ${script}`);
|
|
594
|
-
const result = spawnSync("python3", [script, ...args], { stdio: "inherit", cwd: root, env: { ...process.env, MAGGIE_VERSION: PACKAGE_VERSION } });
|
|
610
|
+
const result = spawnSync("python3", [script, ...(scriptName === "maggie_service_onboarding.py" ? args.slice(1) : args)], { stdio: "inherit", cwd: root, env: { ...process.env, MAGGIE_VERSION: PACKAGE_VERSION } });
|
|
595
611
|
if (result.error) throw result.error;
|
|
596
612
|
process.exitCode = result.status ?? 1;
|
|
597
613
|
}
|
|
598
614
|
|
|
599
615
|
function docs(args) {
|
|
600
|
-
if (args[0] && args[0]
|
|
616
|
+
if (args[0] && !["audit", "rollout-status"].includes(args[0])) throw new Error("docs command must be audit or rollout-status");
|
|
601
617
|
workflowCli("maggie_docs.py", args);
|
|
602
618
|
}
|
|
603
619
|
|
|
@@ -767,6 +783,8 @@ try {
|
|
|
767
783
|
else if (command === "ops") workflowCli("maggie_ops.py", args);
|
|
768
784
|
else if (command === "deployment" && args[0] === "canary") workflowCli("maggie_deployment_canary.py", args.slice(1));
|
|
769
785
|
else if (command === "deployment" && args[0] === "readiness") workflowCli("maggie_deployment_readiness.py", args.slice(1));
|
|
786
|
+
else if (command === "deployment" && args[0] === "auth-canary") workflowCli("maggie_deployment_auth_canary.py", args.slice(1));
|
|
787
|
+
else if (command === "deployment" && args[0] === "collect") workflowCli("maggie_deployment_collect.py", args.slice(1));
|
|
770
788
|
else if (command === "deployment" && args[0] === "parity") workflowCli("maggie_deployment_parity.py", args.slice(1));
|
|
771
789
|
else if (command === "deployment" && args[0] === "release-manifest") workflowCli("maggie_release_manifest.py", args.slice(1));
|
|
772
790
|
else if (command === "deployment" && args[0] === "runtime-preflight") workflowCli("maggie_runtime_preflight.py", args.slice(1));
|
|
@@ -36,7 +36,8 @@
|
|
|
36
36
|
"productRole": {"type": "string", "minLength": 1, "maxLength": 200},
|
|
37
37
|
"evidence": {"$ref": "#/$defs/evidence"},
|
|
38
38
|
"capabilities": {"$ref": "#/$defs/capabilities"},
|
|
39
|
-
"nextAction": {"type": "string", "minLength": 1, "maxLength": 500}
|
|
39
|
+
"nextAction": {"type": "string", "minLength": 1, "maxLength": 500},
|
|
40
|
+
"failure": {"description": "Optional redacted provider failure: error code/reason and HTTP status only. The validator maps it to one prerequisite and safe next action and never echoes it.", "type": "object", "additionalProperties": false, "minProperties": 1, "properties": {"code": {"type": "string", "maxLength": 300}, "reason": {"type": "string", "maxLength": 300}, "httpStatus": {"type": "integer", "minimum": 100, "maximum": 599}}}
|
|
40
41
|
}
|
|
41
42
|
},
|
|
42
43
|
"verifiedRef": {
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://maggie.noblox.app/contracts/maggie-content/email-localization-v1.schema.json",
|
|
4
|
+
"title": "Maggie localized email template manifest v1",
|
|
5
|
+
"description": "Template matrix checked by `maggie localization email-matrix`. Structural shape only; the CLI enforces locale precedence, variable preservation, HTML/plain-text parity, market routes, untranslated values and approval.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"required": ["schemaVersion", "sourceLocale", "locales", "templates"],
|
|
8
|
+
"properties": {
|
|
9
|
+
"schemaVersion": {"const": "maggie-email-localization.v1"},
|
|
10
|
+
"sourceLocale": {"type": "string", "minLength": 2},
|
|
11
|
+
"locales": {"type": "array", "items": {"type": "string"}, "minItems": 1, "uniqueItems": true},
|
|
12
|
+
"markets": {
|
|
13
|
+
"type": "object",
|
|
14
|
+
"additionalProperties": {
|
|
15
|
+
"type": "object",
|
|
16
|
+
"properties": {
|
|
17
|
+
"locales": {"type": "array", "items": {"type": "string"}},
|
|
18
|
+
"routePrefix": {"type": "string", "pattern": "^/"}
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
"glossary": {
|
|
23
|
+
"type": "array",
|
|
24
|
+
"items": {
|
|
25
|
+
"type": "object",
|
|
26
|
+
"required": ["term", "locale", "translation"],
|
|
27
|
+
"properties": {"term": {"type": "string"}, "locale": {"type": "string"}, "translation": {"type": "string"}}
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
"templates": {
|
|
31
|
+
"type": "array",
|
|
32
|
+
"minItems": 1,
|
|
33
|
+
"items": {
|
|
34
|
+
"type": "object",
|
|
35
|
+
"required": ["id", "category", "variables", "localeResolution", "locales"],
|
|
36
|
+
"properties": {
|
|
37
|
+
"id": {"type": "string", "minLength": 1},
|
|
38
|
+
"category": {"enum": ["transactional", "support", "marketing"]},
|
|
39
|
+
"variables": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
|
|
40
|
+
"localeResolution": {
|
|
41
|
+
"type": "array",
|
|
42
|
+
"items": {"enum": ["user", "market", "account", "fallback"]},
|
|
43
|
+
"minItems": 1,
|
|
44
|
+
"uniqueItems": true
|
|
45
|
+
},
|
|
46
|
+
"requiredLocales": {"type": "array", "items": {"type": "string"}},
|
|
47
|
+
"cta": {"type": "object", "properties": {"route": {"type": "string"}}},
|
|
48
|
+
"fixtures": {"type": "object", "description": "Synthetic preview values only; never customer data."},
|
|
49
|
+
"locales": {
|
|
50
|
+
"type": "object",
|
|
51
|
+
"additionalProperties": {
|
|
52
|
+
"type": "object",
|
|
53
|
+
"required": ["subject", "html", "text"],
|
|
54
|
+
"properties": {
|
|
55
|
+
"subject": {"type": "string"},
|
|
56
|
+
"html": {"type": "string"},
|
|
57
|
+
"text": {"type": "string"},
|
|
58
|
+
"ctaRoute": {"type": "string"},
|
|
59
|
+
"market": {"type": "string"},
|
|
60
|
+
"approval": {
|
|
61
|
+
"type": "object",
|
|
62
|
+
"properties": {
|
|
63
|
+
"status": {"enum": ["pending", "approved", "rejected"]},
|
|
64
|
+
"reviewer": {"type": "string"},
|
|
65
|
+
"approvedAt": {"type": "string", "format": "date-time"}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
},
|
|
74
|
+
"callSites": {
|
|
75
|
+
"type": "array",
|
|
76
|
+
"description": "Where the host sends each template and how it resolves the locale.",
|
|
77
|
+
"items": {
|
|
78
|
+
"type": "object",
|
|
79
|
+
"required": ["template", "localeSource"],
|
|
80
|
+
"properties": {
|
|
81
|
+
"id": {"type": "string"},
|
|
82
|
+
"template": {"type": "string"},
|
|
83
|
+
"path": {"enum": ["fulfilment", "outbox", "direct", "preview"]},
|
|
84
|
+
"localeSource": {"enum": ["resolved", "user", "market", "account", "fallback", "accept-language", "hard-coded"]}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://maggie.noblox.app/contracts/maggie-content/lifecycle-email-v1.schema.json",
|
|
4
|
+
"title": "Maggie consent-aware lifecycle email plan v1",
|
|
5
|
+
"description": "Plan validated by `maggie localization lifecycle`. Nothing is sendable until approved; the host owns audience data, consent records, delivery and reporting. Maggie never sends.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"required": ["schemaVersion", "stages", "defaults", "templates"],
|
|
8
|
+
"properties": {
|
|
9
|
+
"schemaVersion": {"const": "maggie-lifecycle-email.v1"},
|
|
10
|
+
"stages": {"const": ["plan", "segment", "consent-check", "preview", "approve", "schedule", "send", "report"]},
|
|
11
|
+
"defaults": {"type": "object", "required": ["send"], "properties": {"send": {"const": "disabled"}}},
|
|
12
|
+
"templates": {
|
|
13
|
+
"type": "array",
|
|
14
|
+
"items": {
|
|
15
|
+
"type": "object",
|
|
16
|
+
"required": ["id", "kind", "category", "frequency", "sendable"],
|
|
17
|
+
"properties": {
|
|
18
|
+
"id": {"type": "string", "minLength": 1},
|
|
19
|
+
"kind": {"enum": ["opt-in-confirmation", "welcome", "digest", "recommendation", "gift-follow-up", "voucher-follow-up", "waitlist-follow-up", "merchant-lead-digest", "campaign-announcement", "re-engagement"]},
|
|
20
|
+
"category": {"enum": ["transactional", "support", "marketing"]},
|
|
21
|
+
"consent": {
|
|
22
|
+
"type": "object",
|
|
23
|
+
"properties": {
|
|
24
|
+
"basis": {"enum": ["opt-in", "double-opt-in", "soft-opt-in", "legitimate-interest-b2b"]},
|
|
25
|
+
"category": {"type": "string"}
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
"unsubscribe": {"type": "object", "properties": {"path": {"type": "string"}}},
|
|
29
|
+
"preferenceCentre": {"type": "string"},
|
|
30
|
+
"frequency": {
|
|
31
|
+
"type": "object",
|
|
32
|
+
"required": ["maxPerWindow", "window"],
|
|
33
|
+
"properties": {"maxPerWindow": {"type": "integer", "minimum": 1}, "window": {"type": "string", "description": "ISO 8601 duration, e.g. P7D"}}
|
|
34
|
+
},
|
|
35
|
+
"attribution": {"type": "object", "properties": {"fields": {"type": "array", "items": {"type": "string"}}}},
|
|
36
|
+
"approval": {"$ref": "#/$defs/approval"},
|
|
37
|
+
"sendable": {"type": "boolean"}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
"campaigns": {
|
|
42
|
+
"type": "array",
|
|
43
|
+
"items": {
|
|
44
|
+
"type": "object",
|
|
45
|
+
"required": ["id", "templates", "audience", "sendable"],
|
|
46
|
+
"properties": {
|
|
47
|
+
"id": {"type": "string"},
|
|
48
|
+
"templates": {"type": "array", "items": {"type": "string"}},
|
|
49
|
+
"audience": {
|
|
50
|
+
"type": "object",
|
|
51
|
+
"properties": {
|
|
52
|
+
"segment": {"type": "string"},
|
|
53
|
+
"requiresConsent": {"type": "boolean"},
|
|
54
|
+
"suppression": {"type": "boolean"},
|
|
55
|
+
"dedupe": {"type": "string"}
|
|
56
|
+
}
|
|
57
|
+
},
|
|
58
|
+
"schedule": {"type": "object"},
|
|
59
|
+
"approval": {"$ref": "#/$defs/approval"},
|
|
60
|
+
"sendable": {"type": "boolean"},
|
|
61
|
+
"report": {"type": "object", "properties": {"metrics": {"type": "array", "items": {"type": "string"}}}}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
},
|
|
66
|
+
"$defs": {
|
|
67
|
+
"approval": {
|
|
68
|
+
"type": "object",
|
|
69
|
+
"properties": {
|
|
70
|
+
"status": {"enum": ["pending", "approved", "rejected"]},
|
|
71
|
+
"reviewer": {"type": "string"},
|
|
72
|
+
"approvedAt": {"type": "string", "format": "date-time"}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
"properties": {
|
|
8
8
|
"schemaVersion": {"const": "maggie-deployment-readiness.v1"},
|
|
9
9
|
"status": {"enum": ["passed", "failed", "inconclusive"]},
|
|
10
|
+
"collector": {"type": "object", "description": "present when produced by maggie deployment collect: config fingerprint, release, and per-adapter run metadata"},
|
|
10
11
|
"checks": {
|
|
11
12
|
"type": "object",
|
|
12
13
|
"required": ["unitRegression", "packageSmoke", "browserEvidence", "renderedCanary", "deploymentPreflight"],
|
|
@@ -17,7 +18,11 @@
|
|
|
17
18
|
"browserEvidence": {"$ref": "#/$defs/check"},
|
|
18
19
|
"renderedCanary": {"$ref": "#/$defs/check"},
|
|
19
20
|
"deploymentPreflight": {"$ref": "#/$defs/check"},
|
|
20
|
-
"runtimeParity": {"$ref": "#/$defs/check"}
|
|
21
|
+
"runtimeParity": {"$ref": "#/$defs/check"},
|
|
22
|
+
"hostHealth": {"$ref": "#/$defs/check"},
|
|
23
|
+
"releaseIdentity": {"$ref": "#/$defs/check"},
|
|
24
|
+
"rollbackEvidence": {"$ref": "#/$defs/check"},
|
|
25
|
+
"authenticatedCanary": {"$ref": "#/$defs/check"}
|
|
21
26
|
}
|
|
22
27
|
}
|
|
23
28
|
},
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://maggie.topy.ai/contracts/maggie-ops/marketing-run-v1.schema.json",
|
|
4
|
+
"title": "Maggie marketing run",
|
|
5
|
+
"description": "One project-scoped run joining content, Social Share, Ads, and measurement. References evidence, approvals, mutations and readbacks by ID; never contains secrets or provider payloads. Validated by tools/clis/maggie_marketing_run.py, which also enforces cross-field rules (approval before external mutation, readback for succeeded mutations, regulated-content review gating only external publication, no secret fields).",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"required": ["schemaVersion", "runId", "projectRef", "objective", "conversion", "channels", "timezone", "mode", "approval", "scheduleLayers"],
|
|
8
|
+
"not": {"anyOf": [{"required": ["scheduled_at"]}, {"required": ["scheduledAt"]}]},
|
|
9
|
+
"properties": {
|
|
10
|
+
"schemaVersion": {"const": "maggie-marketing-run-v1"},
|
|
11
|
+
"runId": {"type": "string", "pattern": "^[a-z0-9][a-z0-9._-]{2,127}$"},
|
|
12
|
+
"projectRef": {"type": "string", "minLength": 1},
|
|
13
|
+
"objective": {"type": "string", "minLength": 1},
|
|
14
|
+
"conversion": {
|
|
15
|
+
"type": "object",
|
|
16
|
+
"required": ["event", "source"],
|
|
17
|
+
"properties": {"event": {"type": "string"}, "source": {"type": "string"}}
|
|
18
|
+
},
|
|
19
|
+
"channels": {"type": "array", "minItems": 1, "items": {"type": "string", "minLength": 1}},
|
|
20
|
+
"timezone": {"type": "string", "description": "IANA time zone for the run."},
|
|
21
|
+
"mode": {"enum": ["draft", "scheduled", "executing", "completed", "cancelled"]},
|
|
22
|
+
"sourceRevisions": {
|
|
23
|
+
"type": "array",
|
|
24
|
+
"items": {"type": "object", "required": ["sourceId", "revision"], "properties": {"sourceId": {"type": "string"}, "revision": {"type": "string"}}}
|
|
25
|
+
},
|
|
26
|
+
"capabilityEvidence": {"type": "array", "items": {"type": "string", "minLength": 1}},
|
|
27
|
+
"approval": {
|
|
28
|
+
"type": "object",
|
|
29
|
+
"required": ["state"],
|
|
30
|
+
"properties": {
|
|
31
|
+
"state": {"enum": ["pending", "approved", "rejected", "not_required"]},
|
|
32
|
+
"actor": {"type": ["string", "null"]},
|
|
33
|
+
"approvalId": {"type": ["string", "null"]}
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
"scheduleLayers": {"type": "array", "minItems": 1, "items": {"$ref": "#/$defs/scheduleLayer"}},
|
|
37
|
+
"mutations": {"type": "array", "items": {"$ref": "#/$defs/mutation"}},
|
|
38
|
+
"readbacks": {
|
|
39
|
+
"type": "array",
|
|
40
|
+
"items": {"type": "object", "required": ["readbackId"], "properties": {"readbackId": {"type": "string"}, "mutationRef": {"type": "string"}, "evidenceRef": {"type": "string"}}}
|
|
41
|
+
},
|
|
42
|
+
"policy": {
|
|
43
|
+
"type": "object",
|
|
44
|
+
"description": "Regulated-content review. Default off. When on, only external publication waits for an approved review; delivery, drafts, SEO/GEO and measurement continue.",
|
|
45
|
+
"properties": {
|
|
46
|
+
"regulatedContent": {"type": "boolean", "default": false},
|
|
47
|
+
"reviewRequired": {"type": "boolean", "default": true},
|
|
48
|
+
"reviewState": {"enum": ["not_required", "pending", "approved", "rejected"]},
|
|
49
|
+
"reviewerRef": {"type": "string"}
|
|
50
|
+
}
|
|
51
|
+
},
|
|
52
|
+
"stages": {
|
|
53
|
+
"type": "object",
|
|
54
|
+
"propertyNames": {"enum": ["delivery", "draft", "seo_geo", "measurement", "external_publication"]},
|
|
55
|
+
"additionalProperties": {"type": "object", "properties": {"status": {"type": "string"}, "reason": {"type": "string"}}}
|
|
56
|
+
},
|
|
57
|
+
"measurement": {"type": "object"}
|
|
58
|
+
},
|
|
59
|
+
"$defs": {
|
|
60
|
+
"scheduleLayer": {
|
|
61
|
+
"type": "object",
|
|
62
|
+
"required": ["layer", "timezone", "owner", "status", "reconciliation"],
|
|
63
|
+
"properties": {
|
|
64
|
+
"layer": {"enum": ["infrastructure", "content_calendar", "campaign_flight", "measurement_window"]},
|
|
65
|
+
"id": {"type": "string"},
|
|
66
|
+
"timezone": {"type": "string"},
|
|
67
|
+
"owner": {"type": "string", "minLength": 1},
|
|
68
|
+
"status": {"enum": ["planned", "active", "paused", "completed", "cancelled"]},
|
|
69
|
+
"start": {"type": "string"},
|
|
70
|
+
"end": {"type": "string"},
|
|
71
|
+
"lagDays": {"type": "integer", "minimum": 0},
|
|
72
|
+
"scheduleRef": {"type": "string", "description": "infrastructure only: the maggie-schedule job name."},
|
|
73
|
+
"reconciliation": {"type": "string", "minLength": 1, "description": "How this layer's actual state is read back and reconciled."}
|
|
74
|
+
}
|
|
75
|
+
},
|
|
76
|
+
"mutation": {
|
|
77
|
+
"type": "object",
|
|
78
|
+
"required": ["mutationId", "kind", "status"],
|
|
79
|
+
"properties": {
|
|
80
|
+
"mutationId": {"type": "string"},
|
|
81
|
+
"kind": {"enum": ["external_publication", "ads_change", "content_delivery", "draft_creation", "configuration"]},
|
|
82
|
+
"channel": {"type": "string"},
|
|
83
|
+
"status": {"enum": ["planned", "pending", "succeeded", "failed", "cancelled"]},
|
|
84
|
+
"idempotencyKey": {"type": "string"},
|
|
85
|
+
"approvalRef": {"type": "string"}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|