@volter/twin-telegram 1.0.0 → 1.0.1

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.
Files changed (52) hide show
  1. package/README.md +2 -2
  2. package/dist/journeys/customer-life.json +21 -21
  3. package/dist/journeys/customer-life.outline.md +17 -17
  4. package/dist/journeys/customer-life.outline.verdict.json +17 -52
  5. package/dist/journeys/customer-life.verdict.json +24 -98
  6. package/dist/journeys/decisions.json +49 -13
  7. package/dist/journeys/demand.json +0 -91
  8. package/dist/journeys/first-use.json +21 -0
  9. package/dist/journeys/unreachable.json +1 -1
  10. package/dist/journeys/vendor-examples.json +14 -6
  11. package/dist/spec/SOURCE.md +5 -6
  12. package/dist/spec/patches.json +20 -20
  13. package/dist/spec/sources.json +15 -0
  14. package/dist/src/cli.js +1 -1
  15. package/dist/src/engine/media.d.ts +6 -12
  16. package/dist/src/engine/media.js +28 -66
  17. package/dist/src/engine/text.d.ts +0 -7
  18. package/dist/src/engine/text.js +2 -2
  19. package/dist/src/index.js +2 -1
  20. package/dist/src/manifest.js +7 -6
  21. package/dist/src/semantics/available-methods.js +50 -40
  22. package/dist/src/semantics/doors.d.ts +0 -1
  23. package/dist/src/semantics/doors.js +82 -5
  24. package/dist/src/semantics/shared.d.ts +10 -6
  25. package/dist/src/semantics/shared.js +29 -8
  26. package/dist/src/server.js +2 -19
  27. package/generated/pack-facts.json +10 -0
  28. package/journeys/customer-life.json +21 -21
  29. package/journeys/customer-life.outline.md +17 -17
  30. package/journeys/customer-life.outline.verdict.json +17 -52
  31. package/journeys/customer-life.verdict.json +24 -98
  32. package/journeys/decisions.json +49 -13
  33. package/journeys/demand.json +0 -91
  34. package/journeys/first-use.json +21 -0
  35. package/journeys/unreachable.json +1 -1
  36. package/journeys/vendor-examples.json +14 -6
  37. package/package.json +12 -9
  38. package/spec/SOURCE.md +5 -6
  39. package/spec/patches.json +20 -20
  40. package/spec/sources.json +15 -0
  41. package/src/cli.ts +1 -1
  42. package/src/engine/media.ts +21 -58
  43. package/src/engine/text.ts +2 -2
  44. package/src/index.ts +2 -1
  45. package/src/manifest.ts +7 -6
  46. package/src/semantics/available-methods.ts +55 -41
  47. package/src/semantics/doors.ts +74 -8
  48. package/src/semantics/shared.ts +27 -8
  49. package/src/server.ts +2 -11
  50. package/dist/generated/pack-facts.json +0 -53
  51. package/dist/spec/page-to-openapi.ts +0 -258
  52. package/spec/page-to-openapi.ts +0 -258
package/README.md CHANGED
@@ -7,7 +7,7 @@ semantics.
7
7
  ## What it serves, and for whom
8
8
 
9
9
  The calls the demand's applications make (`journeys/demand.json`): Volter Harness's Telegram channel (the Chat SDK's
10
- `@chat-adapter/telegram`, polling) and Postiz's Telegram provider (`node-telegram-bot-api`).
10
+ `@chat-adapter/telegram`, polling).
11
11
 
12
12
  - A bot reads itself (`getMe`), removes its webhook (`deleteWebhook`) and polls for its updates (`getUpdates`: offset,
13
13
  limit, allowed_updates, and a timeout that holds the request until an update arrives, a long poll).
@@ -48,6 +48,6 @@ host, `api.telegram.org`.
48
48
  - Editing messages, reactions, inline keyboards and callback queries, stickers, payments, inline mode, games, business
49
49
  and passport methods, forum topics, and every other method of the page.
50
50
  - A medium sent by an HTTP URL, which Telegram downloads: a World lets the twin reach nothing outside it, so it answers
51
- as Telegram does for a URL it could not get (Postiz sends URLs only with its opt-in Cloudflare storage).
51
+ as Telegram does for a URL it could not get.
52
52
  - A photo's other sizes (the twin keeps the one it was given), thumbnails, and a video's frames beyond its header.
53
53
  - The 3-second hold the server puts on a repeated short poll, and a second poller's conflict.
@@ -2,7 +2,7 @@
2
2
  "vendor": "telegram",
3
3
  "author": "Contributor 173",
4
4
  "host": "api.telegram.org",
5
- "about": "Tide Labs, a two-person studio, runs its Volter Harness agent on Telegram (a bot polling for updates, answering in private and in the team group, where privacy mode keeps a plain member from hearing the team until it is made an administrator, posting a scheduled digest, and sending a finished card's release notes as a document) and publishes its news to a Telegram channel through Postiz (connected by a /connect post, then text, an album, a reply, a photo, a video and a PDF), from January to the agent's retirement at the end of February.",
5
+ "about": "Tide Labs, a two-person studio, runs its Volter Harness agent on Telegram (a bot polling for updates, answering in private and in the team group, where privacy mode keeps a plain member from hearing the team until it is made an administrator, posting a scheduled digest, and sending a finished card's release notes as a document) and publishes its news to a Telegram channel through Scheduler (connected by a /connect post, then text, an album, a reply, a photo, a video and a PDF), from January to the agent's retirement at the end of February.",
6
6
  "steps": [
7
7
  {
8
8
  "name": "Monday 5 January, 10:00 in Lisbon",
@@ -530,7 +530,7 @@
530
530
  ]
531
531
  },
532
532
  {
533
- "name": "Ana makes the news bot with BotFather for Postiz, which she runs herself (docker compose, local storage)",
533
+ "name": "Ana makes the news bot with BotFather for Scheduler, which she runs herself (docker compose, local storage)",
534
534
  "method": "POST",
535
535
  "path": "/_twin/bots",
536
536
  "body": {
@@ -571,11 +571,11 @@
571
571
  ]
572
572
  },
573
573
  {
574
- "name": "14:06: Ana sets her Postiz's TELEGRAM_TOKEN to the news bot's token and, in Postiz, chooses to add Telegram",
574
+ "name": "14:06: Ana sets her Scheduler's TELEGRAM_TOKEN to the news bot's token and, in Scheduler, chooses to add Telegram",
575
575
  "wait": "1m"
576
576
  },
577
577
  {
578
- "name": "Postiz's connect screen polls the news bot: only the bot's own promotion is waiting, and it holds no /connect",
578
+ "name": "Scheduler's connect screen polls the news bot: only the bot's own promotion is waiting, and it holds no /connect",
579
579
  "method": "POST",
580
580
  "path": "/bot{news_token}/getUpdates",
581
581
  "headers": {
@@ -602,7 +602,7 @@
602
602
  ]
603
603
  },
604
604
  {
605
- "name": "Ana posts the command Postiz shows her in the channel",
605
+ "name": "Ana posts the command Scheduler shows her in the channel",
606
606
  "method": "POST",
607
607
  "path": "/_twin/messages",
608
608
  "body": {
@@ -613,7 +613,7 @@
613
613
  "status": 200
614
614
  },
615
615
  {
616
- "name": "Postiz polls again from the next update (the last update_id it saw plus one) and finds the /connect post",
616
+ "name": "Scheduler polls again from the next update (the last update_id it saw plus one) and finds the /connect post",
617
617
  "method": "POST",
618
618
  "path": "/bot{news_token}/getUpdates",
619
619
  "headers": {
@@ -637,7 +637,7 @@
637
637
  ]
638
638
  },
639
639
  {
640
- "name": "Postiz reads its bot",
640
+ "name": "Scheduler reads its bot",
641
641
  "method": "POST",
642
642
  "path": "/bot{news_token}/getMe",
643
643
  "headers": {
@@ -709,7 +709,7 @@
709
709
  "wait": "10s"
710
710
  },
711
711
  {
712
- "name": "Postiz deletes its notice",
712
+ "name": "Scheduler deletes its notice",
713
713
  "method": "POST",
714
714
  "path": "/bot{news_token}/deleteMessage",
715
715
  "headers": {
@@ -725,7 +725,7 @@
725
725
  ]
726
726
  },
727
727
  {
728
- "name": "Postiz reads the channel it is connecting",
728
+ "name": "Scheduler reads the channel it is connecting",
729
729
  "method": "POST",
730
730
  "path": "/bot{news_token}/getChat",
731
731
  "headers": {
@@ -783,7 +783,7 @@
783
783
  "wait": "71630s"
784
784
  },
785
785
  {
786
- "name": "Postiz publishes the launch post (Postiz's HTML: a bold title, two paragraphs)",
786
+ "name": "Scheduler publishes the launch post (Scheduler's HTML: a bold title, two paragraphs)",
787
787
  "method": "POST",
788
788
  "path": "/bot{news_token}/sendMessage",
789
789
  "headers": {
@@ -944,7 +944,7 @@
944
944
  "wait": "67h"
945
945
  },
946
946
  {
947
- "name": "Postiz publishes the 0.9 release with three screenshots as one album, the text on the first",
947
+ "name": "Scheduler publishes the 0.9 release with three screenshots as one album, the text on the first",
948
948
  "method": "POST",
949
949
  "path": "/bot{news_token}/sendMediaGroup?chat_id={channel}&media=%5B%7B%22type%22%3A%22photo%22%2C%22media%22%3A%22attach%3A%2F%2F0%22%2C%22caption%22%3A%22%3Cb%3ETide%200.9%3C%2Fb%3E%5CnA%20dashboard%20for%20every%20release%2C%20a%20timeline%20you%20can%20drag%2C%20and%20settings%20in%20one%20place.%22%2C%22parse_mode%22%3A%22HTML%22%7D%2C%7B%22type%22%3A%22photo%22%2C%22media%22%3A%22attach%3A%2F%2F1%22%2C%22parse_mode%22%3A%22HTML%22%7D%2C%7B%22type%22%3A%22photo%22%2C%22media%22%3A%22attach%3A%2F%2F2%22%2C%22parse_mode%22%3A%22HTML%22%7D%5D",
950
950
  "form": {
@@ -979,11 +979,11 @@
979
979
  "equals": "Tide 0.9\nA dashboard for every release, a timeline you can drag, and settings in one place."
980
980
  },
981
981
  {
982
- "path": "result.0.photo.0.width",
982
+ "path": "result.0.photo.2.width",
983
983
  "equals": 480
984
984
  },
985
985
  {
986
- "path": "result.2.photo.0.height",
986
+ "path": "result.2.photo.2.height",
987
987
  "equals": 300
988
988
  },
989
989
  {
@@ -1001,13 +1001,13 @@
1001
1001
  "wait": "1h"
1002
1002
  },
1003
1003
  {
1004
- "name": "Postiz publishes the post's comment, the changelog, as a reply to the album",
1004
+ "name": "Scheduler publishes the post's comment, the changelog, as a reply to the album",
1005
1005
  "method": "POST",
1006
1006
  "path": "/bot{news_token}/sendMessage",
1007
1007
  "headers": {
1008
1008
  "content-type": "application/x-www-form-urlencoded"
1009
1009
  },
1010
- "body": "chat_id={channel}&text=Changelog%3A%20drag%20to%20reschedule%20a%20release%3B%20faster%20dashboard%3B%20fixed%20the%20login%20redirect.%0A&parse_mode=HTML&reply_to_message_id={album}",
1010
+ "body": "chat_id={channel}&text=Changelog%3A%20drag%20to%20reschedule%20a%20release%3B%20faster%20dashboard%3B%20fixed%20the%20login%20redirect.%0A&parse_mode=HTML&reply_parameters=%7B%22message_id%22%3A{album}%7D",
1011
1011
  "status": 200,
1012
1012
  "expect": [
1013
1013
  {
@@ -1062,7 +1062,7 @@
1062
1062
  "wait": "1845m"
1063
1063
  },
1064
1064
  {
1065
- "name": "Postiz sends Ana's product photo with its 1,091-character story, and Telegram refuses the caption",
1065
+ "name": "Scheduler sends Ana's product photo with its 1,091-character story, and Telegram refuses the caption",
1066
1066
  "method": "POST",
1067
1067
  "path": "/bot{news_token}/sendPhoto?chat_id={channel}&caption=Tide%20Desk%20started%20as%20a%20sketch%20on%20a%20caf%C3%A9%20napkin%20in%20Porto%2C%20the%20week%20our%20second%20release%20slipped%20for%20the%20third%20time.%20We%20were%20two%20people%20with%20a%20shared%20spreadsheet%2C%20a%20calendar%20nobody%20trusted%20and%20a%20habit%20of%20shipping%20on%20Fridays%20at%20midnight.%20Ana%20drew%20three%20columns%3A%20what%20is%20ready%2C%20what%20is%20waiting%2C%20what%20is%20promised.%20Bruno%20added%20a%20fourth%3A%20who%20is%20waiting%20for%20it.%20That%20napkin%20became%20the%20first%20board%2C%20and%20the%20board%20became%20the%20planner%20we%20use%20every%20Monday.%20We%20kept%20the%20rule%20from%20that%20night%3A%20nothing%20goes%20on%20the%20timeline%20unless%20someone%20can%20say%20who%20is%20waiting%20for%20it.%20It%20sounds%20small%2C%20but%20it%20changed%20how%20we%20talk%20about%20releases.%20We%20stopped%20arguing%20about%20dates%20and%20started%20asking%20who%20would%20notice.%20The%20desk%20in%20the%20photo%20is%20where%20it%20all%20happens%20now%3A%20one%20screen%20for%20the%20timeline%2C%20one%20for%20the%20changelog%2C%20and%20a%20cup%20that%20says%20Friday.%20Today%20Tide%20plans%20the%20weekly%20releases%20of%20forty%20small%20teams%2C%20from%20a%20bakery%27s%20ordering%20app%20in%20Braga%20to%20a%20school%20timetable%20in%20Coimbra.%20If%20your%20team%20still%20keeps%20its%20releases%20in%20a%20spreadsheet%2C%20we%20were%20you%20two%20years%20ago.%20Come%20and%20try%20the%20board%3B%20the%20napkin%20is%20framed%20on%20the%20wall%20behind%20it.&parse_mode=HTML",
1068
1068
  "form": {
@@ -1092,7 +1092,7 @@
1092
1092
  "wait": "20m"
1093
1093
  },
1094
1094
  {
1095
- "name": "Postiz sends the photo again with the short caption",
1095
+ "name": "Scheduler sends the photo again with the short caption",
1096
1096
  "method": "POST",
1097
1097
  "path": "/bot{news_token}/sendPhoto?chat_id={channel}&caption=Tide%20Desk%20started%20as%20a%20sketch%20on%20a%20caf%C3%A9%20napkin%20in%20Porto%2C%20the%20week%20our%20second%20release%20slipped%20for%20the%20third%20time.%20That%20napkin%20became%20the%20first%20board%2C%20and%20the%20board%20became%20the%20planner%20we%20use%20every%20Monday.%20Today%20Tide%20plans%20the%20weekly%20releases%20of%20forty%20small%20teams.&parse_mode=HTML",
1098
1098
  "form": {
@@ -1108,11 +1108,11 @@
1108
1108
  "status": 200,
1109
1109
  "expect": [
1110
1110
  {
1111
- "path": "result.photo.0.width",
1111
+ "path": "result.photo.2.width",
1112
1112
  "equals": 640
1113
1113
  },
1114
1114
  {
1115
- "path": "result.photo.0.height",
1115
+ "path": "result.photo.2.height",
1116
1116
  "equals": 480
1117
1117
  },
1118
1118
  {
@@ -1126,7 +1126,7 @@
1126
1126
  "wait": "6880m"
1127
1127
  },
1128
1128
  {
1129
- "name": "Postiz publishes the product demo video",
1129
+ "name": "Scheduler publishes the product demo video",
1130
1130
  "method": "POST",
1131
1131
  "path": "/bot{news_token}/sendVideo?chat_id={channel}&caption=Three%20seconds%20of%20Tide%200.9%3A%20a%20release%20dragged%20to%20Friday.&parse_mode=HTML",
1132
1132
  "form": {
@@ -1164,7 +1164,7 @@
1164
1164
  "wait": "4h"
1165
1165
  },
1166
1166
  {
1167
- "name": "Postiz publishes the white paper as a PDF",
1167
+ "name": "Scheduler publishes the white paper as a PDF",
1168
1168
  "method": "POST",
1169
1169
  "path": "/bot{news_token}/sendDocument?chat_id={channel}&caption=How%20a%20two-person%20team%20ships%20every%20week%3A%20our%20notes%2C%20as%20a%20PDF.&parse_mode=HTML",
1170
1170
  "form": {
@@ -2,8 +2,8 @@
2
2
 
3
3
  **The customer.** Tide Labs, a two-person software studio in Lisbon. Ana Ribeiro, its founder, runs an agent on Volter
4
4
  Harness that she and the team talk to on Telegram, and publishes the studio's news to its Telegram channel with
5
- Postiz. Bruno Costa, its engineer, is on the team chat. The story runs from Monday 5 January to Friday 27 February
6
- 2026: two bots made, the agent at work in a private chat and a group, a news channel connected to Postiz and posted to
5
+ Scheduler. Bruno Costa, its engineer, is on the team chat. The story runs from Monday 5 January to Friday 27 February
6
+ 2026: two bots made, the agent at work in a private chat and a group, a news channel connected to Scheduler and posted to
7
7
  for six weeks, the agent's group retired and, at the end, the agent's token revoked. The channel and its bot stay.
8
8
 
9
9
  ## Who acts, and with what
@@ -21,8 +21,8 @@ for six weeks, the agent's group retired and, at the end, the agent's token revo
21
21
  Harness's board, where the agent files work as cards, tells a chat subscribed to a card when it is done, the card's
22
22
  files attached; the Chat SDK sends a message with files as MarkdownV2 (supercode board/dispatch.mjs notifyChats,
23
23
  @chat-adapter/telegram's resolveParseMode).
24
- - **The news bot**, @tidelabs_news_bot, token N: the bot Postiz posts with. Postiz's Telegram integration calls with
25
- the one bot its deployment configures, its TELEGRAM_TOKEN (postiz-app telegram.provider.ts), so Ana runs Postiz
24
+ - **The news bot**, @tidelabs_news_bot, token N: the bot Scheduler posts with. Scheduler's Telegram integration calls with
25
+ the one bot its deployment configures, its TELEGRAM_TOKEN, so Ana runs Scheduler
26
26
  herself (docker compose, local storage) and sets its TELEGRAM_TOKEN to token N. She makes the bot an administrator of
27
27
  the channel allowed to post and to delete messages.
28
28
 
@@ -54,17 +54,17 @@ is a member; a bot deletes another's message in a channel only with the right to
54
54
  exactly those items to the home chat (sendMessage to the group).
55
55
  5. **Wednesday 7 January, 14:00. The news channel.** Ana makes the public channel "Tide Labs News" (@tidelabs_news)
56
56
  with the studio's logo as its photo (door). She makes the news bot with BotFather (token N) and adds it to the
57
- channel as an administrator that may post and delete messages (door). In the Postiz she runs herself (docker compose,
58
- local storage) she sets TELEGRAM_TOKEN to token N, and then chooses to add Telegram; Postiz
59
- shows the command to post, "/connect" and a word, and she posts it in the channel (door). Postiz's connect screen
57
+ channel as an administrator that may post and delete messages (door). In the Scheduler she runs herself (docker compose,
58
+ local storage) she sets TELEGRAM_TOKEN to token N, and then chooses to add Telegram; Scheduler
59
+ shows the command to post, "/connect" and a word, and she posts it in the channel (door). Scheduler's connect screen
60
60
  polls (getUpdates, its library sending allowed_updates as the fields allowed_updates[0]=message and
61
61
  allowed_updates[1]=channel_post, which the Bot API does not read as its JSON-serialized list, so every update type
62
- comes back): the bot's own membership change and her post come back. Postiz reads its bot (getMe), checks the bot
62
+ comes back): the bot's own membership change and her post come back. Scheduler reads its bot (getMe), checks the bot
63
63
  may delete messages there (getChatMember: an administrator with can_delete_messages), deletes her /connect post
64
64
  (deleteMessage), posts "Connection Successful. Message will be deleted in 10 seconds." (sendMessage) and, ten
65
65
  seconds later, deletes that too (deleteMessage). It then reads the channel (getChat), the photo's file (getFile), and copies the photo into its
66
66
  storage from the file's link (the file download).
67
- 6. **Thursday 8 January, 10:00. The launch post, and the release notes.** Postiz publishes Ana's announcement, bold title and two paragraphs
67
+ 6. **Thursday 8 January, 10:00. The launch post, and the release notes.** Scheduler publishes Ana's announcement, bold title and two paragraphs
68
68
  (sendMessage, parse_mode HTML).
69
69
  At 11:00 Ana asks the agent in her private chat for the 0.9 release notes by Friday; Harness's poll receives it,
70
70
  it shows the bot typing, and the agent answers that the work is card t_7c1e9a04 on its board and that this chat
@@ -72,23 +72,23 @@ is a member; a bot deletes another's message in a channel only with the right to
72
72
  January, 15:00**: the card is done with its notes file, and Harness's board tells the chat: the notice "card … done
73
73
  — Draft the 0.9 release notes" and its summary as the caption of the file (sendDocument, the file uploaded, the
74
74
  caption in MarkdownV2 as the Chat SDK escapes it).
75
- 7. **Monday 12 January, 10:00. A release with screenshots.** Postiz publishes the release post with three screenshots
75
+ 7. **Monday 12 January, 10:00. A release with screenshots.** Scheduler publishes the release post with three screenshots
76
76
  as one album, the text on the first (sendMediaGroup, the images uploaded). At 11:00 it publishes the post's comment,
77
- the changelog, as a reply to the album's first message (sendMessage with reply_to_message_id).
77
+ the changelog, as a reply to the album's first message (sendMessage with reply_parameters naming it).
78
78
  8. **Monday 12 January, 18:00. The standups move.** The team moves its standups to a video call and Ana removes the
79
79
  agent bot from "Tide Labs team" (door), but leaves the digest job on. Tuesday 13 January at 09:15 the job posts its
80
80
  digest to the home chat, which says no standup items were posted this week (that morning's standup was on the
81
81
  call), and Telegram refuses: "Forbidden: bot was kicked from the group chat". Ana deletes the job in Harness (no
82
82
  Telegram call).
83
83
  9. **Wednesday 14 January, 16:00. A caption too long.** Ana's next post is one product photo with a 1,091-character
84
- story. Postiz sends it (sendPhoto) and Telegram refuses it: a photo's caption holds at most 1,024 characters
85
- ("Bad Request: message caption is too long"); Postiz shows "Telegram rejected the post". At 16:20 she cuts the story
86
- to a paragraph and Postiz sends it again, which posts.
87
- 10. **Monday 19 January, 11:00. A demo and a paper.** Postiz publishes the product demo video (sendVideo, uploaded) and,
84
+ story. Scheduler sends it (sendPhoto) and Telegram refuses it: a photo's caption holds at most 1,024 characters
85
+ ("Bad Request: message caption is too long"); Scheduler shows "Telegram rejected the post". At 16:20 she cuts the story
86
+ to a paragraph and Scheduler sends it again, which posts.
87
+ 10. **Monday 19 January, 11:00. A demo and a paper.** Scheduler publishes the product demo video (sendVideo, uploaded) and,
88
88
  at 15:00, the white paper as a PDF (sendDocument, uploaded).
89
89
  11. **Friday 27 February, 17:00. The agent retired.** Ana stops using the agent on Telegram and, in BotFather, makes a new
90
90
  token for it (/token), which revokes token A. Harness, still running on her laptop, polls with it and is refused ("Unauthorized"); she stops it. The
91
- news channel, its posts and the news bot stay with Postiz.
91
+ news channel, its posts and the news bot stay with Scheduler.
92
92
 
93
93
  ## What the story reaches
94
94
 
@@ -96,4 +96,4 @@ getMe (both bots), deleteWebhook, getUpdates (held, a long poll; with allowed_up
96
96
  privacy mode (a plain member bot sent a service message and not a plain mention; an administrator bot sent every
97
97
  message), sendChatAction, sendMessage (plain, HTML, a reply; refused for a removed bot), getChatMember, deleteMessage
98
98
  (twice), getChat, getFile, the file download, sendPhoto (refused for its caption, then sent), sendVideo, sendDocument
99
- (Postiz's PDF; Harness's notes with a MarkdownV2 caption), sendMediaGroup; and a revoked token's refusal.
99
+ (Scheduler's PDF; Harness's notes with a MarkdownV2 caption), sendMediaGroup; and a revoked token's refusal.
@@ -1,75 +1,40 @@
1
1
  {
2
2
  "judge": {
3
- "agent": "Claude Code (Claude Agent SDK), model claude-opus-5-5",
4
- "name": "Contributor 106"
3
+ "agent": "Claude journey judge (Opus)",
4
+ "name": "Independent journey judge"
5
5
  },
6
6
  "authors": [
7
- "Contributor 173"
7
+ "yueranyuan",
8
+ "Aaron (A-001)",
9
+ "Claude Opus 5.5",
10
+ "Codex"
8
11
  ],
9
- "bar": "829132787d94a2d4",
10
- "sha256": "267e4ae00d8d6bd435831be1a5b9dc741a7003bd0a43641ea7c4c000ee974e20",
11
- "judgedAt": "2026-10-02",
12
+ "sha256": "4186f9087ab35bb7639a6d5aaa3471c51695ed2be4c086e417a7e2ebd2310d19",
13
+ "judgedAt": "2026-10-15",
12
14
  "plausible": true,
13
15
  "rulings": [
14
16
  {
15
- "id": "three-tuesdays-skipped",
17
+ "id": "reply-to-message-id-era",
16
18
  "steps": [
17
- "act 3",
18
- "act 4",
19
- "act 7",
20
- "act 8",
21
- "act 9",
22
- "act 10"
19
+ "act 7"
23
20
  ],
24
- "barItem": "a stated cause that never happens, and a promise never kept",
25
- "reason": "Act 3 sets the standup weekly on Tuesdays and makes the agent an administrator, which is sent every group message (https://core.telegram.org/bots/features#privacy-mode). Act 4 runs the first standup and digest on 6 January. The standups move to the call only on Monday 2 February (act 10). Tuesdays 13, 20 and 27 January fall within acts 7-9 with no standup, no poll and no digest. Act 10's digest then says that no items were posted \"this week\", as if earlier weeks had them.",
26
- "correction": "Move act 10 to Monday 12 January, 18:00, so that the refused digest is Tuesday 13 January's. Or tell the three January Tuesdays' standups and digests."
27
- },
28
- {
29
- "id": "postiz-never-given-token-n",
30
- "steps": [
31
- "Who acts",
32
- "act 5"
33
- ],
34
- "barItem": "the wrong actor or credential for an act",
35
- "reason": "Postiz posts to Telegram through the one bot its deployment configures, process.env.TELEGRAM_TOKEN (postiz-app e0a08a7, libraries/nestjs-libraries/src/integrations/social/telegram.provider.ts:19). In hosted Postiz, that bot is Postiz's own. The outline calls @tidelabs_news_bot, token N, \"Postiz's Telegram integration\", and in act 5 Ana makes the bot and Postiz then calls with it. The outline never says that she runs Postiz herself or that token N becomes its TELEGRAM_TOKEN.",
36
- "correction": "In 'Who acts' and act 5, say that Ana self-hosts Postiz (docker compose, local storage) and sets its TELEGRAM_TOKEN to token N before she adds Telegram."
21
+ "barItem": "the wrong era: building on an API the vendor had deprecated by the World's date; a call through a door the vendor does not document",
22
+ "reason": "Act 7 has Scheduler publish the changelog comment as a reply 'with reply_to_message_id'. Telegram replaced that parameter in Bot API 7.0, December 29, 2023 (https://core.telegram.org/bots/api-changelog: 'Replaced parameters reply_to_message_id and allow_sending_without_reply in the methods ... with the field reply_parameters'), two years before the story's January 2026, and the reference page the spec is written from (https://core.telegram.org/bots/api#sendmessage, Bot API 10.3) no longer documents it at all, as spec/SOURCE.md itself states; the act builds on a door the vendor withdrew, even though the server still reads it.",
23
+ "correction": "Act 7 sends the reply with reply_parameters (a JSON-serialized ReplyParameters naming the album's first message_id), as https://core.telegram.org/bots/api#sendmessage documents, and the 'What the story reaches' line says so."
37
24
  }
38
25
  ],
39
26
  "applied": {
40
- "from": "7f1802b57b256e32061a52ede0d2972060c725a7550b068ac1ae23f131c63c6c",
27
+ "from": "4bdc79fa09692fb332a4eac8080c9a10e5d7b2234435712284ef4e599d37d4eb",
41
28
  "wasPlausible": false,
42
29
  "steps": [
43
- "0",
44
- "5",
45
- "8",
46
- "9",
47
- "10"
30
+ "act 7"
48
31
  ],
49
32
  "rulings": [
50
33
  {
51
- "id": "three-tuesdays-skipped",
52
- "steps": [
53
- "act 3",
54
- "act 4",
55
- "act 7",
56
- "act 8",
57
- "act 9",
58
- "act 10"
59
- ],
60
- "barItem": "a stated cause that never happens, and a promise never kept",
61
- "reason": "Act 3 sets the standup weekly on Tuesdays and makes the agent an administrator, which is sent every group message (https://core.telegram.org/bots/features#privacy-mode). Act 4 runs the first standup and digest on 6 January. The standups move to the call only on Monday 2 February (act 10). Tuesdays 13, 20 and 27 January fall within acts 7-9 with no standup, no poll and no digest. Act 10's digest then says that no items were posted \"this week\", as if earlier weeks had them.",
62
- "correction": "Move act 10 to Monday 12 January, 18:00, so that the refused digest is Tuesday 13 January's. Or tell the three January Tuesdays' standups and digests."
63
- },
64
- {
65
- "id": "postiz-never-given-token-n",
66
34
  "steps": [
67
- "Who acts",
68
- "act 5"
35
+ "act 7"
69
36
  ],
70
- "barItem": "the wrong actor or credential for an act",
71
- "reason": "Postiz posts to Telegram through the one bot its deployment configures, process.env.TELEGRAM_TOKEN (postiz-app e0a08a7, libraries/nestjs-libraries/src/integrations/social/telegram.provider.ts:19). In hosted Postiz, that bot is Postiz's own. The outline calls @tidelabs_news_bot, token N, \"Postiz's Telegram integration\", and in act 5 Ana makes the bot and Postiz then calls with it. The outline never says that she runs Postiz herself or that token N becomes its TELEGRAM_TOKEN.",
72
- "correction": "In 'Who acts' and act 5, say that Ana self-hosts Postiz (docker compose, local storage) and sets its TELEGRAM_TOKEN to token N before she adds Telegram."
37
+ "why": "Act 7 sends the reply with reply_parameters (a JSON-serialized ReplyParameters naming the album's first message_id), as https://core.telegram.org/bots/api#sendmessage documents, and the 'What the story reaches' line says so."
73
38
  }
74
39
  ]
75
40
  }
@@ -1,133 +1,59 @@
1
1
  {
2
2
  "judge": {
3
- "agent": "Claude Code (Claude Agent SDK), model claude-opus-5-5",
4
- "name": "Contributor 106"
3
+ "agent": "Claude journey judge (Opus)",
4
+ "name": "Independent journey judge"
5
5
  },
6
6
  "authors": [
7
- "Contributor 173"
7
+ "yueranyuan",
8
+ "Aaron (A-001)",
9
+ "Claude Opus 5.5",
10
+ "Codex"
8
11
  ],
9
- "bar": "829132787d94a2d4",
10
- "sha256": "f58ee4db9e9c90c0f87f6018cf370f00963898ae16e0d4e7069e6afca17a6cf3",
11
- "judgedAt": "2026-10-02",
12
+ "sha256": "d4f45ec531a3cafd7ec746629b2fb110cf5bb5adb0664f52a5d279eaf7f59ad3",
13
+ "judgedAt": "2026-10-15",
12
14
  "plausible": true,
13
15
  "rulings": [
14
16
  {
15
- "id": "three-tuesdays-skipped",
17
+ "id": "reply-to-message-id-era",
16
18
  "steps": [
17
- 16,
18
- 20,
19
- 22,
20
- 30,
21
- 58,
22
- 62,
23
- 66,
24
- 70,
25
- 73
19
+ 61
26
20
  ],
27
- "barItem": "a stated cause that never happens, and a promise never kept",
28
- "reason": "Steps 16, 20 and 22 set the standup for 9:00 every Tuesday, with items posted in the group, and the agent promises the digest at 9:15. From step 19 the agent is an administrator, and an administrator is sent every group message (https://core.telegram.org/bots/features#privacy-mode, \"bot admins always receive all messages\"). The job runs once, Tuesday 6 January (step 30). The team keeps the group standup until Monday 2 February (step 70: \"the standups move to a video call\"), yet Tuesdays 13, 20 and 27 January pass inside steps 58-70 with no items posted, no poll and no digest. Step 73's digest then says \"No standup items were posted this week\", which implies the earlier weeks had items. Three of the four weekly runs the story promises never happen, and nothing in the story explains why.",
29
- "correction": "Move the standups' move and the bot's removal to Monday 12 January, 18:00, after step 61. The job's next run, Tuesday 13 January at 09:15, is then the refused one, and the waits to Wednesday 14 January 16:00 and onward are adjusted. Alternatively, show the Tuesday standups of 13, 20 and 27 January: items posted, a poll, and a digest each week."
21
+ "barItem": "the wrong era: building on an API the vendor had deprecated by the World's date; a call through a door the vendor does not document",
22
+ "reason": "Step 61 (Monday 12 January 2026) replies to the album with the form field reply_to_message_id={album}. Telegram replaced that parameter in Bot API 7.0, December 29, 2023 (https://core.telegram.org/bots/api-changelog: 'Replaced parameters reply_to_message_id and allow_sending_without_reply in the methods ... with the field reply_parameters'), and the page the spec is written from (https://core.telegram.org/bots/api#sendmessage, Bot API 10.3) no longer documents it; spec/SOURCE.md admits the page 'no longer lists it' and patches it in. A step through a parameter the vendor withdrew two years before the World's date is rejected even where the twin answers it.",
23
+ "correction": "Step 61 sends reply_parameters={\"message_id\":{album}} (JSON-serialized ReplyParameters, as https://core.telegram.org/bots/api#sendmessage documents) in place of reply_to_message_id, keeping its expectation result.reply_to_message.message_id equals {album}."
30
24
  },
31
25
  {
32
- "id": "postiz-never-given-token-n",
26
+ "id": "photo-sizes-order",
33
27
  "steps": [
34
- 33,
35
- 37,
36
- 40,
37
- 41,
38
- 42,
39
- 43,
40
- 45,
41
- 46,
42
- 47,
43
- 48,
44
- 50,
45
28
  59,
46
- 61,
47
- 63,
48
- 65,
49
- 67,
50
29
  69
51
30
  ],
52
- "barItem": "the wrong actor or credential for an act",
53
- "reason": "Postiz's Telegram provider calls with one bot, the one its deployment configures: `new TelegramBot(process.env.TELEGRAM_TOKEN!)` (libraries/nestjs-libraries/src/integrations/social/telegram.provider.ts:19, postiz-app e0a08a7; demand.json, Postiz's client: \"TELEGRAM_TOKEN\"). In hosted Postiz, that is Postiz's own bot and not one a customer makes. Step 33 has Ana make @tidelabs_news_bot \"for Postiz\", and from step 37 on Postiz calls with {news_token}. But no step or name says that Ana runs Postiz herself, or that token N is set as its TELEGRAM_TOKEN. The life never shows how the credential Postiz uses reaches it, and as written it reads as the hosted product calling with a bot that belongs to the customer.",
54
- "correction": "In step 33 or a step beside it, say that Ana runs Postiz herself (docker compose, local storage, as demand.json reads it) and sets TELEGRAM_TOKEN to the news bot's token before she adds Telegram. Use the same wording in the outline."
55
- },
56
- {
57
- "id": "running-harness-polls-without-offset",
58
- "steps": [
59
- 76
60
- ],
61
- "barItem": "content that does not bear out the step's name",
62
- "reason": "Step 76 is Harness \"still running on her laptop\". The adapter it runs keeps its offset in its polling loop and sends it on every poll: `offset = update.update_id + 1` (@chat-adapter/telegram 4.39.0, dist/index.js:3327-3345, pollingLoop; demand.json: \"confirming the last with offset\"). The life last confirmed one at step 53. Step 76's body, {\"limit\": 100, \"timeout\": 30}, is the request a freshly started adapter sends (step 9), not the request of the process the step names.",
63
- "correction": "Step 76's body: {\"offset\": \"{agent_next}\", \"limit\": 100, \"timeout\": 30}."
31
+ "barItem": "vendor behaviour the vendor's documentation contradicts",
32
+ "reason": "Step 59 expects result.0.photo.0.width 480 and result.2.photo.0.height 300 for 480x300 PNG uploads, and step 69 expects result.photo.0.width 640 and height 480 for a 640x480 JPEG: the first PhotoSize being the uploaded image itself. Telegram 'attaches a vector of thumbnails with reduced resolution to all uploaded media', the smallest type s 'bounded by 100x100 pixels' and m by 320x320 (https://core.telegram.org/api/files, image thumbnail types; Message.photo is 'available sizes of the photo', https://core.telegram.org/bots/api#message), and the Bot API answers them in ascending order (TDLib at 42e6a52, td/telegram/PhotoSize.cpp get_photo_sizes_object, stable_sort by size then width*height, the TDLib source the spec cites). photo.0 is the 100-pixel thumbnail; the original's dimensions are on the last size.",
33
+ "correction": "Steps 59 and 69 expect the uploaded dimensions on the last PhotoSize (step 59: result.0.photo.2.width 480 and result.2.photo.2.height 300; step 69: result.photo.2.width 640 and height 480), with photo.0 the s thumbnail, bounded by 100x100."
64
34
  }
65
35
  ],
66
36
  "applied": {
67
- "from": "1248e944117c27955453a626f8ed5a44ff07ad520f525feaa0a7a6dc53399963",
37
+ "from": "8251bda4592d9f3dae1bb5067727bee657d212ebd5aca36c32e8a7f4d1beb222",
68
38
  "wasPlausible": false,
69
39
  "steps": [
70
- "33",
71
- "36",
72
- "62",
73
- "70",
74
- "71",
75
- "72",
76
- "73",
77
- "74",
78
- "76"
40
+ "59",
41
+ "61",
42
+ "69"
79
43
  ],
80
44
  "rulings": [
81
45
  {
82
- "id": "three-tuesdays-skipped",
83
46
  "steps": [
84
- 16,
85
- 20,
86
- 22,
87
- 30,
88
- 58,
89
- 62,
90
- 66,
91
- 70,
92
- 73
47
+ 61
93
48
  ],
94
- "barItem": "a stated cause that never happens, and a promise never kept",
95
- "reason": "Steps 16, 20 and 22 set the standup for 9:00 every Tuesday, with items posted in the group, and the agent promises the digest at 9:15. From step 19 the agent is an administrator, and an administrator is sent every group message (https://core.telegram.org/bots/features#privacy-mode, \"bot admins always receive all messages\"). The job runs once, Tuesday 6 January (step 30). The team keeps the group standup until Monday 2 February (step 70: \"the standups move to a video call\"), yet Tuesdays 13, 20 and 27 January pass inside steps 58-70 with no items posted, no poll and no digest. Step 73's digest then says \"No standup items were posted this week\", which implies the earlier weeks had items. Three of the four weekly runs the story promises never happen, and nothing in the story explains why.",
96
- "correction": "Move the standups' move and the bot's removal to Monday 12 January, 18:00, after step 61. The job's next run, Tuesday 13 January at 09:15, is then the refused one, and the waits to Wednesday 14 January 16:00 and onward are adjusted. Alternatively, show the Tuesday standups of 13, 20 and 27 January: items posted, a poll, and a digest each week."
49
+ "why": "Step 61 sends reply_parameters={\"message_id\":{album}} (JSON-serialized ReplyParameters, as https://core.telegram.org/bots/api#sendmessage documents) in place of reply_to_message_id, keeping its expectation result.reply_to_message.message_id equals {album}."
97
50
  },
98
51
  {
99
- "id": "postiz-never-given-token-n",
100
52
  "steps": [
101
- 33,
102
- 37,
103
- 40,
104
- 41,
105
- 42,
106
- 43,
107
- 45,
108
- 46,
109
- 47,
110
- 48,
111
- 50,
112
53
  59,
113
- 61,
114
- 63,
115
- 65,
116
- 67,
117
54
  69
118
55
  ],
119
- "barItem": "the wrong actor or credential for an act",
120
- "reason": "Postiz's Telegram provider calls with one bot, the one its deployment configures: `new TelegramBot(process.env.TELEGRAM_TOKEN!)` (libraries/nestjs-libraries/src/integrations/social/telegram.provider.ts:19, postiz-app e0a08a7; demand.json, Postiz's client: \"TELEGRAM_TOKEN\"). In hosted Postiz, that is Postiz's own bot and not one a customer makes. Step 33 has Ana make @tidelabs_news_bot \"for Postiz\", and from step 37 on Postiz calls with {news_token}. But no step or name says that Ana runs Postiz herself, or that token N is set as its TELEGRAM_TOKEN. The life never shows how the credential Postiz uses reaches it, and as written it reads as the hosted product calling with a bot that belongs to the customer.",
121
- "correction": "In step 33 or a step beside it, say that Ana runs Postiz herself (docker compose, local storage, as demand.json reads it) and sets TELEGRAM_TOKEN to the news bot's token before she adds Telegram. Use the same wording in the outline."
122
- },
123
- {
124
- "id": "running-harness-polls-without-offset",
125
- "steps": [
126
- 76
127
- ],
128
- "barItem": "content that does not bear out the step's name",
129
- "reason": "Step 76 is Harness \"still running on her laptop\". The adapter it runs keeps its offset in its polling loop and sends it on every poll: `offset = update.update_id + 1` (@chat-adapter/telegram 4.39.0, dist/index.js:3327-3345, pollingLoop; demand.json: \"confirming the last with offset\"). The life last confirmed one at step 53. Step 76's body, {\"limit\": 100, \"timeout\": 30}, is the request a freshly started adapter sends (step 9), not the request of the process the step names.",
130
- "correction": "Step 76's body: {\"offset\": \"{agent_next}\", \"limit\": 100, \"timeout\": 30}."
56
+ "why": "Steps 59 and 69 expect the uploaded dimensions on the last PhotoSize (step 59: result.0.photo.2.width 480 and result.2.photo.2.height 300; step 69: result.photo.2.width 640 and height 480), with photo.0 the s thumbnail, bounded by 100x100."
131
57
  }
132
58
  ]
133
59
  }