Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# Changelog

## Unreleased

- Publish exact Threads text through `posts.publish@5` without requiring a
PNG, while preserving optional PNG publication and exact permalink readback.

## 0.13.1 - 2026-08-23

- Keep Beeper account selector aliases internal while returning plain,
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@
"src/assets/adapters/threads/wrench-web-adapter.v1.3.0.json",
"src/assets/adapters/threads/wrench-web-adapter.v1.4.0.json",
"src/assets/adapters/threads/wrench-web-adapter.v1.5.0.json",
"src/assets/adapters/threads/wrench-web-adapter.v1.6.0.json",
"src/assets/adapters/tiktok/wrench-web-adapter.json",
"src/assets/adapters/tiktok/wrench-web-adapter.v1.0.0.json",
"src/assets/adapters/whatsapp/wrench-web-adapter.json",
Expand Down
2 changes: 1 addition & 1 deletion skills/wrench/references/platform-patterns.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ template.
- Treat Instagram, Threads, Facebook Page, Facebook Group, and Facebook Marketplace as separate surfaces and auth/account bindings even when Meta shares infrastructure.
- Live-proven direct R1 coverage currently includes Instagram feed/post/media/comment/inbox summaries, the Threads feed, Facebook's bounded initial personal home-feed bootstrap, one exact Group's bounded first feed page, the Marketplace browse feed with cursor continuation, and one exact Marketplace listing. Every result is exact-current-user bound; Group and Marketplace reads additionally bind their exact numeric targets.
- The personal Facebook home result makes no completion or pagination claim. The Group reader assembles only the complete first streamed page and never exposes its provider cursor because the matching continuation query is not yet reviewed. Marketplace reads use a direct inert HTML bootstrap, resolve the current registered Relay revision from bounded canonical first-party bundles without executing them, and assemble each complete streamed page before returning a locally authenticated, account/descriptor/target/chain-bound cursor envelope. A locally truncated projection returns no cursor so it cannot skip unreturned listings. Exact listing reads use the inert bootstrap so the browser-only item-seen mutation is never executed.
- Threads has two separate observed Meta writes. `posts.publish@4` requires exactly one plan-bound PNG, while `media.publish@1` requires exactly one bounded ISO BMFF MP4 with one video track. Each binds the completed upload dimensions and exact created locator into durable target evidence, then verifies the exact permalink actor, text, media identity, dimensions, and media type before success. Instagram `media.publish@1` remains a capture-required reservation and admits only named image/video MIME types instead of wildcards. Facebook personal Messenger listing is capture-required: the current route and folder queries, paging and completeness, and acknowledgement/presence behavior are not proven. Every other Meta write, all message reads/sends, every Facebook Page operation, and all Group operations except the exact first-page feed read remain capture-required. Marketplace messaging and mutations remain capture-required; its observed feed/listing reads do not confer publishing, seller, conversation, or purchase authority.
- Threads has two separate observed Meta writes. `posts.publish@5` publishes exact text with an optional plan-bound PNG, while `media.publish@1` requires exactly one bounded ISO BMFF MP4 with one video track. Both bind the exact created locator into durable target evidence; the image and video paths also bind completed-upload dimensions. Success requires independent permalink verification of the exact actor, text, optional media identity, dimensions, and media type. Instagram `media.publish@1` remains a capture-required reservation and admits only named image/video MIME types instead of wildcards. Facebook personal Messenger listing is capture-required: the current route and folder queries, paging and completeness, and acknowledgement/presence behavior are not proven. Every other Meta write, all message reads/sends, every Facebook Page operation, and all Group operations except the exact first-page feed read remain capture-required. Marketplace messaging and mutations remain capture-required; its observed feed/listing reads do not confer publishing, seller, conversation, or purchase authority.
- Capture each surface's exact first-party GraphQL/REST exchange and dynamic token source. Do not copy an operation name, revision, feature set, or actor binding across surfaces.
- DMs, comments, replies, posts, stories, reels, shares, Page messages, Group posts, and Marketplace listing publication are R3. Reversible likes, reactions, follows, and saves may be R2.
- For Facebook, bind Page/profile/group/Marketplace actor and target independently. Keep roles, ads, business settings, member moderation, purchases, payments, shipping commitments, and deletion R4.
Expand Down
4 changes: 2 additions & 2 deletions skills/wrench/references/social-platform-routing.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ Use this as routing guidance only. Always inspect `wrench capabilities <adapter>
| LinkedIn | `linkedin` | Official OAuth | Inspect installed schema | Documented API post |
| Bluesky | `bluesky-web` | Profile-backed Bluesky web session | `body`, optional image, media type, and alt text | AT Protocol feed post |
| Substack | `substack-web` | Browser cookies/profile | `body`, optional Note media | Public Substack Note, not an article/newsletter |
| Threads | `meta-web` | Browser cookies/profile | Image `posts.publish`: `body`, audience, one PNG. Video `media.publish`: `body`, audience, one MP4. | Threads post |
| Threads | `meta-web` | Browser cookies/profile | Text/image `posts.publish`: `body`, audience, optional one PNG. Video `media.publish`: `body`, audience, one MP4. | Threads post |

Cleanup is capability-driven too. At this reference revision, `bluesky-web`
exposes observed `content.delete@1` only for one current-account post URI plus
Expand Down Expand Up @@ -59,5 +59,5 @@ Do not place credentials in the input file. Delete task input files after planni
- If the ordered image set exceeds one platform's bound, request a smaller shared set or an explicit per-platform set. Do not manufacture a collage.
- If LinkedIn requires visibility and the user requested a public cross-post, use `public`; otherwise obtain the user's audience choice.
- If Threads requires `audience` and the user requested ordinary posting, use the installed schema's ordinary/default audience only when that meaning is explicit in the capability description.
- At this reference revision, reviewed Threads image publication requires exactly one PNG and reviewed video publication requires exactly one MP4. Treat text-only Threads publication as unavailable unless the installed schema says otherwise.
- At this reference revision, reviewed Threads text/image publication accepts no attachment or exactly one PNG, and reviewed video publication requires exactly one MP4. A dummy PNG, collage, or composer click-path changes the package and is not an installed fallback. JPEG and other image types remain unavailable unless the installed schema independently lists them.
- If image alt text is supported on only some targets, preserve the same factual description on every target that accepts it; unsupported alt text is not a reason to alter the visible post.
2 changes: 1 addition & 1 deletion skills/wrench/references/social-video-platform-routing.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ are authoritative and may change.
| Substack | `substack-web` | `media.publish` when observed | Public Substack Note, not an article or newsletter. |
| TikTok | `tiktok-web` | `media.publish` when observed | Native TikTok video |
| Instagram | `meta-web` on the Instagram surface | `media.publish` when observed | Instagram video or Reel only when the schema says so. |
| Threads | `meta-web` on the Threads surface | `media.publish` | Observed single-MP4 Threads video post; image `posts.publish` remains a separate contract. |
| Threads | `meta-web` on the Threads surface | `media.publish` | Observed single-MP4 Threads video post; text/image `posts.publish` remains a separate contract. |
| YouTube Shorts | `youtube-web` | `media.publish` when observed | Studio video upload. Community `posts.publish` is not a Short. |
| Reddit | `reddit-web` | `media.publish` when observed | One video post in one exact confirmed subreddit. |

Expand Down
11 changes: 5 additions & 6 deletions src/assets/adapters/threads/wrench-web-adapter.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"schemaVersion": 4,
"id": "threads-web",
"version": "1.6.0",
"version": "1.7.0",
"displayName": "Threads (Authenticated Internal API)",
"surfaceId": "threads",
"origins": [
Expand Down Expand Up @@ -411,9 +411,9 @@
}
},
"posts.publish": {
"description": "Observed contract: publish one confirmed Threads post with one reviewed PNG after exact viewer binding, synchronous upload completion, exact minimal created-locator binding, durable upload-dimension target retention, and independent exact permalink actor/text/image readback.",
"description": "Observed contract: publish one confirmed Threads post with optional reviewed PNG after exact viewer binding, optional synchronous upload completion, exact minimal created-locator binding, durable response-bound post identity plus completed-upload dimensions when an image is supplied, and independent exact permalink actor/text and optional image readback.",
"risk": "R3",
"sideEffect": "Publishes one externally visible Threads post with the exact confirmed text and one reviewed PNG.",
"sideEffect": "Publishes one externally visible Threads post with the exact confirmed text and optional reviewed PNG.",
"idempotency": "local-at-most-once",
"dedupeWindowMs": 86400000,
"input": {
Expand All @@ -426,7 +426,7 @@
},
"attachment": {
"type": "file",
"description": "One exact reviewed PNG attachment",
"description": "Optional exact reviewed PNG attachment",
"maxBytes": 20971520,
"mediaTypes": [
"image/png"
Expand All @@ -441,14 +441,13 @@
}
},
"required": [
"attachment",
"body"
]
},
"webSession": {
"site": "threads",
"action": "posts.publish",
"contractVersion": 4,
"contractVersion": 5,
"timeoutMs": 60000,
"maxOutputBytes": 8388608
}
Expand Down
Loading