@topy-ai/maggie 0.7.49 → 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 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.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
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.49`,包含 batch 26、27 feedback 修正與 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
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,7 +89,13 @@ 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.49`. It closes batch 27: 33 local feedback
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
93
99
  drafts from 2026-09-09 to 09-16 that were never submitted, reconciled against
94
100
  the current code (two were already satisfied):
95
101
 
@@ -728,8 +734,8 @@ artifact schemas.
728
734
  Recommended upgrade sequence for the current release:
729
735
 
730
736
  ```bash
731
- npx @topy-ai/maggie@0.7.49 update --scope project --project . --force
732
- npx @topy-ai/maggie@0.7.49 cleanup --scope project --project .
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 .
733
739
  ```
734
740
 
735
741
  Maintainers should pass npm credentials through the repository helper, never
package/bin/maggie.js CHANGED
@@ -388,13 +388,13 @@ function diffSummary(source, target) {
388
388
  return `${added} local additions, ${removed} package lines removed across ${blocks} changed blocks (${localLines.length} local lines vs ${packageLines.length} package lines)`;
389
389
  }
390
390
 
391
- function syncTree(source, target, force, root = null, managedFiles = {}) {
391
+ function syncTree(source, target, force, root = null, managedFiles = {}, stats = { unchanged: 0, preserved: 0 }) {
392
392
  let changed = 0;
393
393
  for (const entry of readdirSync(source, { withFileTypes: true })) {
394
394
  const sourcePath = join(source, entry.name);
395
395
  const targetPath = join(target, entry.name);
396
396
  if (entry.isDirectory()) {
397
- changed += syncTree(sourcePath, targetPath, force, root, managedFiles);
397
+ changed += syncTree(sourcePath, targetPath, force, root, managedFiles, stats);
398
398
  continue;
399
399
  }
400
400
  const managedPath = root ? relative(root, targetPath) : targetPath;
@@ -406,12 +406,16 @@ function syncTree(source, target, force, root = null, managedFiles = {}) {
406
406
  writeFileSync(targetPath, readFileSync(sourcePath));
407
407
  console.log(`installed ${targetPath}`);
408
408
  changed++;
409
- } else if (force || packageDigest === localDigest || wasManaged) {
409
+ } else if (packageDigest === localDigest) {
410
+ // Identical content: leave the file and its timestamps untouched.
411
+ stats.unchanged++;
412
+ } else if (force || wasManaged) {
410
413
  writeFileSync(targetPath, readFileSync(sourcePath));
411
414
  console.log(`updated ${targetPath}`);
412
415
  changed++;
413
416
  } else {
414
417
  console.log(`preserved ${targetPath} (local changes; ${diffSummary(sourcePath, targetPath)}; use --force to replace)`);
418
+ stats.preserved++;
415
419
  }
416
420
  }
417
421
  return changed;
@@ -545,6 +549,7 @@ function update(args) {
545
549
  const previousManagedFiles = previousManifest.managedFiles && typeof previousManifest.managedFiles === "object" ? previousManifest.managedFiles : {};
546
550
  if (!existsSync(SKILLS_ROOT)) throw new Error("bundled skills are missing; run npm pack from the package source");
547
551
  let updated = 0;
552
+ const stats = { unchanged: 0, preserved: 0 };
548
553
  const managedRoot = scope === USER_SCOPE ? "/" : root;
549
554
  for (const agentRoot of roots) {
550
555
  for (const skill of skills) {
@@ -554,22 +559,22 @@ function update(args) {
554
559
  console.log(`absent ${target} (run install to add it)`);
555
560
  continue;
556
561
  }
557
- updated += syncTree(source, target, force, managedRoot, previousManagedFiles);
562
+ updated += syncTree(source, target, force, managedRoot, previousManagedFiles, stats);
558
563
  }
559
- 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);
560
565
  }
561
566
  if (scope === PROJECT_SCOPE) {
562
567
  const tools = join(root, "tools");
563
568
  if (existsSync(TOOLS_ROOT)) for (const group of ["clis", "runtime", "integrations"]) if (existsSync(join(TOOLS_ROOT, group))) {
564
569
  const target = join(tools, group);
565
- 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);
566
571
  }
567
572
  if (existsSync(join(DESIGN_ROOT, "SPA-DESIGN.md")) && existsSync(join(root, ".maggie", "design-reference"))) {
568
- 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);
569
574
  }
570
- if (existsSync(MARKETPLACE_ROOT) && existsSync(join(root, "marketplace"))) updated += syncTree(MARKETPLACE_ROOT, join(root, "marketplace"), force, root, previousManagedFiles);
571
- if (existsSync(CONTRACTS_ROOT) && existsSync(join(root, "contracts"))) updated += syncTree(CONTRACTS_ROOT, join(root, "contracts"), force, root, previousManagedFiles);
572
- 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);
573
578
  }
574
579
  const manifestRoots = scope === USER_SCOPE ? allUserAgentRoots() : roots;
575
580
  const updatedUserSkills = scope === USER_SCOPE ? mergedUserSkillNames(manifestRoots) : [];
@@ -577,8 +582,8 @@ function update(args) {
577
582
  ? { scope, version: PACKAGE_VERSION, agents: manifestRoots, skills: updatedUserSkills, skillsByAgent: userSkillInventory(manifestRoots), managedFiles: userManagedFileDigests(manifestRoots, updatedUserSkills, previousManagedFiles), updated_at: new Date().toISOString() }
578
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() };
579
584
  writeInstallManifest(root, manifest, scope);
580
- console.log(`Maggie ${scope} update complete: ${updated} files changed`);
581
- if (!force) console.log("Local files with changes were preserved. Review the output and rerun with --force only when replacement is intended.");
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.");
582
587
  }
583
588
 
584
589
  function list() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@topy-ai/maggie",
3
- "version": "0.7.49",
3
+ "version": "0.7.50",
4
4
  "description": "Install and manage Maggie Skills for AI coding agents",
5
5
  "license": "MIT",
6
6
  "type": "module",