@topy-ai/maggie 0.6.4 → 0.6.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -157,8 +157,8 @@ only and never stores response bodies, cookies, or credentials.
157
157
  Recommended upgrade sequence for the current release:
158
158
 
159
159
  ```bash
160
- npx @topy-ai/maggie@0.6.4 update --project . --force
161
- npx @topy-ai/maggie@0.6.4 cleanup --project .
160
+ npx @topy-ai/maggie@0.6.6 update --project . --force
161
+ npx @topy-ai/maggie@0.6.6 cleanup --project .
162
162
  ```
163
163
 
164
164
  ## MaggieDash lifecycle
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.6.4 init --agent all
11
+ npx @topy-ai/maggie@0.6.6 init --agent all
12
12
  npx @topy-ai/maggie doctor --project .
13
13
  ```
14
14
 
@@ -2,11 +2,17 @@
2
2
  name: maggie-content-localization
3
3
  description: Manage translation, polish, rewrite, market localization, review, stale detection, and publishing for pages, guides, posts, services, products, and categories.
4
4
  metadata:
5
- version: 1.0.0
5
+ version: 1.1.0
6
6
  ---
7
7
 
8
8
  # Maggie Content Localization
9
9
 
10
+ Localization job filenames are derived from content identity, but content IDs
11
+ are data, not paths. The CLI sanitizes separators and adds a short identity
12
+ hash when needed, so IDs such as `site.example/static-pages` always produce a
13
+ single addressable file under `.maggie/localization/`. Never construct a job
14
+ path by interpolating an unsanitized content ID.
15
+
10
16
  Use the shared [Content Localization Contract](../../references/content-localization-contract.md).
11
17
  Use the shared [memory hook](../../references/memory-hook.md) to read prior
12
18
  locale preferences and record confirmed terminology or translation failures.
@@ -53,3 +59,9 @@ Never change price, currency, rating, provider facts, booking URLs, legal or
53
59
  health claims, slug, canonical ownership, or content identity during a copy
54
60
  operation without structured approval. Incomplete or fallback output must be
55
61
  `isIndexable: false`. High-risk content requires Admin approval before publish.
62
+
63
+ The current validator checks the localization record. It does not yet extract
64
+ strings from a host project or prove browser-rendered language output. That
65
+ larger capability is specified in
66
+ [`docs/localization-extraction-render-prd.md`](../../docs/localization-extraction-render-prd.md)
67
+ and remains a separate release-gated feature.
@@ -4,7 +4,9 @@
4
4
  from __future__ import annotations
5
5
 
6
6
  import argparse
7
+ import hashlib
7
8
  import json
9
+ import re
8
10
  import sys
9
11
  from datetime import datetime, timezone
10
12
  from pathlib import Path
@@ -24,6 +26,14 @@ def load(path: Path) -> dict:
24
26
  return value
25
27
 
26
28
 
29
+ def safe_job_content_token(content_id: str) -> str:
30
+ """Make a content identity safe for a single filename component."""
31
+ token = re.sub(r"[^A-Za-z0-9._-]+", "-", str(content_id)).strip(".-_") or "content"
32
+ if token != content_id:
33
+ token = f"{token}-{hashlib.sha256(str(content_id).encode('utf-8')).hexdigest()[:8]}"
34
+ return token[:180]
35
+
36
+
27
37
  def plan_job(args: argparse.Namespace) -> int:
28
38
  content = load(args.content)
29
39
  if args.source_lang not in LANGUAGES or args.target_lang not in LANGUAGES:
@@ -39,7 +49,7 @@ def plan_job(args: argparse.Namespace) -> int:
39
49
  if not content_id:
40
50
  raise ValueError("contentId is required in content identity")
41
51
  job = {
42
- "jobId": f"localize-{content_id}-{args.target_lang.lower()}-{datetime.now(timezone.utc).strftime('%Y%m%d%H%M%S')}",
52
+ "jobId": f"localize-{safe_job_content_token(content_id)}-{args.target_lang.lower()}-{datetime.now(timezone.utc).strftime('%Y%m%d%H%M%S')}",
43
53
  "content": content,
44
54
  "contentId": content_id,
45
55
  "contentType": identity.get("contentType", "page"),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@topy-ai/maggie",
3
- "version": "0.6.4",
3
+ "version": "0.6.6",
4
4
  "description": "Install and manage Maggie Skills for AI coding agents",
5
5
  "license": "MIT",
6
6
  "type": "module",