@topy-ai/maggie 0.7.41 → 0.7.42

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
@@ -8,11 +8,14 @@ Codex、Claude Code 與相容的 coding agents。
8
8
  ## 安裝
9
9
 
10
10
  ```bash
11
- npx @topy-ai/maggie@0.7.41 init --agent all
12
- npx @topy-ai/maggie@0.7.41 doctor --project .
11
+ npx @topy-ai/maggie@0.7.42 init --agent all
12
+ npx @topy-ai/maggie@0.7.42 doctor --project .
13
13
  ```
14
14
 
15
- 目前 release 是 `0.7.41`,完成 feedback batches 22、23:加入 declarative
15
+ 目前 release 是 `0.7.42`。新增 redacted Gemini video-provider evidence gate,
16
+ 驗證 provider acknowledgement、idempotency、moderation、object-storage
17
+ readback、bounded retry 與 git provenance,並拒絕 raw provider payload 或
18
+ input asset 欄位。0.7.41 完成 feedback batches 22、23:加入 declarative
16
19
  browser interaction evidence、design markup/style/content-key gate、compiler
17
20
  source anchoring、entity double-escape protection、`update --help` read-only,
18
21
  以及 noindex hypothetical indexability、可過期 baseline acknowledgement、
@@ -41,6 +44,8 @@ maggie provenance --project . --source src/content/post.md
41
44
  maggie scaffold --project . --framework astro --language typescript --write --confirm
42
45
  maggie brand-kit --project . --design DESIGN.md --write --confirm
43
46
  maggie npm11 --project . --smoke --confirm
47
+ maggie media video-provider-evidence --evidence .maggie/video-provider-evidence.json \
48
+ --environment staging --model gemini-omni-1.1-flash --require-host
44
49
  maggie media video-playback --evidence .maggie/video-playback-evidence.json
45
50
  maggie booking-delivery --policy .maggie/booking-delivery-policy.json
46
51
  ```
package/README.md CHANGED
@@ -60,7 +60,11 @@ 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 20 installable skills and a local-first MaggieDash foundation.
62
62
 
63
- The current release is `0.7.41`. It closes feedback batches 22 and 23 with
63
+ The current release is `0.7.42`. It adds a redacted Gemini video-provider
64
+ evidence gate for provider acknowledgement, idempotency, moderation,
65
+ object-storage readback, bounded retry, and git provenance; unknown raw
66
+ provider payload and input-asset fields fail validation. The 0.7.41 release
67
+ closes feedback batches 22 and 23 with
64
68
  declarative browser interaction evidence, stable design markup/style/content-key
65
69
  gates, compiler source anchoring, entity double-escape protection, and a
66
70
  read-only `update --help` path. It also adds hypothetical indexability
@@ -86,6 +90,8 @@ maggie provenance --project . --source src/content/post.md
86
90
  maggie scaffold --project . --framework astro --language typescript --write --confirm
87
91
  maggie brand-kit --project . --design DESIGN.md --write --confirm
88
92
  maggie npm11 --project . --smoke --confirm
93
+ maggie media video-provider-evidence --evidence .maggie/video-provider-evidence.json \
94
+ --environment staging --model gemini-omni-1.1-flash --require-host
89
95
  maggie media video-playback --evidence .maggie/video-playback-evidence.json
90
96
  maggie booking-delivery --policy .maggie/booking-delivery-policy.json
91
97
  ```
package/bin/maggie.js CHANGED
@@ -135,7 +135,7 @@ Usage:
135
135
  maggie schedule PATH/.maggie/schedule.json --project PATH
136
136
  maggie analytics [traffic-audit|release-gate] --project PATH --environment staging
137
137
  maggie analytics gsc-readiness --gsc-evidence FILE
138
- maggie media [image-policy|video-policy|video-job|video-playback] [--policy/--job/--evidence FILE]
138
+ maggie media [image-policy|video-policy|video-job|video-provider-evidence|video-playback] [--policy/--job/--evidence FILE]
139
139
  maggie provenance --project PATH [--source PATH] [--output FILE]
140
140
  maggie scaffold --project PATH --framework astro|nextjs|sveltekit|nuxt|vite-react|vite-vue [--write --confirm]
141
141
  maggie brand-kit --manifest FILE | --project PATH --design DESIGN.md [--write --confirm]
@@ -0,0 +1,25 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://maggie.noblox.app/contracts/maggie-media/video-provider-evidence-v1.schema.json",
4
+ "title": "Maggie video provider canary evidence v1",
5
+ "type": "object",
6
+ "required": ["schemaVersion", "environment", "provider", "model", "status", "hostVerified", "acknowledgement", "idempotency", "moderation", "storage", "retry", "rawProviderPayloadIncluded", "inputAssetDataIncluded", "sourceRevision"],
7
+ "properties": {
8
+ "schemaVersion": {"const": "maggie-video-provider-evidence.v1"},
9
+ "environment": {"enum": ["test", "staging", "production"]},
10
+ "provider": {"const": "google-gemini"},
11
+ "model": {"type": "string", "pattern": "^(gemini|veo)-"},
12
+ "status": {"const": "passed"},
13
+ "hostVerified": {"const": true},
14
+ "acknowledgement": {"type": "object", "required": ["accepted", "providerReferencePresent"], "properties": {"accepted": {"const": true}, "providerReferencePresent": {"const": true}}, "additionalProperties": false},
15
+ "idempotency": {"type": "object", "required": ["replayAccepted", "duplicateChargePrevented", "assetDeduplicated"], "properties": {"replayAccepted": {"const": true}, "duplicateChargePrevented": {"const": true}, "assetDeduplicated": {"const": true}}, "additionalProperties": false},
16
+ "moderation": {"type": "object", "required": ["preflightPassed", "postGenerationReviewPassed"], "properties": {"preflightPassed": {"const": true}, "postGenerationReviewPassed": {"const": true}}, "additionalProperties": false},
17
+ "storage": {"type": "object", "required": ["uploadAccepted", "metadataPersisted", "readbackPassed", "signedOrApprovedUrlPresent"], "properties": {"uploadAccepted": {"const": true}, "metadataPersisted": {"const": true}, "readbackPassed": {"const": true}, "signedOrApprovedUrlPresent": {"const": true}}, "additionalProperties": false},
18
+ "retry": {"type": "object", "required": ["transientFailureObserved", "bounded", "attempts"], "properties": {"transientFailureObserved": {"const": true}, "bounded": {"const": true}, "attempts": {"type": "integer", "minimum": 1, "maximum": 3}}, "additionalProperties": false},
19
+ "rawProviderPayloadIncluded": {"const": false},
20
+ "inputAssetDataIncluded": {"const": false},
21
+ "sourceRevision": {"type": "object", "required": ["commit", "branch", "dirty"], "properties": {"commit": {"type": "string"}, "branch": {"type": "string"}, "dirty": {"type": "boolean"}}, "additionalProperties": false},
22
+ "generatedAt": {"type": "string"}
23
+ },
24
+ "additionalProperties": false
25
+ }
@@ -104,6 +104,57 @@ def validate_video_job(args: argparse.Namespace) -> int:
104
104
  return emit({"schemaVersion": "maggie-video-job.v1", "passed": not errors, "jobId": job.get("jobId"), "state": state, "errors": errors, "rawProviderPayloadIncluded": False}, args.output)
105
105
 
106
106
 
107
+ def validate_video_provider_evidence(args: argparse.Namespace) -> int:
108
+ evidence = load(Path(args.evidence).expanduser().resolve())
109
+ errors: list[str] = []
110
+ allowed = {
111
+ "schemaVersion", "environment", "provider", "model", "status", "hostVerified",
112
+ "acknowledgement", "idempotency", "moderation", "storage", "retry",
113
+ "rawProviderPayloadIncluded", "inputAssetDataIncluded", "sourceRevision", "generatedAt",
114
+ }
115
+ for key in evidence:
116
+ if key not in allowed:
117
+ errors.append(f"evidence.{key} is not allowed")
118
+ nested_allowed = {
119
+ "acknowledgement": {"accepted", "providerReferencePresent"},
120
+ "idempotency": {"replayAccepted", "duplicateChargePrevented", "assetDeduplicated"},
121
+ "moderation": {"preflightPassed", "postGenerationReviewPassed"},
122
+ "storage": {"uploadAccepted", "metadataPersisted", "readbackPassed", "signedOrApprovedUrlPresent"},
123
+ "retry": {"transientFailureObserved", "bounded", "attempts"},
124
+ "sourceRevision": {"commit", "branch", "dirty"},
125
+ }
126
+ for parent, keys in nested_allowed.items():
127
+ value = evidence.get(parent)
128
+ if isinstance(value, dict):
129
+ for key in value:
130
+ if key not in keys:
131
+ errors.append(f"{parent}.{key} is not allowed")
132
+ if evidence.get("schemaVersion") != "maggie-video-provider-evidence.v1": errors.append("schemaVersion must be maggie-video-provider-evidence.v1")
133
+ if evidence.get("environment") not in {"test", "staging", "production"}: errors.append("environment is unsupported")
134
+ if evidence.get("provider") != "google-gemini": errors.append("provider must be google-gemini")
135
+ if not str(evidence.get("model", "")).startswith(("gemini-", "veo-")): errors.append("model must be a Gemini or Veo model id")
136
+ if evidence.get("status") != "passed": errors.append("status must be passed")
137
+ if args.require_host and evidence.get("hostVerified") is not True: errors.append("hostVerified must be true")
138
+ acknowledgement = evidence.get("acknowledgement") if isinstance(evidence.get("acknowledgement"), dict) else {}
139
+ if acknowledgement.get("accepted") is not True or acknowledgement.get("providerReferencePresent") is not True: errors.append("provider acknowledgement is incomplete")
140
+ idempotency = evidence.get("idempotency") if isinstance(evidence.get("idempotency"), dict) else {}
141
+ if any(idempotency.get(key) is not True for key in ("replayAccepted", "duplicateChargePrevented", "assetDeduplicated")): errors.append("video idempotency evidence is incomplete")
142
+ moderation = evidence.get("moderation") if isinstance(evidence.get("moderation"), dict) else {}
143
+ if moderation.get("preflightPassed") is not True or moderation.get("postGenerationReviewPassed") is not True: errors.append("moderation evidence is incomplete")
144
+ storage = evidence.get("storage") if isinstance(evidence.get("storage"), dict) else {}
145
+ if any(storage.get(key) is not True for key in ("uploadAccepted", "metadataPersisted", "readbackPassed", "signedOrApprovedUrlPresent")): errors.append("storage readback evidence is incomplete")
146
+ retry = evidence.get("retry") if isinstance(evidence.get("retry"), dict) else {}
147
+ attempts = retry.get("attempts")
148
+ if retry.get("transientFailureObserved") is not True or retry.get("bounded") is not True or not isinstance(attempts, int) or attempts < 1 or attempts > 3: errors.append("retry evidence is incomplete")
149
+ if evidence.get("rawProviderPayloadIncluded") is not False: errors.append("raw provider payloads must be excluded")
150
+ if evidence.get("inputAssetDataIncluded") is not False: errors.append("input asset data must be excluded")
151
+ source = evidence.get("sourceRevision") if isinstance(evidence.get("sourceRevision"), dict) else {}
152
+ if not isinstance(source.get("commit"), str) or not isinstance(source.get("branch"), str) or not isinstance(source.get("dirty"), bool): errors.append("sourceRevision is incomplete")
153
+ if args.environment and evidence.get("environment") != args.environment: errors.append("environment does not match workflow input")
154
+ if args.model and evidence.get("model") != args.model: errors.append("model does not match workflow input")
155
+ return emit({"schemaVersion": "maggie-video-provider-evidence.v1", "passed": not errors, "environment": evidence.get("environment"), "provider": evidence.get("provider"), "model": evidence.get("model"), "errors": errors, "rawProviderPayloadIncluded": False, "redacted": True}, args.output)
156
+
157
+
107
158
  def git_value(project: Path, *args: str) -> str:
108
159
  result = subprocess.run(["git", "-C", str(project), *args], capture_output=True, text=True, check=False)
109
160
  if result.returncode:
@@ -369,6 +420,7 @@ def main() -> int:
369
420
  for kind, relative in (("image", "maggie-media/image-generation-policy-v1.json"), ("video", "maggie-media/video-generation-policy-v1.json")):
370
421
  command = media_sub.add_parser(f"{kind}-policy"); command.add_argument("--policy", default=str(contract_root() / relative)); command.add_argument("--output"); command.set_defaults(func=validate_media, kind=kind)
371
422
  job = media_sub.add_parser("video-job"); job.add_argument("--job", required=True); job.add_argument("--output"); job.set_defaults(func=validate_video_job)
423
+ video_provider = media_sub.add_parser("video-provider-evidence"); video_provider.add_argument("--evidence", required=True); video_provider.add_argument("--environment", choices=["test", "staging", "production"]); video_provider.add_argument("--model"); video_provider.add_argument("--require-host", action="store_true"); video_provider.add_argument("--output"); video_provider.set_defaults(func=validate_video_provider_evidence)
372
424
  provenance = sub.add_parser("provenance"); provenance.add_argument("--project", default="."); provenance.add_argument("--source"); provenance.add_argument("--boundary", choices=["git-source", "host-runtime", "generated-artifact"], default="git-source"); provenance.add_argument("--output"); provenance.set_defaults(func=capture_provenance)
373
425
  scaffold_parser = sub.add_parser("scaffold"); scaffold_parser.add_argument("--project", default="."); scaffold_parser.add_argument("--framework", choices=sorted(FRAMEWORK_PACKAGES), required=True); scaffold_parser.add_argument("--language", choices=["typescript", "javascript"], default="typescript"); scaffold_parser.add_argument("--package-manager", choices=["npm", "pnpm", "yarn", "bun"], default="npm"); scaffold_parser.add_argument("--install-dependencies", action="store_true"); scaffold_parser.add_argument("--write", action="store_true"); scaffold_parser.add_argument("--confirm", action="store_true"); scaffold_parser.add_argument("--force", action="store_true"); scaffold_parser.add_argument("--output"); scaffold_parser.set_defaults(func=scaffold)
374
426
  brand = sub.add_parser("brand-kit"); brand.add_argument("--manifest"); brand.add_argument("--project", default="."); brand.add_argument("--design"); brand.add_argument("--tokens"); brand.add_argument("--logo"); brand.add_argument("--font"); brand.add_argument("--icon-library", default="host-icon-library"); brand.add_argument("--assets"); brand.add_argument("--write", action="store_true"); brand.add_argument("--confirm", action="store_true"); brand.add_argument("--output"); brand.set_defaults(func=lambda args: validate_brand(args) if args.manifest else brand_kit(args))
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@topy-ai/maggie",
3
- "version": "0.7.41",
3
+ "version": "0.7.42",
4
4
  "description": "Install and manage Maggie Skills for AI coding agents",
5
5
  "license": "MIT",
6
6
  "type": "module",