<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Foundry</title>
    <description>The latest articles on DEV Community by Foundry (@runfoundry).</description>
    <link>https://dev.to/runfoundry</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4177838%2F24fc194d-349b-4b48-8d45-449d035057ab.png</url>
      <title>DEV Community: Foundry</title>
      <link>https://dev.to/runfoundry</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/runfoundry"/>
    <language>en</language>
    <item>
      <title>We tested 13 variables on 1,398 short videos. The one that zeroed our Instagram reach was the repeat.</title>
      <dc:creator>Foundry</dc:creator>
      <pubDate>Thu, 15 Oct 2026 13:41:54 +0000</pubDate>
      <link>https://dev.to/runfoundry/we-tested-13-variables-on-1398-short-videos-the-one-that-zeroed-our-instagram-reach-was-the-1j0e</link>
      <guid>https://dev.to/runfoundry/we-tested-13-variables-on-1398-short-videos-the-one-that-zeroed-our-instagram-reach-was-the-1j0e</guid>
      <description>&lt;p&gt;&lt;em&gt;Disclosure: I'm on the team that builds Foundry, the tool these posts went out through. The numbers are from our own accounts; the link is at the bottom.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;We post short clips of debates to Instagram, TikTok and YouTube Shorts from our own iPhones. Between Aug 31 and Oct 12 that was 1,398 posts with a view count we could read. By early October our Instagram had a problem: more and more posts were stopping at 10 views or fewer, and a few were stopping at zero.&lt;/p&gt;

&lt;p&gt;The usual suspects are posting time, hashtags, account age, video length, captions. We tested all of those and a few more, and most of them did almost nothing. One variable stood far above the rest.&lt;/p&gt;

&lt;h2&gt;
  
  
  How we measured
&lt;/h2&gt;

&lt;p&gt;For each post we kept the platform, the account, the hour, the clip, the source video and its view count. Two outcomes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;a zero:&lt;/strong&gt; 10 views or fewer&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;a hit:&lt;/strong&gt; 1,000 views or more&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Then 13 variables: posting time, spacing from the account's last post, account age, first frame (letterboxed or full frame), first-second loudness, length, caption template, hashtag count, whether the upload was the original file or a re-encode, where the clip came from, how many accounts share the phone, and two about repeats.&lt;/p&gt;

&lt;p&gt;Comparing raw numbers across weeks lies to you, because the weeks were different (our content mix changed a lot). So every comparison is made &lt;strong&gt;inside the same week&lt;/strong&gt; and combined with a Mantel-Haenszel ratio: how much more likely is a zero (or a hit) in group A than group B, holding the week fixed.&lt;/p&gt;

&lt;h2&gt;
  
  
  What didn't matter much
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Hashtag count:&lt;/strong&gt; a ratio of 1.0. Nothing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Posting time:&lt;/strong&gt; Instagram medians for the four time blocks sat between 147 and 181 views.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Caption template, length, first-second loudness, spacing between posts, where the clip came from, account age:&lt;/strong&gt; ratios between 1.3 and 1.8, next to 4 to 5 for the repeat.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;How many accounts share a phone:&lt;/strong&gt; it ran the wrong way for a fix. Instagram accounts sharing a phone with two or more others hit 1,000 views more often, not less.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you have been tuning posting times, this was the least useful lever in our data.&lt;/p&gt;

&lt;p&gt;The one real second-order effect was the &lt;strong&gt;first frame&lt;/strong&gt;. On Instagram, clips that opened letterboxed (black bars above and below) stopped at 10 views or fewer 26% of the time, against 10% for clips that opened full frame. Inside the same weeks, full frame roughly halved the chance of a zero. Worth fixing, but it was not the main story.&lt;/p&gt;

&lt;h2&gt;
  
  
  The one that mattered: the same debate, posted again on the same platform
&lt;/h2&gt;

&lt;p&gt;A "repeat" here means the same source debate going out again on the same platform, even as a different cut or with a different caption, on the same or a different account.&lt;/p&gt;

&lt;p&gt;Instagram, by how many times that debate had already gone out there:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Time on Instagram&lt;/th&gt;
&lt;th&gt;Posts&lt;/th&gt;
&lt;th&gt;Median views&lt;/th&gt;
&lt;th&gt;Share at 10 views or fewer&lt;/th&gt;
&lt;th&gt;Hits (1k+)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1st&lt;/td&gt;
&lt;td&gt;386&lt;/td&gt;
&lt;td&gt;196&lt;/td&gt;
&lt;td&gt;3%&lt;/td&gt;
&lt;td&gt;6.0%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2nd&lt;/td&gt;
&lt;td&gt;184&lt;/td&gt;
&lt;td&gt;153&lt;/td&gt;
&lt;td&gt;20%&lt;/td&gt;
&lt;td&gt;2.7%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3rd to 5th&lt;/td&gt;
&lt;td&gt;147&lt;/td&gt;
&lt;td&gt;137&lt;/td&gt;
&lt;td&gt;28%&lt;/td&gt;
&lt;td&gt;0%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;6th or more&lt;/td&gt;
&lt;td&gt;58&lt;/td&gt;
&lt;td&gt;129&lt;/td&gt;
&lt;td&gt;31%&lt;/td&gt;
&lt;td&gt;0%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;A first post zeroed 3% of the time. A second one, 20%. A third or later post on Instagram hit 1,000 views &lt;strong&gt;zero times out of 205.&lt;/strong&gt; And of the 101 Instagram zeros since Sept 28, 92% were repeats.&lt;/p&gt;

&lt;p&gt;Waiting doesn't fix it. A debate going out again on Instagram after 14 days or more still zeroed 29% of the time, against 3% for a first post. Whatever Instagram is matching on, it remembers for longer than two weeks.&lt;/p&gt;

&lt;h2&gt;
  
  
  YouTube is the exception
&lt;/h2&gt;

&lt;p&gt;On YouTube Shorts, posts going out a 3rd to 5th time still hit 1,000 views half the time (12 of 24). Our YouTube numbers are better across the board (median 666 views against 165 on Instagram), so a rule that holds on one platform can be the wrong rule on another. We now cap repeats on Instagram only and leave YouTube alone.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why it crept up on us
&lt;/h2&gt;

&lt;p&gt;The repeat wasn't a choice. It was supply. In the week of Aug 31, 84% of our Instagram posts were debates Instagram had never seen. By the week of Oct 5 it was 25%. The posting side kept filling every slot on time, and when there was nothing new to fill them with, it reached for clips that had already gone out. Every individual post looked fine. The schedule looked full. The reach quietly fell.&lt;/p&gt;

&lt;p&gt;That's the trap with any automated posting setup: a scheduler optimizes for "a post went out", and nothing in that metric tells you the post was a duplicate the platform has already judged.&lt;/p&gt;

&lt;h2&gt;
  
  
  What we changed
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Fresh first, on every platform.&lt;/strong&gt; When choosing what fills a slot, a debate the platform has never seen ranks ahead of everything else, always.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Instagram gets at most two posts of any debate.&lt;/strong&gt; A third one is held instead of posted, with the reason written down ("repeat clip"), so an empty slot shows up as an empty slot instead of a quiet zero.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The fix for reach is new source material, not settings.&lt;/strong&gt; No posting-time or hashtag change was going to move this. More fresh debates will.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  What we're still watching
&lt;/h2&gt;

&lt;p&gt;The biggest raw ratio in the whole table was the upload file: the original file vs a copy our renderer re-encoded, on TikTok. We haven't counted it as proven. Most of the difference falls in a single week, and our newer files don't carry the encoder tag we would need to separate them cleanly. If you've measured re-encodes on TikTok yourself, I'd like to compare notes.&lt;/p&gt;

&lt;h2&gt;
  
  
  If you run several accounts
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Count zeros (10 views or fewer) per post, not averages per account. Averages hid this from us for weeks.&lt;/li&gt;
&lt;li&gt;Track how many times each source has already gone out &lt;strong&gt;on that platform&lt;/strong&gt;, and read your zeros against it.&lt;/li&gt;
&lt;li&gt;Compare inside the same week before you believe any lever.&lt;/li&gt;
&lt;li&gt;Expect one platform's rule to be wrong on another.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The tool these posts went out through is &lt;strong&gt;Foundry&lt;/strong&gt;: a Mac app plus a CLI and an agent skill that posts to your own accounts from your own iPhones, 7 days free at &lt;a href="https://runfoundry.app" rel="noopener noreferrer"&gt;https://runfoundry.app&lt;/a&gt;. If you'd rather we run it for your app on our phones, that's at &lt;a href="https://runfoundry.app/book" rel="noopener noreferrer"&gt;https://runfoundry.app/book&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;What has your own data said about reposting? I'm curious whether anyone has seen Instagram forget a clip, and after how long.&lt;/p&gt;

</description>
      <category>socialmedia</category>
      <category>marketing</category>
      <category>datascience</category>
      <category>startup</category>
    </item>
    <item>
      <title>Setting up an iPhone farm for short-form video: what 9 phones and 1,669 posts taught us</title>
      <dc:creator>Foundry</dc:creator>
      <pubDate>Wed, 14 Oct 2026 21:53:30 +0000</pubDate>
      <link>https://dev.to/runfoundry/setting-up-an-iphone-farm-for-short-form-video-what-9-phones-and-1669-posts-taught-us-2587</link>
      <guid>https://dev.to/runfoundry/setting-up-an-iphone-farm-for-short-form-video-what-9-phones-and-1669-posts-taught-us-2587</guid>
      <description>&lt;p&gt;&lt;em&gt;Disclosure: I'm on the team that builds Foundry, the tool this comes from. This is the setup guide we wish we had; the link is at the bottom.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;If you search "iPhone farm" or "phone farm setup", you mostly get photos of a wall of phones and very little about what keeps one posting on a Tuesday afternoon with nobody watching. We have run our own for eight weeks: 9 iPhones, 48 accounts across Instagram, TikTok and YouTube, 1,669 posts since Aug 21, about 400 a week. This is the setup, in the order we would build it again.&lt;/p&gt;

&lt;p&gt;Earlier write-ups covered &lt;a href="https://dev.to/runfoundry/what-broke-when-we-let-an-ai-agent-post-short-form-video-from-real-iphones-1506-posts-in-48fg"&gt;what broke first&lt;/a&gt;, &lt;a href="https://dev.to/runfoundry/6-ways-an-iphone-automation-fails-without-throwing-an-error-from-1547-real-posts-1kio"&gt;six failures that threw no error&lt;/a&gt; and &lt;a href="https://dev.to/runfoundry/our-swipe-passed-in-the-logs-and-bounced-on-the-glass-measuring-a-flick-on-a-real-iphone-4nd2"&gt;one swipe that bounced on the glass&lt;/a&gt;. This one is the map.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. The hardware is the boring part
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Phones:&lt;/strong&gt; used iPhones are fine. Ours are a mix of older and newer models, and the mix matters later (screen sizes, see section 4).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;One Mac:&lt;/strong&gt; every phone is plugged into it over USB. The Mac runs the automation and holds the video files.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Power and cables:&lt;/strong&gt; a powered USB hub and short cables. Check the cable before you debug the code.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Network:&lt;/strong&gt; leave Wi-Fi on. One of ours lost all data the moment Wi-Fi went off, because its SIM had none.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  2. The official apps, driven like a person
&lt;/h2&gt;

&lt;p&gt;We post through the real Instagram, TikTok and YouTube apps, driven by iOS UI automation (WebDriverAgent, the same layer Appium uses). No private APIs, no emulators, no cloud phones. The upload is the original file, not a re-compressed copy from a scheduler.&lt;/p&gt;

&lt;p&gt;The cost of doing it this way: you own every pop-up, every app update and every new sheet the app invents. Budget for that before you budget for anything else.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Signing will bite you every week
&lt;/h2&gt;

&lt;p&gt;WebDriverAgent is an app you build in Xcode and install on each phone. On a free Apple ID its provisioning profile expires after 7 days, and every phone stops at once. A paid developer account moves that to a year. Whichever you use, put the expiry date somewhere a script checks, not in your head.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Test on the smallest and the biggest screen you own
&lt;/h2&gt;

&lt;p&gt;Our phones run at three screen sizes. A tap that lands on one lands on blank space on another. Find elements by their label, not their position, and keep a small per-app list of the buttons that change between sizes.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Accounts: fewer per phone than you think
&lt;/h2&gt;

&lt;p&gt;Each phone holds a few accounts with a hard cap per app, and a new account warms for a week (scrolling, watching, no posting) before its first post. Before every posting session an account also scrolls its own feed for a while. Every account gets a safety check twice a day, and one that shows a warning stops posting until it clears.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Count a post only when you can see it
&lt;/h2&gt;

&lt;p&gt;"Tapped share" is not "posted". A post counts when the profile count goes up (Instagram), the live Short is there (YouTube) or the posted screen comes back (TikTok). Every post writes a receipt, and a retry reads the receipt first so it never double posts.&lt;/p&gt;

&lt;h2&gt;
  
  
  7. The ceiling is the content, not the phones
&lt;/h2&gt;

&lt;p&gt;Once posting was reliable, the limit moved. The same moment of a video posted again within about a week gets crushed, even on a different account. Every account needs its own cut of the source. Phones make volume reliable; they do not make it good.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it costs to run
&lt;/h2&gt;

&lt;p&gt;Our honest numbers: one Mac, nine phones, a hub, and about 1.2 posts a day per account (394 in the last 7 days across 48). The time sink was never the hardware. It was the weird screens in section 2 and the signing in section 3.&lt;/p&gt;

&lt;h2&gt;
  
  
  If you are building one
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Verify the outcome, not the action.&lt;/li&gt;
&lt;li&gt;Keep receipts so retries are safe.&lt;/li&gt;
&lt;li&gt;Put every expiry date (signing, sessions, cookies) where a script checks it.&lt;/li&gt;
&lt;li&gt;Plan for the content to be the bottleneck by week three.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We packaged our setup as &lt;strong&gt;Foundry&lt;/strong&gt;: a Mac app plus a CLI and an agent skill that runs on your own iPhones and your own accounts, 7 days free at &lt;a href="https://runfoundry.app" rel="noopener noreferrer"&gt;https://runfoundry.app&lt;/a&gt;. If you would rather we run it for your app on our phones, that is at &lt;a href="https://runfoundry.app/book" rel="noopener noreferrer"&gt;https://runfoundry.app/book&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;What does your setup look like? I'd like to hear what breaks first for you.&lt;/p&gt;

</description>
      <category>ios</category>
      <category>automation</category>
      <category>mobile</category>
      <category>startup</category>
    </item>
    <item>
      <title>Our swipe passed in the logs and bounced on the glass: measuring a flick on a real iPhone</title>
      <dc:creator>Foundry</dc:creator>
      <pubDate>Tue, 13 Oct 2026 13:39:15 +0000</pubDate>
      <link>https://dev.to/runfoundry/our-swipe-passed-in-the-logs-and-bounced-on-the-glass-measuring-a-flick-on-a-real-iphone-4nd2</link>
      <guid>https://dev.to/runfoundry/our-swipe-passed-in-the-logs-and-bounced-on-the-glass-measuring-a-flick-on-a-real-iphone-4nd2</guid>
      <description>&lt;p&gt;&lt;em&gt;Disclosure: I'm on the team that builds Foundry, the tool this comes from. This is a debugging write-up; the link is at the bottom.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;We post short-form video from real iPhones: 9 phones, 48 accounts, 1,594 posts since Aug 21. The official Instagram, TikTok and YouTube apps are driven through iOS UI automation (WebDriverAgent). Before an account posts, it also scrolls its feed for a while, which means one gesture gets sent thousands of times a day: swipe up, next video.&lt;/p&gt;

&lt;p&gt;Earlier write-ups covered &lt;a href="https://dev.to/runfoundry/what-broke-when-we-let-an-ai-agent-post-short-form-video-from-real-iphones-1506-posts-in-48fg"&gt;what broke first&lt;/a&gt; and &lt;a href="https://dev.to/runfoundry/6-ways-an-iphone-automation-fails-without-throwing-an-error-from-1547-real-posts-1kio"&gt;six failures that threw no error&lt;/a&gt;. This one is about a single gesture. We rewrote it, ran it on a phone with the screen recorded before shipping it, and it failed in a way our own log would have called a success.&lt;/p&gt;

&lt;h2&gt;
  
  
  The swipe that went nowhere
&lt;/h2&gt;

&lt;p&gt;The rewritten swipe drew a clean curved path from the lower part of the screen to the upper part. On the device the feed followed the finger up, then snapped back to the same video. Vertical video feeds are paged: if the finger is not moving fast enough at the moment it lifts, the page decides you changed your mind and bounces back.&lt;/p&gt;

&lt;p&gt;The scroll routine's log could not see that. It would have recorded every one of those swipes as &lt;code&gt;advanced&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why the log was wrong
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;advanced&lt;/code&gt; came from comparing a hash of the whole screenshot before and after the swipe. A playing video changes that hash on every frame. So a bounce, which leaves you on the same video a second later in playback, logs as a successful page.&lt;/p&gt;

&lt;p&gt;It is the same class of bug as confirming a post by a profile counter that wobbles: the signal can be caused by something other than the event. Here it was caused by time passing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt; decide "next video or same video" from something only a page change can cause. We read the overlay text (caption and account name) from frames before and after. Same text, same video, no matter how many pixels changed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Measuring instead of guessing
&lt;/h2&gt;

&lt;p&gt;We recorded the phone's screen stream with wall clock timestamps, ran our own scroll routine through it, and for each swipe measured the speed of the last moving segment before lift, in points per second. On an iPhone 13 Pro:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;App&lt;/th&gt;
&lt;th&gt;Bounced back at&lt;/th&gt;
&lt;th&gt;Advanced from&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;YouTube Shorts&lt;/td&gt;
&lt;td&gt;208 to 397 pt/s (7 swipes)&lt;/td&gt;
&lt;td&gt;435 pt/s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Instagram Reels&lt;/td&gt;
&lt;td&gt;261, 295 and 328 pt/s&lt;/td&gt;
&lt;td&gt;362 pt/s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;TikTok&lt;/td&gt;
&lt;td&gt;295 pt/s&lt;/td&gt;
&lt;td&gt;not pinned down&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The new swipe lifted at a median of about 600 pt/s, which clears all of that. But on the small screens, where YouTube's layout shortens the stroke, the median was 385, and the slowest swipe it could generate lifted at 156. So the typical swipe paged and the slow tail bounced. Distance was never the problem. A long, slow drag bounces; a short, quick flick pages.&lt;/p&gt;

&lt;p&gt;There was a second defect at the other end of the stroke. The swipe started almost at rest, taking about 100 ms to move its first 10 points. TikTok ignored two of those outright when a sponsored item with a button was under the touch. A touch that sits still for a tenth of a second looks like a press, not a scroll.&lt;/p&gt;

&lt;h2&gt;
  
  
  The fix
&lt;/h2&gt;

&lt;p&gt;Two changes to the gesture:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It lands already moving (32 to 44% of its top speed) and is 10 points from where it landed within 27 ms.&lt;/li&gt;
&lt;li&gt;It peaks late and lifts at 86 to 95% of that peak, never under 778 pt/s (the median is 1,024 to 1,313 depending on the screen), with a total duration of 202 to 606 ms by stroke length.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We generated 48,000 swipes and checked every one against those limits before any of them touched a phone. Then the same recording harness again, on a 13 Pro and on an iPhone SE: 143 of 144 swipes went to the next video. That set includes the 12 weakest swipes per app, chosen on purpose, since the average swipe was never the one that failed. The single miss was a sponsored Reel, which can take two swipes for a person too.&lt;/p&gt;

&lt;h2&gt;
  
  
  What we changed in how we test gestures
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Prove a gesture from a recording, not from the automation's return value.&lt;/strong&gt; WebDriverAgent will happily report that it performed the touch actions. It cannot tell you what the app did with them.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Test the weakest case, not the typical one.&lt;/strong&gt; Sort your generated swipes by lift speed and send the slowest dozen.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Test the smallest screen you support and a big one.&lt;/strong&gt; Our phones mix 375x667, 375x812 and 390x844 points. A stroke scaled to the screen height has a different speed on each.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Keep a number per app.&lt;/strong&gt; The thresholds above are from our recordings in October 2026. Apps change. The harness is what we keep, not the numbers.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  A second silent one, found on the way
&lt;/h2&gt;

&lt;p&gt;While reading the device session logs for this we noticed our "recycle each device session after 60 minutes" rule had never fired. It read the process age with &lt;code&gt;ps -o etimes=&lt;/code&gt;, which Linux has and macOS does not. The command failed quietly, the age was never over the limit, and sessions had been running 15 hours and more.&lt;/p&gt;

&lt;p&gt;Nothing threw. It is always the check that runs fine and measures the wrong thing.&lt;/p&gt;

&lt;h2&gt;
  
  
  If you drive real devices
&lt;/h2&gt;

&lt;p&gt;Whatever your stack (WebDriverAgent, Appium, XCUITest), the question that paid for itself was: could this check pass if the thing I care about did not happen? For our swipe log the answer was yes, on every frame of every video.&lt;/p&gt;

&lt;p&gt;The phones and the agent CLI are what we build at &lt;a href="https://runfoundry.app" rel="noopener noreferrer"&gt;Foundry&lt;/a&gt;. Happy to answer questions about the harness in the comments.&lt;/p&gt;

</description>
      <category>ios</category>
      <category>automation</category>
      <category>testing</category>
      <category>mobile</category>
    </item>
    <item>
      <title>6 ways an iPhone automation fails without throwing an error (from 1,547 real posts)</title>
      <dc:creator>Foundry</dc:creator>
      <pubDate>Mon, 12 Oct 2026 17:35:24 +0000</pubDate>
      <link>https://dev.to/runfoundry/6-ways-an-iphone-automation-fails-without-throwing-an-error-from-1547-real-posts-1kio</link>
      <guid>https://dev.to/runfoundry/6-ways-an-iphone-automation-fails-without-throwing-an-error-from-1547-real-posts-1kio</guid>
      <description>&lt;p&gt;&lt;em&gt;Disclosure: I'm on the team that builds Foundry, the tool this comes from. This is a debugging write-up; the link is at the bottom.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;We post short-form video from real iPhones: 9 phones, 47 accounts, 1,547 posts since Aug 21. The official Instagram, TikTok and YouTube apps are driven through iOS UI automation (WebDriverAgent), and a coding agent queues the work through a CLI.&lt;/p&gt;

&lt;p&gt;Yesterday I wrote about &lt;a href="https://dev.to/runfoundry/what-broke-when-we-let-an-ai-agent-post-short-form-video-from-real-iphones-1506-posts-in-48fg"&gt;what broke first&lt;/a&gt;. This one is narrower: the failures that never raised an exception. The run looked green and the post was simply not there.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. The phone's count was full and one account posted nothing
&lt;/h2&gt;

&lt;p&gt;Our scheduler covers a failed post with another post on a different account of the same phone. Sensible, until we looked per account: one phone showed 10 of 10 for the day while one of its YouTube accounts had posted zero for five days.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt; count planned against live per account, never per device. A fallback that keeps the total looking healthy is hiding a dead lane.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. A system alert is not in the app's element tree
&lt;/h2&gt;

&lt;p&gt;Apple's App Tracking Transparency prompt is a system alert. It does not show up in Instagram's accessibility tree, so the poster saw the Instagram screen behind it, tapped "Continue" on that, and nothing happened. Forever.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt; before acting, read what is actually on screen (system alerts included) and tap the exact label, in our case "Ask App Not to Track". Do not match on a generic button name that also exists behind the alert.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. The same app behaves differently on a different iPhone model
&lt;/h2&gt;

&lt;p&gt;On one iPhone 12 Pro, tapping a video tile in YouTube's picker opens the trim page right away. Our check that "the right clip is selected" took its picture after the tap, scored a black corner of the trim page, and refused the correct clip 13 times in a row.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt; take the proof before the tap, and only use it once the tile has left the screen. Then we made it stricter after review: a near-blank clip is accepted only with the pre-tap match and a second signal (the selection tray's length).&lt;/p&gt;

&lt;h2&gt;
  
  
  4. A counter that wobbles is not a receipt
&lt;/h2&gt;

&lt;p&gt;For TikTok we first confirmed a post by the profile's video count going up. That count wobbles by one on its own, so it produced both false passes and false fails.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt; wait while TikTok's upload chip is showing, then confirm. Pick a signal that only the event you care about can cause.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. A dropped session can need a human hand, and no retry will fix it
&lt;/h2&gt;

&lt;p&gt;When an automation session ends, the phone may want its passcode before automation mode comes back. The log line is &lt;code&gt;Timed out while enabling automation mode&lt;/code&gt;, and the phone's own log says the daemon "requires authentication to enable automation mode". One morning all nine lanes dropped at once and stayed down until someone walked to the rig.&lt;/p&gt;

&lt;p&gt;Two things helped:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Settings &amp;gt; Developer &amp;gt; &lt;strong&gt;Enable UI Automation&lt;/strong&gt;, switched on by hand once per phone.&lt;/li&gt;
&lt;li&gt;A watcher that runs every 30 minutes, stays silent when healthy, and when lanes are down with posts overdue it names the blocker (Mac screen locked, phone with no USB session, passcode) for a human.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Our agents never answer a Trust or passcode prompt. That is a person's job on purpose.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. The fix itself was too loose
&lt;/h2&gt;

&lt;p&gt;Two of the fixes above went onto the phones, then an independent review found the first versions accepted too much. We reworked both. The lesson we wrote down: review before you install on the machine that is posting, not after.&lt;/p&gt;

&lt;h2&gt;
  
  
  The audit that caught all of it
&lt;/h2&gt;

&lt;p&gt;One script, run for any date range:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;planned posts against done posts, per phone and per account&lt;/li&gt;
&lt;li&gt;every miss listed with its cause&lt;/li&gt;
&lt;li&gt;"done" YouTube rows checked against the public channel feed&lt;/li&gt;
&lt;li&gt;"unknown" TikTok rows checked against the public profile&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Three days in early October came back 159 of 165 live. After the fixes, the next full day was 61 of 62. The six misses were the interesting part, because each one was a green run.&lt;/p&gt;

&lt;h2&gt;
  
  
  If you automate real devices
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Verify against the public result, not your own log.&lt;/li&gt;
&lt;li&gt;Count per account or per tenant, not per device.&lt;/li&gt;
&lt;li&gt;Treat system alerts as a separate layer from the app.&lt;/li&gt;
&lt;li&gt;Take proofs before the action that changes the screen.&lt;/li&gt;
&lt;li&gt;Decide in advance which prompts only a human may answer.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We packaged the poster as &lt;strong&gt;Foundry&lt;/strong&gt;: a Mac app, a CLI and an agent skill, running on your own iPhones and your own accounts. 7 days free: &lt;a href="https://runfoundry.app" rel="noopener noreferrer"&gt;https://runfoundry.app&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you run device automation at any scale, what was your worst green run?&lt;/p&gt;

</description>
      <category>ios</category>
      <category>automation</category>
      <category>testing</category>
      <category>ai</category>
    </item>
    <item>
      <title>What broke when we let an AI agent post short-form video from real iPhones (1,506 posts in)</title>
      <dc:creator>Foundry</dc:creator>
      <pubDate>Sun, 11 Oct 2026 21:17:04 +0000</pubDate>
      <link>https://dev.to/runfoundry/what-broke-when-we-let-an-ai-agent-post-short-form-video-from-real-iphones-1506-posts-in-48fg</link>
      <guid>https://dev.to/runfoundry/what-broke-when-we-let-an-ai-agent-post-short-form-video-from-real-iphones-1506-posts-in-48fg</guid>
      <description>&lt;p&gt;&lt;em&gt;Disclosure: I'm on the team that builds Foundry, the tool described here. This is a write-up of what went wrong, not a sales page; the link is at the bottom.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;We run a debate app, and short-form video is basically our only growth channel. That means dozens of Instagram, TikTok and YouTube accounts, each needing its own posts every day.&lt;/p&gt;

&lt;p&gt;We tried the usual routes first:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Posting by hand&lt;/strong&gt; fell apart within a week.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Schedulers&lt;/strong&gt; post through APIs and re-compress the video.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cloud phones&lt;/strong&gt; felt like renting someone else's accounts.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So we plugged iPhones into a Mac and had the official apps driven through iOS UI automation (WebDriverAgent), with a coding agent (Claude Code, Codex or Cursor) calling a small CLI to queue and post clips.&lt;/p&gt;

&lt;p&gt;Today our own setup is 9 iPhones, 44 accounts, 1,506 posts since Aug 21, about 400 a week. Here is what broke, roughly in the order it hurt.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Pop-ups are the real enemy
&lt;/h2&gt;

&lt;p&gt;Every app throws surprise sheets: rate-this-app prompts, "new feature" cards, permission dialogs, iOS update nags. A script written for the happy path stalls on the first one, and that phone posts nothing for the rest of the day.&lt;/p&gt;

&lt;p&gt;What worked: before every tap, look for anything modal on screen and clear it, with a list of known dismiss buttons per app. When something unknown shows up, screenshot it, skip that post, and keep the phone moving. Our worst day before this we missed 21 posts.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. "Tapped share" is not "posted"
&lt;/h2&gt;

&lt;p&gt;The first version counted a post the moment it tapped Share. Uploads fail silently, processing stalls, and drafts get saved instead of published.&lt;/p&gt;

&lt;p&gt;Now a post only counts once it is verified after it goes up:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Instagram:&lt;/strong&gt; the profile's post count went up.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;YouTube:&lt;/strong&gt; the live Short is there.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;TikTok:&lt;/strong&gt; the posted screen came back.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Every post writes a receipt. A failed one retries 20 minutes later, and the retry checks the receipt first so it never double-posts.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Read the caption back off the screen
&lt;/h2&gt;

&lt;p&gt;Autocorrect and dropped characters happen, especially with emoji and hashtags typed through automation. The poster types the caption, reads it back from the screen, and fixes or retypes it before sharing.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. The limit was reach, not posting
&lt;/h2&gt;

&lt;p&gt;Once posting was reliable, we hit the real wall. The same moment of a video, posted again within about a week, gets crushed, even on a different account.&lt;/p&gt;

&lt;p&gt;Every account needs its own cut: a different part of the source video, not the same clip re-uploaded. Reliable volume only helps if each post is actually different.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Volume is not growth by itself
&lt;/h2&gt;

&lt;p&gt;The tool makes the volume reliable. Whether the views turn into installs still comes down to the content and the funnel behind it. We're still working on that side, and I won't pretend the automation solved it.&lt;/p&gt;

&lt;h2&gt;
  
  
  If you're building something similar
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Treat every UI state as untrusted, and verify the outcome instead of the action.&lt;/li&gt;
&lt;li&gt;Keep receipts, so retries are safe.&lt;/li&gt;
&lt;li&gt;Budget most of your time for the weird screens, not the main flow.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We packaged this as &lt;strong&gt;Foundry&lt;/strong&gt;: a Mac app plus a CLI and an agent skill, running on your own iPhones and your own accounts. It's 7 days free: &lt;a href="https://runfoundry.app" rel="noopener noreferrer"&gt;https://runfoundry.app&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you run a bunch of phones or a UGC account setup, I'd really like to hear what breaks for you.&lt;/p&gt;

</description>
      <category>automation</category>
      <category>ios</category>
      <category>ai</category>
      <category>startup</category>
    </item>
  </channel>
</rss>
