Skip to content

Releases: yohimik/crier

v1.1.1

Choose a tag to compare

@yohimik yohimik released this 06 Sep 18:27

Fixes

  • Make repeating-gradient origins round consistently in packaged Go and TinyGo builds with a pinned, two-line webrender patch. Pixel acceptance thresholds are unchanged; unprepared source builds still use upstream webrender's permitted floating-point behavior. (acac2f0) (by yohimik)
  • Add stripped, static TinyGo Linux AMD64 and ARM64 binaries alongside the six standard release binaries, using the published TinyGo v0.43.0-net.2 fork. Installers and normal self-update still select standard binaries; tiny assets are opt-in. (acac2f0) (by yohimik)
  • Validate tiny artifacts with full CLI integration, real FFmpeg, TinyGo-built update replacements, TLS refusal/trust, offline rollback and same-source pixel comparisons, retaining compiler and artifact provenance. (acac2f0) (by yohimik)

Authors

  • yohimik

Validation and provenance

Post-release CI run 34061068016 passed all eight jobs against exact released source acac2f0eae0d98e42f442c7f4e6a36ccf9bc3665 and verified published binary hashes.

  • Native Linux, macOS and Windows, each on AMD64 and ARM64: Dispat, platform-script and released-composite-action installation checks passed. Unix smoke suites passed all seven tests; Windows passed six with the one declared Unix-shell-only announcement test skipped.
  • Native Linux AMD64 and ARM64: full Go and TinyGo integration passed 144 top-level tests / 156 passing events per compiler, with zero failures or skips, including real FFmpeg, stamped updates, TLS and rollback.
  • All 13 PNG comparisons per architecture passed unchanged thresholds. AMD64 was pixel-exact; ARM64 differed only in four event-card pixels by one channel value.
  • Standard source format, vet, lint, workflow/shell checks, generated docs, unit/E2E tests, six-target cross-compilation and coverage passed; combined statement coverage was 90.6%.

The original publication was manual, before this CI validation. That was a process error: future publication must use CI/CD. This metadata correction does not replace the exact release tag, binaries, checksum manifest or original acceptance report. The frozen artifact report predates CI; the linked run supplies the subsequent native-platform evidence.

These are Crier application acceptance results, not proof of general Go networking compatibility. The fork retains broader deadline/cancellation and descriptor limitations; generic emulated AMD64 closed-descriptor tests also had failures. See TinyGo acceptance for scope and historical results.

Optional tiny binaries

Asset Bytes
crier-tiny-linux-amd64 16,447,000
crier-tiny-linux-arm64 13,835,840

Download the matching asset explicitly and verify it against SHA256SUMS. Tiny binaries are Linux-only and are not the installer's or normal self-update's default.

Install

curl -fsSL https://raw.githubusercontent.com/yohimik/crier/v1.1.1/install.sh | CRIER_VERSION=1.1.1 sh
& ([scriptblock]::Create((irm https://raw.githubusercontent.com/yohimik/crier/v1.1.1/install.ps1))) -Version '1.1.1'
dispat install yohimik/crier

v1.1.0

Choose a tag to compare

@github-actions github-actions released this 05 Sep 03:09

Features

  • publish release media together (7edaff9) (by yohimik)

Fixes

  • templates execute without reflect (daf8778) (by yohimik, Claude Fable 5.1)
    crier's templates ran on html/template and text/template, whose executors
    reach into values and call functions through reflection. That was the one
    thing a TinyGo toolchain could not do for crier: its reflect has no
    Type.NumOut and no Value.Call, and text/template needs both before it
    executes a line, so a fork-built crier panicked on its first template.

    internal/template/exec is an executor over text/template/parse's tree with
    no reflection in it. crier's data is never an arbitrary struct — a document
    is YAML or JSON, so maps, lists and scalars — and its function set is its
    own, so the executor walks plain values and dispatches functions through
    a typed table. Its tests run the same templates through both executors
    and require the same output: the truth rules, the missing-key options,
    the comparison functions and their errors, the printing, the variable
    scoping, the range order. The real templates — every example and both
    announcement layouts — render byte for byte what html/template rendered,
    comments aside.

    What changes for a gc binary is small and written down in the template
    documentation: one escaping rule (every value escaped as HTML text) where
    html/template had a context machine for URLs, CSS and scripts that a
    renderer never needed; template comments kept rather than stripped;
    method calls limited to times; join accepting a list from the data
    document, which the documentation's own example relied on and
    text/template refused; and a version line that names TinyGo when TinyGo
    built the binary.

    Under the fork the black-box suite now passes 106 of its tests where it
    passed 47, and renders. What fails is the fork's net, which dials and
    does not listen, so the stage server cannot serve; that is the fork's to
    close, and until it does the release binaries stay gc's.

Authors

  • yohimik
  • Claude Fable 5.1

Install

curl -fsSL https://raw.githubusercontent.com/yohimik/crier/v1.1.0/install.sh | CRIER_VERSION=1.1.0 sh
:CRIER_VERSION = '1.1.0'
irm https://raw.githubusercontent.com/yohimik/crier/v1.1.0/install.ps1 | iex
dispat install yohimik/crier

v1.0.0

Choose a tag to compare

@github-actions github-actions released this 02 Sep 19:06

Breaking Changes

  • finally graduated, thanks for not unsubscribing during dogfooding (a83f31b) (by yohimik)

  • rc train before 1.0.0 (aad80fc) (by yohimik)

  • fail closed on anything unrecognised (b5720f3) (by yohimik, Claude Fable 5)
    An unknown command word, an unknown flag anywhere, and a stray positional
    argument are all usage errors now, and the unknown-command message lists what
    would have worked. Nothing is guessed and nothing passes through: the failure
    this prevents is a mistyped --dry-run that publishes for real.

    Adds --set key=value, repeatable, which sets any key by its dotted name at
    the flag layer. A key that does not exist is refused with the nearest one
    suggested, because a flag that silently goes nowhere looks like it worked.

  • add init and make version a flag (57ead75) (by yohimik, Claude Fable 5)
    crier init writes a configuration to start from: a short commented file by
    default, every option with --full, in yaml, json or toml. The generator moved
    into internal/configgen and is now shared with tools/gendocs, so what init
    writes and what crier.example.yaml holds come from one walk over the registry
    and cannot drift apart.

    crier version becomes crier --version, special-cased ahead of the rule that
    sends a leading flag to publish.

    The system font scan is wrapped in a recover: the parser underneath panics
    rather than erroring on a font file it cannot read, and one such file took the
    whole program down while rendering something that never needed that font.

  • make publish the default command (f615fd6) (by yohimik, Claude Fable 5)
    Bare crier renders and posts, so the everyday flow is to change into a
    project directory and run one word. Also silences the lint gate with
    reasons rather than blanket exclusions.

Features

  • a graduation dresses up and takes its time (50d2f5d) (by yohimik, Claude Fable 5)
    The crossing from rc to stable is the release worth stopping for, and
    v1.0.0 crossed it in silence. The card now knows a graduation when
    dispat hands it one: the cover carries a stable banner counting the
    candidates it took, both captions open with the graduation and the
    thanks, and the collected train fills the pages behind it. The
    linkedin reel stops squeezing into sixteen seconds: six for the cover,
    four a page, with render.video.audio-loop, a new key that repeats the
    soundtrack for as long as a slideshow runs. Instagram keeps the same
    pages carousel, which on graduation day is the whole train.

  • linkedin gets the whole release in one post (06700f3) (by yohimik, Claude Fable 5)
    One post was the requirement and LinkedIn's schema forbids the easy
    shape: a post takes one video or many images, never both, with
    content.multiImage documented images-only. So the pages go inside the
    video. The reel holds the cover under the fanfare and then leafs
    through the changelog pages in reading order, sixteen seconds for the
    whole release, one post carrying all of it. The pages render once and
    feed everything: the anthem's frames, the reel's, and the cover both
    clips open on. No ffmpeg still means the album, cover first.

  • the release pings before it posts (b0eafa0) (by yohimik, Claude Fable 5)
    A revoked token used to surface as a skipped announcement at the end
    of a fifteen-minute run. Now a ping job stands after the plan: the
    previous release's binary asks every announcement platform whether the
    credentials still work, read-only, nothing posted, and a dead token
    fails the run in its first minute. A repository without the secrets
    skips the gate and releases without announcing, as before.

  • the release chooses its own look and its own fanfare (6e257ee) (by yohimik, Claude Fable 5)
    Audio pools join template pools: render.video.audio-pool lists the
    files, the run's seed picks one, and the pick is drawn right after the
    layout's so the two travel together. The announcement dogfoods both.
    Four public-domain anthems now sit beside the card, two layouts share
    every load-bearing rule and differ in everything cosmetic, and
    announce.sh derives one seed from the version for every pass, so the
    stories wear the face the feed wore and any release can be rendered
    again exactly as it went out.

  • boosty is the fourteenth platform (ee06f06) (by yohimik, Claude Fable 5)
    The first platform without an official API: the contract is what the
    web editor itself speaks, pinned from four independent client
    libraries and encoded in the test fake, with every host configurable.
    A post is uploaded images and draft-style text blocks in one call,
    and its audience is the new part: free for everyone, priced for a
    one-time purchase, or held to a subscription level. Video stays out
    until someone captures the editor uploading one; a guessed endpoint
    would leave an unplayable file in a paid post.

  • youtube is the thirteenth platform (10784ca) (by yohimik, Claude Fable 5)
    Video only, because that is all the Data API takes: community image
    posts have no public API at all. OAuth refresh tokens the way reddit
    taught crier, a resumable session and one streamed PUT, the caption as
    the description and its first line as the title. A Short is not an
    endpoint, just a vertical video that says so. Privacy defaults to
    private, which is also what Google forces on unaudited projects, and a
    refused thumbnail is a warning, because the video is already up.

  • threads is the twelfth platform (841b4c5) (by yohimik, Claude Fable 5)
    The same Meta machinery Instagram taught crier: a container per page,
    a poll to FINISHED, one publish, and the bounded retry for the refusals
    proven to have created nothing. Threads adds two rules of its own: a
    carousel wants at least two items, so a single page posts as a plain
    image, and the token is a Threads token, which an Instagram token is
    not. Twenty pages to a carousel, captions ride as the post's text.

  • the release announces itself on linkedin too (16a46fd) (by yohimik, Claude Fable 5)
    The anthem clip is the announcement: a LinkedIn post takes one video or
    many images, never both, so the cover with its soundtrack carries the
    commentary and the changelog pages follow as a multi-image album. The
    commentary is written around what makes the post worth stopping for:
    the changelog came from the commits, and the render and the publish
    both happened inside the release run. No secrets, no post, no red
    release, as ever.

  • vk is the eleventh platform (a5e621e) (by yohimik, Claude Fable 5)
    A wall post is three borrowed steps: an upload slot from
    photos.getWallUploadServer, the bytes to that slot, and the
    server-photo-hash triple handed back through photos.saveWallPhoto.
    Pages become one post of up to ten attachments, a clip goes through
    video.save, and a GIF travels as a document, which is what VK calls
    one. The owner id's sign decides whose wall: negative is a community,
    posted as the community itself.

  • a twentieth probe to round the parade off at a number worth a page break of its own (0d89c31) (by yohimik, Claude Fable 5)
    A dogfooding probe for the paginated release card.

  • an eighteenth probe of comfortable two-line length, the kind most real subjects turn out to be (f1ef42a) (by yohimik, Claude Fable 5)
    A dogfooding probe for the paginated release card.

  • a sixteenth probe, generously proportioned in the manner of the eighth, invoking imaginary flags and fictitious platforms for no purpose but the three lines it will be given on the card (8297cdf) (by yohimik, Claude Fable 5)
    A dogfooding probe for the paginated release card.

  • the release renders its anthem once and leads with it (42ff389) (by yohimik, Claude Fable 5)
    The clip was rendered inside the story pass and existed only for that
    pass. It is now rendered first, on its own, to a temp file that outlives
    the step: crier render with the frames input and the audio, output to
    anthem.mp4.

    Both surfaces then use that one file. The feed pass passes it as
    --publish-instagram-lead-video, so the carousel opens with the fanfare
    before the cover card. The story pass publishes the same bytes with
    --publish-input, so the reel opens with it too and nothing is encoded
    twice. Order is unchanged: feed, anthem story, changelog stories.

    Rendering it f...

Read more

v1.0.0-rc.9

v1.0.0-rc.9 Pre-release
Pre-release

Choose a tag to compare

@github-actions github-actions released this 02 Sep 10:50

Fixes

  • a fitted platform reshapes the file it was handed (453b273) (by yohimik, Claude Fable 5)
    rc.8's anthem story was the square anthem.mp4 published with the story
    frame's flags. Publish-only mode passed the file through as it arrived,
    so the flags did nothing and Instagram padded the square to 9:16 on its
    own servers, in black rather than in the card's colour.

    Passing a file through is right for a format preference and wrong for a
    fit. A fit says what shape the platform is to receive; ignoring it hands
    the decision to the platform, which crops or pads without saying where
    the cut fell. So a platform that set one now gets the file reshaped: an
    image is resampled, a clip is re-encoded through the same filter a
    rendered clip is fitted with. The audio stream is copied rather than
    encoded again, because on this clip the soundtrack is the point.

    Those modes had one shared variant, on the grounds that overlays and
    render sizes are instructions to a renderer that is not running. A fit is
    not one of those, so they now group by frame alone: platforms that asked
    for nothing still share the file as it arrived, and two that asked for
    the same frame share one re-encode.

    The same gap in the frames-input path is closed with it, since the
    machinery was already there and unused: an encoded frames run and its
    poster are fitted like a rendered clip, so --render-variant previews the
    shape the platform will get.

  • number every page of a coverless card (8c9269d) (by yohimik, Claude Fable 5)
    The first-page rule that hides the small badge and the page counter is
    about page one being the cover, not about page one. The updates document
    has no cover, so its first page is the first changelog page, and the rule
    stripped its margin: rc.8's two-page story pair was numbered on the
    second page and nowhere else, and the first story never said which
    release it was.

    It is now emitted only when there is a cover. A coverless document also
    needs a source for the version string, since the only thing that sets it
    is the big badge the cover carries, so one is drawn with no height and no
    type: the small badge would otherwise be blank on every page rather than
    on the first.

    Both halves have a test. The rendered pages are read back and the two
    margin boxes are counted for ink, so a coverless page one has a badge and
    a counter, and a cover page one still has neither.

  • instagram wants media_type on a video carousel child (e6a7bad) (by yohimik, Claude Fable 5)
    rc.8's feed post failed with 400 IGApiException code 100, "The parameter
    image_url is required" (fbtrace A0MpoozUBsHxq-KQTcd9gcG). Without a
    media_type the API presumes the child is an image and asks for the
    parameter an image child would have.

    The reference lists CAROUSEL, REELS and STORIES for that parameter and
    omits VIDEO entirely, which is what the previous change read as an
    instruction to leave it out. The endpoint disagrees, and the endpoint is
    what posts. Behaviour wins; the docs now say so and cite the trace.

    Both Instagram fakes refuse a video child that omits it, answering with
    the message Meta answered with. Removing the parameter now fails the
    suite instead of passing it and failing a release.

Authors

  • yohimik
  • Claude Fable 5

Install

curl -fsSL https://raw.githubusercontent.com/yohimik/crier/v1.0.0-rc.9/install.sh | CRIER_VERSION=1.0.0-rc.9 sh
:CRIER_VERSION = '1.0.0-rc.9'
irm https://raw.githubusercontent.com/yohimik/crier/v1.0.0-rc.9/install.ps1 | iex
dispat install yohimik/crier

v1.0.0-rc.8

v1.0.0-rc.8 Pre-release
Pre-release

Choose a tag to compare

@github-actions github-actions released this 02 Sep 10:05

Features

  • a twentieth probe to round the parade off at a number worth a page break of its own (0d89c31) (by yohimik, Claude Fable 5)
    A dogfooding probe for the paginated release card.

  • an eighteenth probe of comfortable two-line length, the kind most real subjects turn out to be (f1ef42a) (by yohimik, Claude Fable 5)
    A dogfooding probe for the paginated release card.

  • a sixteenth probe, generously proportioned in the manner of the eighth, invoking imaginary flags and fictitious platforms for no purpose but the three lines it will be given on the card (8297cdf) (by yohimik, Claude Fable 5)
    A dogfooding probe for the paginated release card.

  • the release renders its anthem once and leads with it (42ff389) (by yohimik, Claude Fable 5)
    The clip was rendered inside the story pass and existed only for that
    pass. It is now rendered first, on its own, to a temp file that outlives
    the step: crier render with the frames input and the audio, output to
    anthem.mp4.

    Both surfaces then use that one file. The feed pass passes it as
    --publish-instagram-lead-video, so the carousel opens with the fanfare
    before the cover card. The story pass publishes the same bytes with
    --publish-input, so the reel opens with it too and nothing is encoded
    twice. Order is unchanged: feed, anthem story, changelog stories.

    Rendering it first is also what makes the feed pass able to lead with it,
    which is the point. Without ffmpeg, or when the render fails, anthem.mp4
    stays empty: the feed pass goes out with no lead video and the anthem
    story is skipped, which is the same thing the missing-ffmpeg path always
    did.

    This also carries the in-flight nocover work the tree was found with: the
    data document grows a nocover flag, the template honours it, and the
    story pass posts the changelog pages alone because the cover story is now
    the video. The two changes touch the same lines of announce.sh and could
    not be separated into two commits that both run.

  • the carousel and the album open with the clip (331ce8a) (by yohimik, Claude Fable 5)
    Instagram builds a video child first and lists it first in the parent.
    The child is video_url plus is_carousel_item and nothing else: media_type
    names a container kind, and its documented values are CAROUSEL, REELS and
    STORIES. VIDEO is no longer among them, and REELS is refused inside a
    carousel outright, so the kind is inferred from which URL was sent. Meta
    accepts no caption on a child either. Video children process
    asynchronously and the existing container wait already covers that, so
    the parent is not created until the clip says FINISHED.

    Telegram prepends an InputMediaVideo to the media group, which is the one
    Telegram shape that mixes a clip with photos. The caption belongs to the
    album's first item, so it travels with the clip and still appears under
    the album.

    A clip is one of the ten items on both, so a run that opens with one
    declares nine pages per post. The audio takes nothing away at Telegram:
    it is a message of its own, so an album can carry a lead video and the
    track after it. A story ignores the clip and says so, because a story has
    no carousel to open and one config file drives both passes.

  • a thirteenth probe, medium length, with just enough said to wrap once (1d177a5) (by yohimik, Claude Fable 5)
    A dogfooding probe for the paginated release card.

  • an eighth probe that describes an imaginary feature in the language of a real one, mentioning a configuration key that does not exist and a platform that never heard of it, purely to occupy three wrapped lines (37db480) (by yohimik, Claude Fable 5)
    A dogfooding probe for the paginated release card.

  • a seventh, short probe (c24eb86) (by yohimik, Claude Fable 5)
    A dogfooding probe for the paginated release card.

  • a sixth probe about nothing at all, phrased the way changelog entries actually arrive, with a clause after the comma that pushes it past the width of one line (89d2baf) (by yohimik, Claude Fable 5)
    A dogfooding probe for the paginated release card.

  • a fifth probe, whose subject settles in at around one hundred and sixty characters so that it reliably wraps to a second line and reaches toward a third on the card (81d9ee7) (by yohimik, Claude Fable 5)
    A dogfooding probe for the paginated release card.

  • a post can name the clip that opens it (7157208) (by yohimik, Claude Fable 5)
    publish..lead-video, on the same terms as music-file: the key
    exists for all ten platforms, and the eight that cannot post mixed media
    are answered by Validate with the reason rather than by the decoder with
    an unknown-key error.

    Two platforms can. An Instagram feed carousel takes video children beside
    image children. A Telegram media group mixes InputMediaPhoto and
    InputMediaVideo in one array. Everywhere else a post is pictures or it is
    a video, and no arrangement of API calls makes it both.

    There is no shared key to fall back to, unlike the audio. A clip that
    opens a post is part of that post's composition rather than a decoration
    applied to every surface, and the two that take one want different shapes
    of it often enough that naming it twice is the honest spelling.

Fixes

  • a nineteenth probe that wraps twice by design, padding its clause with qualifiers the way release notes do when nobody edits them down before the tag (70a545d) (by yohimik, Claude Fable 5)
    A dogfooding probe for the paginated release card.

  • a seventeenth probe recounting, in the past tense and with unnecessary chronology, the discovery of a bug that never existed and the weekend that was never lost to it (d7daa57) (by yohimik, Claude Fable 5)
    A dogfooding probe for the paginated release card.

  • a fifteenth probe that closes the parade at a length calculated to wrap twice, so the last page of the card has some weight to carry as well (4a13cbf) (by yohimik, Claude Fable 5)
    A dogfooding probe for the paginated release card.

  • a fourteenth probe, one word longer than the tenth (cb715ab) (by yohimik, Claude Fable 5)
    A dogfooding probe for the paginated release card.

  • a twelfth probe whose subject would have been two sentences anywhere else, joined here by a comma because commit subjects have no full stops to spare, and stretched to guarantee its third line (d7a6667) (by yohimik, Claude Fable 5)
    A dogfooding probe for the paginated release card.

  • an eleventh probe carrying a middling subject that lands almost exactly on the wrap boundary of the card face (e5f1211) (by yohimik, Claude Fable 5)
    A dogfooding probe for the paginated release card.

  • a tenth probe, terse (4fc6440) (by yohimik, Claude Fable 5)
    A dogfooding probe for the paginated release card.

  • a ninth probe fixing nothing, at length: the sort of subject where the author explains the symptom, the cause and the cure all before the colon has any right to expect them (20a5e0f) (by yohimik, Claude Fable 5)
    A dogfooding probe for the paginated release card.

Authors

  • yohimik
  • Claude Fable 5

Install

curl -fsSL https://raw.githubusercontent.com/yohimik/crier/v1.0.0-rc.8/install.sh | CRIER_VERSION=1.0.0-rc.8 sh
:CRIER_VERSION = '1.0.0-rc.8'
irm https://raw.githubusercontent.com/yohimik/crier/v1.0.0-rc.8/install.ps1 | iex
dispat install yohimik/crier

v1.0.0-rc.7

v1.0.0-rc.7 Pre-release
Pre-release

Choose a tag to compare

@github-actions github-actions released this 02 Sep 08:37

Features

  • a fourth probe that stands in for the release notes nobody plans: written in one breath, trailing detail after detail, the kind of subject that a reviewer asks to be split and the author promises to split next time and never does (253da0d) (by yohimik, Claude Fable 5)

  • a probe whose subject describes, at deliberate and unhurried length, the way a paginated release card lets every one of these words survive onto the page where a single-line card would have cut them at the first ellipsis (5acbc6d) (by yohimik, Claude Fable 5)
    A dogfooding probe: this subject and its siblings exist so the next
    release candidate's card shows long entries wrapping to their full three
    lines and pushing one another across page after page.

Fixes

  • a third probe, short (372329b) (by yohimik, Claude Fable 5)

  • a second probe, briefer than the first but still comfortably past the width of one card line, so the wrapped entries alternate with the short ones on the pages (3d18235) (by yohimik, Claude Fable 5)

  • a long entry wraps instead of losing its ending (dd5445e) (by yohimik, Claude Fable 5)
    One line per entry was the single-page card's economy. A paginated card
    can afford the truth: up to three lines each, then the multi-line clamp,
    and an unbroken run breaks anywhere rather than escaping. A long entry
    costing three lines is what pushes its neighbours onto the next page,
    which is the point of having pages.

Authors

  • yohimik
  • Claude Fable 5

Install

curl -fsSL https://raw.githubusercontent.com/yohimik/crier/v1.0.0-rc.7/install.sh | CRIER_VERSION=1.0.0-rc.7 sh
:CRIER_VERSION = '1.0.0-rc.7'
irm https://raw.githubusercontent.com/yohimik/crier/v1.0.0-rc.7/install.ps1 | iex
dispat install yohimik/crier

v1.0.0-rc.6

v1.0.0-rc.6 Pre-release
Pre-release

Choose a tag to compare

@github-actions github-actions released this 02 Sep 08:20

Fixes

  • Meta's second costume for the same race, and ffmpeg for the runner (3c95025) (by yohimik, Claude Fable 5)
    The rc.5 story died on error 24, Media Not Found: the container this
    process created and polled FINISHED seconds earlier did not exist at
    the publish endpoint for a moment. A container that does not exist
    published nothing, so it joins 9007 in the ask-again matcher — and one
    genuinely gone spends the budget and surfaces the same error.

    The anthem skipped for a plainer reason: the runner image carries no
    ffmpeg. The release job now installs it when the announce secrets are
    present.

Authors

  • yohimik
  • Claude Fable 5

Install

curl -fsSL https://raw.githubusercontent.com/yohimik/crier/v1.0.0-rc.6/install.sh | CRIER_VERSION=1.0.0-rc.6 sh
:CRIER_VERSION = '1.0.0-rc.6'
irm https://raw.githubusercontent.com/yohimik/crier/v1.0.0-rc.6/install.ps1 | iex
dispat install yohimik/crier

v1.0.0-rc.5

v1.0.0-rc.5 Pre-release
Pre-release

Choose a tag to compare

@github-actions github-actions released this 02 Sep 08:04

Features

  • the release opens its story with a fanfare (a5d3b9f) (by yohimik, Claude Fable 5)
    A third announce pass: the cover page held for sixteen seconds as a
    video story, with sixteen seconds of the 1812 Overture finale as its
    soundtrack — a public-domain recording by the United States Marine Band,
    provenance in announce/anthem.md. Video is the one way audio reaches
    Instagram, which takes no audio file and no track id. The cover renders
    once and is copied into frames: 384 identical layouts would cost
    minutes, one copied 384 times costs a second.

  • ping checks the audio file, and publish says when nothing carries it (79b8393) (by yohimik, Claude Fable 5)
    A row per configured music file: the file is there, it can be read, and
    its first bytes are one of the four containers crier sends. The extension
    is not consulted, because an image renamed to .mp3 is accepted by the
    file system and refused by the platform, after the post.

    The rows come before the publishers are built, since building one refuses
    a file that is not audio — a check that ran after the build would never
    be reached by the configuration it exists to explain.

    A file no enabled platform can carry is a success with a note rather than
    a failure. The file is fine. Publishing warns about the same finding, so
    a run that enables Instagram and X and names a jingle says out loud that
    the jingle is going nowhere.

  • three platforms carry the audio, each its own way (4668bee) (by yohimik, Claude Fable 5)
    Discord and Slack put the track in the same message as the pictures.
    Discord takes it as another files[n] part; Slack gives it an upload slot
    like any other file, and step three shares them together, which is what
    makes them one message.

    The audio takes one of the message's file slots, so both declare one
    fewer page per post when music is configured. Reserving the slot is what
    lets a long document paginate into messages that fit, rather than into a
    message the platform refuses.

    Telegram cannot do that. The Bot API groups audio only with audio, so a
    track cannot join the album it belongs to. It goes out as its own
    message, immediately after, in the same chat, which is what clients
    render as a player under the pictures. That message failing is a warning
    rather than a failure: the post is already out, and saying the platform
    failed would be untrue.

    TikTok gets auto_add_music in post_info for a photo direct post. It is
    the only music setting any of these APIs offers, and it names no track.

  • the configuration can name an audio file (96b28ae) (by yohimik, Claude Fable 5)
    publish.music-file names one audio file for the whole run, and
    publish..music-file overrides it for one platform. Both anchor
    to the config file the way every other path key does.

    The per-platform key exists for all ten platforms rather than only for
    the three whose API can carry audio. A key that simply did not exist for
    Instagram would answer "can I attach a track here" with an unknown-key
    error, which reads like a typo; the key exists, its reference row says it
    is not available, and a value in it is refused with the reason. Only
    Discord, Slack and Telegram have an endpoint that takes an audio file at
    all.

    publish.tiktok.auto-add-music comes along beside it. It is the one music
    setting any of these APIs offers, and it names no track: TikTok picks
    one.

  • WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW (23fc4a2) (by yohimik, Claude Fable 5)
    A deliberate hostile-changelog probe, and nothing else: this subject is
    a hundred unbroken copies of the widest glyph the card's face carries,
    here so the next release candidate has to ellipsise it on its own card,
    in production, where the smoke suite's copy of the same monster already
    passes. A changelog is what people wrote; the card has to survive that.

Fixes

  • ask again where a refusal created nothing (5469a24) (by yohimik, Claude Fable 5)
    Three platforms share Instagram's race between media processed and media
    usable, and each now gets the treatment its own API earns:

    • Mastodon refuses a status whose attachment is still processing with a
      422 raised before any status exists; it is retried within the poll
      budget. The message is localized per account, so a non-English
      instance falls back to the never-repeat rule, which is the safe
      direction to miss in.
    • X answers a not-yet-consistent media id with the same 400 it uses for
      a genuinely wrong one, and neither creates a tweet; the bounded retry
      costs a permanent mistake the poll budget and then surfaces it
      unchanged. Two new keys carry the budget.
    • LinkedIn is the dangerous one: the post can be accepted with 201, sit
      in PUBLISH_REQUESTED, and end PUBLISH_FAILED with nothing visible and
      no error on any call crier made. Images now wait for AVAILABLE before
      the post, the way videos always did.
    • Reddit is the inverse and gets no retry at all: its failure signal can
      arrive for a post that was nonetheless created.
    • Slack blocks until ingestion finishes; TikTok fails inside its own
      polled flow; Facebook photos are synchronous. Nothing to do on any of
      the three.

Authors

  • yohimik
  • Claude Fable 5

Install

curl -fsSL https://raw.githubusercontent.com/yohimik/crier/v1.0.0-rc.5/install.sh | CRIER_VERSION=1.0.0-rc.5 sh
:CRIER_VERSION = '1.0.0-rc.5'
irm https://raw.githubusercontent.com/yohimik/crier/v1.0.0-rc.5/install.ps1 | iex
dispat install yohimik/crier

v1.0.0-rc.4

v1.0.0-rc.4 Pre-release
Pre-release

Choose a tag to compare

@github-actions github-actions released this 02 Sep 06:47

Fixes

  • green padding between the text and the page margin (13d5a50) (by yohimik, Claude Fable 5)
    Type sat flush against the white frame on every page. The panel now
    extends past the text, and the cover height subtracts the padding it
    gained.

  • ask again when Instagram says the media is not ready (8dc5170) (by yohimik, Claude Fable 5)
    A container can poll FINISHED while Meta is still making the media
    publishable, and media_publish then answers error 9007, media not
    available. That refusal means no post was created, so it is the one
    publish failure that is safe to retry, bounded by the poll budget. Seen
    on the rc.3 release: the carousel published and the first story,
    seconds behind it, was told to wait a moment. Every other publish
    failure keeps the never-repeat rule.

Authors

  • yohimik
  • Claude Fable 5

Install

curl -fsSL https://raw.githubusercontent.com/yohimik/crier/v1.0.0-rc.4/install.sh | CRIER_VERSION=1.0.0-rc.4 sh
:CRIER_VERSION = '1.0.0-rc.4'
irm https://raw.githubusercontent.com/yohimik/crier/v1.0.0-rc.4/install.ps1 | iex
dispat install yohimik/crier

v1.0.0-rc.3

v1.0.0-rc.3 Pre-release
Pre-release

Choose a tag to compare

@github-actions github-actions released this 02 Sep 06:24

Features

  • the release announces itself as a carousel (34535f2) (by yohimik, Claude Fable 5)
    The card was one page, and a changelog was cut to two or three entries a
    section to make it fit. That was the constraint the whole card was designed
    around, and it is gone.

    Page one is the cover: the version badge a thumbnail has to carry, the lede,
    and the three install routes pinned to the bottom edge. The changelog carries
    on across the pages after it, under a small version badge and a footer that
    numbers the page. Both are drawn in the page margins, so they repeat without
    being written into the flow, and the first page suppresses them because it
    carries its own badge and because "1 / 1" on a short release says nothing.

    Each pass turns those pages into what its surface takes. The feed post is one
    carousel. The story pass posts one story per page, in order, each live before
    the next is created. Neither is a flag: crier works it out from the platform.
    Stories have no cover-page opt-out — announcing a release without saying what
    is in it is not a saving worth making.

    notes.sh keeps a ceiling of twenty entries a section, which is a guard against
    absurdity rather than a design constraint: past it the render would exceed
    render.pages-max and be refused outright, and a release with sixty entries in
    one section is not one anybody reads to the end of.

    The end-to-end test now asserts the whole shape against a fake Graph API: a
    child container per page, one parent listing them in order, one publish, and
    then a story per page. The committed preview is both pages.

  • the last three platforms, and where each number came from (1ddab98) (by yohimik, Claude Fable 5)
    LinkedIn takes two to twenty as a multi-image post. One image is a different
    shape entirely — content.media rather than content.multiImage, and a
    multiImage of one is refused — so the shape follows the batch size rather than
    a flag. TikTok's photo post was already a list of URLs, so several pages are
    more entries in the request it always sent, up to the documented thirty-five.

    Reddit stays at one file per post on purpose. It has galleries, but the only
    way to make one is an endpoint Reddit's own web client uses and Reddit
    documents nowhere, with no published limit and no promise it keeps working.
    Several ordinary posts that will still be there next month beat one gallery
    built on that.

    The numbers are now sorted into the ones a platform documents and the ones
    crier chose. Instagram's ten, Telegram's two-to-ten, x's four, LinkedIn's
    twenty and TikTok's thirty-five are the platform's own words. Facebook,
    Discord and Slack document the mechanism and no limit on it, so ten is crier's
    ceiling rather than theirs, and the comments say so. Mastodon's four is the
    instance's, advertised as max_media_attachments and merely defaulted to four,
    so crier assumes the conservative number.

    One test lists every capacity with the source of each, so a number that
    changes without that list changing is a post that would silently start
    splitting.

  • the platforms that take several files now do (21f8ef6) (by yohimik, Claude Fable 5)
    Seven of the ten accept more than one file in a post, and each does it
    differently. Every one of them keeps the page order.

    Instagram builds a carousel: a child container per image, a parent that lists
    them, one publish. The caption belongs to the parent, which is what makes a
    five-page changelog one entry in the feed rather than five. Stories have no
    carousel at all, so a story run stays at one file and becomes one story per
    page, published in order.

    Facebook uploads each photo unpublished and attaches the ids to one feed post.
    Telegram sends a media group, with the caption on the first item because
    Telegram shows an album's caption once; a batch of one still goes through
    sendPhoto, since a media group has a minimum of two. x and Mastodon upload in
    page order and list the ids. Discord numbers its file parts. Slack uploads each
    file and shares the lot in one completeUploadExternal, which is what makes them
    one message.

    A custom platform gets CRIER_ARTIFACTS and CRIER_URLS, one path per line
    because a path may contain a space, plus a count and the post and page numbers.
    Its capacity is whatever max-attachments says, since the command is the
    platform and there is no API here to know better.

    The e2e suite proves the three shapes against the fakes: sequential stories,
    one carousel, and a four-cap split. One scenario runs all three platforms
    together and asserts each saw the same five pages in the same order. It is in
    the smoke subset, so the release build proves it against the shipped bytes.

    LinkedIn, Reddit and TikTok still take one file each. They follow.

  • a page list becomes a sequence of posts (e1754f0) (by yohimik, Claude Fable 5)
    The run has one ordered page list. Every platform receives it whole, in order,
    and the only thing a platform may do to it is cut it into the sizes it accepts.
    Nothing reorders, skips, merges or dedupes pages. That is what makes a carousel
    at one platform and a run of single posts at another tell the same story in the
    same sequence.

    Needs.MaxAttachments declares how many files a platform takes in one post, with
    zero read as one. Every platform still declares one, so today a five-page
    document is five posts everywhere; raising the numbers and implementing the
    multi-file calls is the next commit. publish..max-attachments lowers
    it, and only lowers it: asking a platform for more than it takes would only be
    refused by the platform, which is a worse way to find out.

    A platform's posts go out one at a time, each finished before the next begins.
    That is not caution. Several platforms order a feed by when a post completed,
    so publishing two of one sequence at once is how a two-part post turns up back
    to front. A post that fails stops the ones after it and the outcome says how
    far it got: a gap in the middle of a sequence is worse than a short sequence,
    because a reader cannot tell it happened. Platforms still run alongside each
    other; the sequencing is within one.

    Captions are rendered once per post rather than once per run, with .Post,
    .Posts, .Page and .Pages bound, so one line of configuration can write "2 of
    3". They read 1 of 1 when nothing paginated, so a caption that mentions them is
    safe to write either way.

  • keep every page a document lays out into (8c35002) (by yohimik, Claude Fable 5)
    Laying out was always producing pages. crier kept the first and refused the
    rest, so a changelog too long for one card was an error telling you to shorten
    it.

    It is a post now. A run produces one ordered page list, and that list is what
    every platform receives: same pages, same order, everywhere. The fit is applied
    per page, so a carousel is a set of pictures the same shape rather than one
    fitted picture and four that were not. Staging gives each page an address of
    its own, because a platform that fetches by URL fetches every page.

    render.pages-max, default 10, refuses a document past it. The check runs after
    the layout, since the count is not knowable until the content has flowed: a
    template with a loop that never ends fails here rather than at the platform,
    which would have taken the first ten and said nothing about the rest. The hard
    ceiling is 20, above every platform's own carousel limit bar Reddit's.

    A document that still fits on one page produces one page with the file name it
    always had, so nothing downstream has to learn about pagination to keep
    working. crier render writes the whole set, numbered when there is more than
    one.

    Nothing publishes more than one page yet. That is the next commit.

Fixes

  • the page margin is the template's to choose (fdd258c) (by yohimik, Claude Fable 5)
    crier appended its page rule after the document's own styles, and that rule
    carried two declarations: the size and a zero margin. The size belongs there.
    Putting it last is what makes --render-width win over a rule the template
    happens to carry.

    The margin did not belong there. Appended last it overruled whatever margin the
    template asked for, and a page's margin boxes draw in the page margin. With the
    margin forced to zero they had no room: a running header and footer came out
    clipped to a sliver, straddling the page edge. A paginated template could not
    have worked, which is why this surfaced while verifying paged media at all.

    The rule is split across the document now. The margin goes first, as a default
    a template can overrule. The size still goes last, where it cannot be. A
    template that says nothing still gets an edge-to-edge page, because that is
    what a social image is.

    Verified through the raster backend: page margin boxes paint, the page counters
    resolve, the first-page selector picks page one, running headers from content
    work, and a card that would straddle a page break moves whole. A three-page
    golden pins the lot.

Authors

  • yohimik
  • Claude Fable 5

Install

curl -fsSL https://raw.githubusercontent.com/yohimik/crier/v1.0.0-rc.3/install.sh | CRIER_VERSION=1.0.0-rc.3 sh
:CRIER_VERSION = '1.0.0-rc.3'
irm https://raw.githubusercontent.com/yohimik/crier/v1.0.0-rc.3/install.ps1 | iex
dispat install yohimik/crier