release-and-metadata

A set of project instructions for checking app icons, release notes, and app-store listing text before committing changes. It describes automated checks for required fields, character limits, line endings, control characters, and allowed text scripts.

In plain words
What is it for?
Use it when changing release notes or store metadata, maintaining localized listings, checking character limits, and keeping local checks consistent with the release process.
Why use it?
App-store submissions can fail because text is missing, too long, incorrectly shared between platforms, or contains unsupported characters. These instructions help catch those problems during development and continuous integration.

Agent

Install

Getting it into your agent

One page per mod, every tool's command on it. A separate URL per tool would split the same page into five that compete with each other.

agentmods
npx agentmods add agents/multiplex-term/multiplex/release-and-metadata
Clone the repo
git clone --depth 1 https://github.com/multiplex-term/Multiplex
Per session 0 Only the description is in the session, so the agent can decide to use it. The body loads when it is invoked.
When invoked 2,065 The whole file, excluding the scripts and references it only reads on demand.
Security scan A 0 findings. Scan, not verified.
Origin original No closer match found in the catalogue.
Token cost

What it costs to keep this loaded

Counted locally with the o200k_base tokenizer, which is exact for GPT models; Claude uses its own tokenizer and its counts differ. Treat this as one consistent yardstick across the catalogue rather than a bill. Prices are per million input tokens.

ModelPer sessionOnce invoked
Fable 5 $0.00000 $0.02065
Opus 5 $0.00000 $0.01033
Sonnet 5 $0.00000 $0.00413
Haiku 4.5 $0.00000 $0.00206

Measured yesterday against content hash 70ad7dc781b0, method: parsed. Prices are Anthropic first-party input rates as of 2026-08-30, from the pricing page.

Security

Grade A, and why

release-and-metadata scanned grade A with 0 findings against 26 rules in 11 categories — prompt injection, anti-refusal, data exfiltration, privilege escalation, supply chain, agent snooping, system-prompt leakage, SSRF and excessive agency — measured yesterday.

A static scan of the body, not an audit. Every finding is printed with the line that produced it so you can judge whether it matters here. A mod is markdown that instructs an agent; that is exactly why what it instructs is worth reading.

Nothing flagged

None of the 26 patterns this scan looks for appear in this file: no shell pipes, no recursive deletes, no credential paths, no hidden text, no instruction-override or anti-refusal phrasing, no agent-config snooping. That is not a guarantee, it is the absence of the things that are checkable.

docs/agents/release-and-metadata.md · 127 lines

How it starts

The opening of the file, as written. The whole thing — 127 lines — stays where its author put it; the contents beside it link to each section on GitHub.

Release surfaces: app icon, release notes, store metadata

Split from AGENTS.md — read before committing any user-visible change.

ruby Tools/check-metadata.rb is the mechanical half of this document, and CI's Linux job runs it on every push. It reads fastlane/testflight-whats-new.txt and fastlane/metadata/, and fails on: a field over its App Store Connect cap (measured in CHARACTERS — this copy's dashes and arrows run its byte length several hundred higher), an empty or missing field, a shared description.txt / release_notes.txt breaking the platform split, CRLF, control characters, and any non-ASCII glyph not vetted in Tools/metadata_limits.rb. That last rule is the ⟨…⟩ incident: the changelog looked right in every editor and App Store Connect refused the character. The caps live in that one file, required by fastlane/Fastfile too, so the lane that fails an archive and the job that fails a pull request can never disagree. Add a glyph to the allowlist only after an upload has actually accepted it. Localized listings (fastlane/metadata/zh-Hant, ja — every en-US file mirrored, same caps) are allowed their whole scripts by Unicode block (MetadataLimits::SCRIPT_RANGES: ideographs, kana, bopomofo, CJK punctuation, full-width forms) instead of glyph-by-glyph; en-US and the TestFlight changelog stay glyph-strict, and the changelog stays English. When en-US copy changes, change the two mirrors in the same PR (glossary in i18n.md; run zhtw-mcp lint over the zh-Hant files).

  • App icon is a hand-authored Icon Composer package (AppIcon.icon; spec + bake-off in DESIGN.md); icon.json lists groups frontmost-first. Validate headlessly with xcrun actool AppIcon.icon --compile <dir> --platform iphonesimulator --minimum-deployment-target 17.0 --app-icon AppIcon --output-partial-info-plist <dir>/p.plist — zero warnings today; the emitted PNGs are the flattened pre-26 fallbacks. Icon Composer has no visionOS target, so Assets.xcassets/AppIcon.solidimagestack is baked, not hand-drawn: swift Tools/bake-vision-icon.swift renders with Icon Composer's own ictool and unblends the layers, verifying the restack recomposites the reference (≤0.5/255). Never edit the three layer PNGs by hand — edit AppIcon.icon and re-bake. Keep the artwork SVGs to filled paths — no stroke. Icon Composer's importer closes an open stroked path, and the iOS 26 design generation draws that phantom closing segment as a grey hairline. The V used to be a stroked <polyline>, so a line ran across the M's counter — invisible in Icon Composer's preview, on device, and in every default (generation 27) render, and visible only where the 26 generation is rendered: App Store Connect and the App Store product page. Fixed by outlining the stroke into a fill; caps and the mitered apex are spelled out in carrier.svg. Check both generations when the artwork changes — ictool inside Icon Composer.app/Contents/Executables takes --design-generation 26|27, and a background row through the counter (y≈310, x 400–620 at 1024) must read the fill's ~24/255, not ~108.
  • The release notes are one content model with two renderings, and the launch card is priced like the interruption it is (ReleaseNotes pure + tested; WhatsNewViewController / ReleaseLogViewController; ReleaseNotesStore). The card shows up to FOUR changes (a patch release shows what it has — 1.4.1 is three rows on an iPhone), no navigation bar, and ends inside one phone screen; FULL NOTES and Settings ▸ About ▸ What's New both open the full banked record — ReleaseNotes.releases, every release newest first, so a reader updating across two releases misses neither. The card speaks only for the newest release. Bake-off record: the log alone was dismissed at the fold, the card alone left eight changes unread, so each absorbs the other's failure. Load-bearing details:
    • A missing stamp is not a first run. Every device updating from a version that never wrote one has lastSeenVersion == nil, so ReleaseNotesGate takes installHasPriorUse (the deck answers it with its locally cached host list) to tell "updated" from "installed today". Reading nil as new silences the notes for exactly the people they are for; reading it as updated shows a changelog to someone meeting the app. Pinned by ReleaseNotesTests + DeckWindowUIKitTests.
    • Once per NOTES release: ReleaseNotes.version advancing at any component reopens the card (1.3 → 1.3.1 did, because 1.3.1 wrote notes of its own); a patch build that leaves the constant alone compares equal and stays silent. Stamped on presentation rather than dismissal (a force-quit mid-animation must not make it recurring), and device-local UserDefaults — updating on iPad must not consume the notice on Vision Pro, so it never rides the synced Host record.
    • ReleaseNotes.version is the notes' own release, not the bundle's short version: a patch build must not present itself as a release with its own notes.
    • Entries and highlights are platform-filtered the way TerminalGuide.entries(for:) is — GLASS never reaches an iPad, keep-alive never a Vision Pro — and each platform's FOURTH card row is whichever change is about it. The card's "also in 1.3" line is DERIVED from the entries no shown highlight covers, so it can never re-offer something the card just said or miscount the rest.
    • It rides the deck's presentation queue as its own PresentationKind, so it waits behind the app-lock veil; it defers while ExternalActionRouter.hasPendingActions (a widget deep link asked for something specific), and it needs real deck width — the compact shell clips its deck pane to zero, and a later layout pass retries. FULL NOTES supersedes the card rather than stacking a second sheet, the same reason the licenses page is its own modal.

Read the full file on GitHub · 127 lines

Changes

What this file has done since we first saw it

Hashed on every crawl. A supply-chain change to an agent config is a question of when, not whether, so the history is kept rather than the latest state alone.

  1. yesterday First seen · 127 lines · 0 tokens per session scan A 70ad7dc781b0

Subscribe to this mod's changes

release-and-metadata is an agent published in the GitHub repository multiplex-term/Multiplex (10 stars, last pushed 5d ago), licensed Apache-2.0. It costs nothing until one of its globs matches a file; then it loads 2,065 tokens. A static security scan graded it A with 0 findings. No closer match exists in the catalogue, so it is treated as the original; first seen 2026-08-31.

Related

Other agents, from other repositories

i18n

Hermex ships one String Catalog, HermesMobile/Resources/Localizable.xcstrings, included in the app, widget, and share-extension targets. Every user-facing literal is already externalized (String(localized:) / LocalizedStringKey), so adding a language is normally translation-only — no Swift edits.

uzairansaruzi/hermex · 0 tokens

Localization Audit

Audits localization completeness: finds hardcoded strings, missing XText keys, unused keys, and naming violations.

tqtuan1201/TTBaseUIKit · 24 tokens

feature-gap-index

Thin, always-current classification of upstream Hermes-WebUI API route groups against Hermes-Mobile. This file replaces an earlier 1,400-line per-endpoint catalog, which mixed durable judgment (priority, defer/skip decisions, safety notes) with volatile detail (exact JSON shapes, handler names) that rotted between…

uzairansaruzi/hermex · 0 tokens

issue-tracker

Issues and PRDs for this repo live as GitHub issues. Use the gh CLI for issue operations.

uzairansaruzi/hermex · 0 tokens

layer3-issue-detection

Layer 3 systematically scans ALL entry points from Layer 1 and applies issue detection rules. Unlike Layer 2 (which traces specific flows in depth), Layer 3 does a breadth-first scan to categorize issues across the entire codebase.

Terryc21/workflow-audit · 0 tokens

layer5-data-wiring

Layer 5 verifies that features use real user data instead of mock/hardcoded values, and that model capabilities are fully wired into the features that need them. While Layers 1-4 audit navigation and UX, Layer 5 audits whether the data flowing through those workflows is genuine.

Terryc21/workflow-audit · 0 tokens