@odla-ai/brand 0.8.4 → 0.8.5

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
@@ -35,6 +35,14 @@ The package is a **schema + rules + an agent skill + a color engine + a token co
35
35
  accepted/rejected decision across pending requests and retries. Proposal
36
36
  author names must come from a Registry-owned principal projection; mutable
37
37
  chat participants and raw ids are not identity presentation.
38
+ - **Activation is the promotion checkpoint.** After palette and typography
39
+ approvals, `GET /books/:id/activate` returns the exact promotable revision a
40
+ human is reviewing. Posting that snapshot back with one stable mutation id
41
+ consumes a direct-human exact `brand.approve` external action, persists an
42
+ immutable `brand_activation_receipt`, and atomically marks only that revision
43
+ `active`. `exportBrandPromotion` refuses drafts and active rows without this
44
+ activation provenance. Any later accepted proposal returns the book to
45
+ `draft`, so the changed payload needs a new explicit activation.
38
46
  - **Vision happens through a semantic bridge.** `view_asset` asks the trusted
39
47
  host for bytes by asset id and returns image/PDF blocks inside the tool
40
48
  result when the model supports them. The rules-scoped agent credential
@@ -153,6 +161,22 @@ await fetch(`/api/brand/books/${book.id}/proposals/${proposal.id}/resolve`, {
153
161
  });
154
162
  ```
155
163
 
164
+ Activate the resulting approved palette and typography revision before
165
+ promotion. The POST must return exactly the snapshot rendered by the review UI:
166
+
167
+ ```ts
168
+ const review = await fetch(`/api/brand/books/${book.id}/activate`).then((r) => r.json());
169
+ const activated = await fetch(`/api/brand/books/${book.id}/activate`, {
170
+ method: "POST",
171
+ headers: { "content-type": "application/json" },
172
+ body: JSON.stringify({
173
+ mutationId: crypto.randomUUID(),
174
+ reviewedBook: review.reviewedBook,
175
+ }),
176
+ }).then((r) => r.json());
177
+ // activated.promotion is the adapter output; promotionDigest binds it exactly.
178
+ ```
179
+
156
180
  Wire the agent by attaching `brandSkill` to a persona (or let the chat-agent worker route a `brandBotTrigger` dispatch into `dispatchBrandTurn`):
157
181
 
158
182
  ```ts
@@ -5,6 +5,7 @@ declare const BRAND_NS: {
5
5
  readonly palette: "brand_palette";
6
6
  readonly proposal: "brand_proposal";
7
7
  readonly approvalReceipt: "brand_approval_receipt";
8
+ readonly activationReceipt: "brand_activation_receipt";
8
9
  readonly asset: "brand_asset";
9
10
  };
10
11
  /** Brand-book lifecycle: authored → adopted → retired (delete is owner-only). */
@@ -5,6 +5,7 @@ declare const BRAND_NS: {
5
5
  readonly palette: "brand_palette";
6
6
  readonly proposal: "brand_proposal";
7
7
  readonly approvalReceipt: "brand_approval_receipt";
8
+ readonly activationReceipt: "brand_activation_receipt";
8
9
  readonly asset: "brand_asset";
9
10
  };
10
11
  /** Brand-book lifecycle: authored → adopted → retired (delete is owner-only). */