<?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: Kaung Zin Hein</title>
    <description>The latest articles on DEV Community by Kaung Zin Hein (@zin_kg).</description>
    <link>https://dev.to/zin_kg</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%2F1461616%2F808e72a4-9fcb-4668-95e8-50793b4f42cd.jpg</url>
      <title>DEV Community: Kaung Zin Hein</title>
      <link>https://dev.to/zin_kg</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/zin_kg"/>
    <language>en</language>
    <item>
      <title>I Built an AI Cargo Fleet That Never Holds the Key</title>
      <dc:creator>Kaung Zin Hein</dc:creator>
      <pubDate>Mon, 31 Aug 2026 23:04:33 +0000</pubDate>
      <link>https://dev.to/zin_kg/i-built-an-ai-cargo-fleet-that-never-holds-the-key-474k</link>
      <guid>https://dev.to/zin_kg/i-built-an-ai-cargo-fleet-that-never-holds-the-key-474k</guid>
      <description>&lt;h3&gt;
  
  
  A maritime release workflow where agents coordinate the work, but only human attestation and independently verified receipts can unlock the container.
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;This article was created for the purposes of entering the All Things Agentic Hackathon.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The container is undamaged.&lt;/p&gt;

&lt;p&gt;It is still not moving.&lt;/p&gt;

&lt;p&gt;That was the operational contradiction that pulled me into Cargo Release.&lt;/p&gt;

&lt;p&gt;After a maritime casualty, cargo interests may need to provide General Average security before cargo is released. In practice, that can involve an average bond from the cargo interest and a guarantee from an insurer, routed through an average adjuster and then recognized by the carrier. The final adjustment can remain open long after the immediate release-security work is complete. That separation—release now, settle later—is documented in both the &lt;a href="https://comitemaritime.org/wp-content/uploads/2018/06/2016-York-Antwerp-Rules-Proposals-CMI-Guidelines-V4.pdf" rel="noopener noreferrer"&gt;CMI guidance on the York-Antwerp Rules&lt;/a&gt; and &lt;a href="https://unctad.org/system/files/official-document/unctadsddleg1_en.pdf" rel="noopener noreferrer"&gt;UNCTAD's review of General Average practice&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;For the person coordinating the cargo interest, this creates a peculiar queue of work:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;reconcile the casualty notice and cargo evidence;&lt;/li&gt;
&lt;li&gt;obtain the owner's attestation;&lt;/li&gt;
&lt;li&gt;obtain the insurer's guarantee;&lt;/li&gt;
&lt;li&gt;submit the security pack;&lt;/li&gt;
&lt;li&gt;retain an adjuster's rejection instead of losing it in email;&lt;/li&gt;
&lt;li&gt;correct the pack;&lt;/li&gt;
&lt;li&gt;obtain acceptance;&lt;/li&gt;
&lt;li&gt;request the carrier's release order;&lt;/li&gt;
&lt;li&gt;confirm that the carrier actually read it back;&lt;/li&gt;
&lt;li&gt;notify the operator without confusing notification with authority.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That is exactly the kind of multi-party friction an agent fleet should remove.&lt;/p&gt;

&lt;p&gt;It is also exactly the kind of workflow where an agent should never be allowed to say, “Looks good to me—release the cargo.”&lt;/p&gt;

&lt;p&gt;So I built the fleet around a constraint:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Agents coordinate. Humans attest. Independent receipts authorize release.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The model can inspect, extract, rank, explain, and propose. It cannot become the owner, insurer, adjuster, carrier, or state writer.&lt;/p&gt;

&lt;p&gt;That is the product.&lt;/p&gt;

&lt;h2&gt;
  
  
  One attestation, eight bounded actions
&lt;/h2&gt;

&lt;p&gt;Cargo Release begins with one synthetic casualty CloudEvent delivered through Google Cloud Pub/Sub and Eventarc. The deployed run converges on one durable mission in Cloud SQL—even when the same event is delivered more than once.&lt;/p&gt;

&lt;p&gt;The workflow collects five prepared evidence sources. Two of them are deliberately placed in conflict.&lt;/p&gt;

&lt;p&gt;One is a synthetic scanned adjuster rejection with a visible correction field. The other is a hostile email telling the model to ignore the process and manufacture acceptance.&lt;/p&gt;

&lt;p&gt;The email stays visible, but it is quarantined. It creates no trusted fact, no memory entry, and no state transition.&lt;/p&gt;

&lt;p&gt;The scan follows a different path. Its digest, case, container, revision, checkbox, missing field, and confidence must fit a typed schema. Deterministic policy—not model prose—decides whether that structure is acceptable.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fa91mhoh8za6wtn18p8vq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fa91mhoh8za6wtn18p8vq.png" alt="Prepared rejection scan beside typed extraction and quarantined hostile email" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then Cargo Release stops.&lt;/p&gt;

&lt;p&gt;The operator must make the sole human decision in the run: attest the synthetic owner bond.&lt;/p&gt;

&lt;p&gt;That one action starts eight bounded downstream actions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1 human attestation
  → 5 unique signed partner receipts
  + 1 security submission
  + 1 automatic correction
  + 1 marked post-release notification
  = 8 autonomous downstream actions
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Security pack v1 is rejected. That rejection is not treated as an exception to hide; it becomes durable evidence. The controller uses the validated missing-field reference to produce v2. The adjuster accepts v2. The carrier issues an order and then independently confirms read-back.&lt;/p&gt;

&lt;p&gt;Only then does the physical cargo state move from &lt;code&gt;HELD&lt;/code&gt; to &lt;code&gt;RELEASED&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The General Average adjustment remains &lt;code&gt;OPEN&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;That last detail matters. The system does not collapse a complicated legal and commercial process into a dishonest green checkmark. It advances one bounded operational state and leaves the larger adjustment where it belongs.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fdogrc91630peln7v9je8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fdogrc91630peln7v9je8.png" alt="Cargo released with five verified receipts while the adjustment remains open" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The architecture is an authority map
&lt;/h2&gt;

&lt;p&gt;Most cloud architecture diagrams answer, “Which products did you use?”&lt;/p&gt;

&lt;p&gt;I needed this one to answer a harder question:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Who is allowed to change reality?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fb3lafqfc6aqfhfwzrw3i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fb3lafqfc6aqfhfwzrw3i.png" alt="Cargo Release authority architecture" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The system has four lanes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Authenticated intake.&lt;/strong&gt; Pub/Sub and Eventarc deliver the casualty envelope. The public Next.js service runs on Cloud Run and exposes a narrow authenticated relay. The only media input is the prepared, digest-bound synthetic scan. There is no unrestricted public upload surface.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Scoped coordination.&lt;/strong&gt; Google ADK runs a coordinator and four specialized workers on Vertex AI: manifest evidence, security pack, carrier authority, and runtime recovery. Each worker has one read-only tool, structured output, no peer transfer, and the invariant &lt;code&gt;release_authority=false&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Deterministic authority.&lt;/strong&gt; A private Cloud Run controller is the sole state writer. Cloud SQL for PostgreSQL holds missions, versions, leases, evidence decisions, receipts, and hash-linked events. One human attestation and issuer-bound partner receipts advance the state graph. The insurer, adjuster, and carrier run as identity-isolated private Cloud Run services.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Observable consequence.&lt;/strong&gt; The container changes state only after the two-key condition has been satisfied. A marked Slack message is sent after carrier read-back. Notification is proof of the consequence, never a cause of it.&lt;/p&gt;

&lt;p&gt;Across the four lanes, Agent Identity, Agent Gateway, Registry, Model Armor, Memory Bank, Cloud Logging, and Cloud Trace constrain or observe the system. They never acquire release authority.&lt;/p&gt;

&lt;p&gt;Cloud Run service identities are useful here because Google Cloud can authenticate service-to-service calls using the identity assigned to each workload rather than a shared credential baked into the application. Google documents that distinction explicitly in its &lt;a href="https://docs.cloud.google.com/run/docs/securing/service-identity" rel="noopener noreferrer"&gt;Cloud Run service identity guide&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The resulting design rule is simple:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Intelligence may be distributed. Authority must remain explicit.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  The failure that improved the project
&lt;/h2&gt;

&lt;p&gt;The most important multimodal feature in Cargo Release is also the place where the honest answer is least glamorous.&lt;/p&gt;

&lt;p&gt;I built a Vertex AI adapter for Gemini to extract an &lt;code&gt;adjuster-rejection-v1&lt;/code&gt; record from the prepared scan. The adapter is digest-bound, schema-versioned, and records a zero-authority model receipt.&lt;/p&gt;

&lt;p&gt;Then I staged it against the managed service.&lt;/p&gt;

&lt;p&gt;The ambiguous case failed closed, exactly as intended.&lt;/p&gt;

&lt;p&gt;The valid scan did not pass. The managed model returned malformed structured output.&lt;/p&gt;

&lt;p&gt;There were two tempting responses:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;loosen the validator until the output passed;&lt;/li&gt;
&lt;li&gt;hide the failure and record the happy path with a deterministic response.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I did neither.&lt;/p&gt;

&lt;p&gt;The production interface and demo label the extraction &lt;code&gt;FIXTURE&lt;/code&gt;. The deterministic fixture uses the same schema and validation boundary, so the evidence-to-v2 causal path remains demonstrable, but I do not claim that the live extraction is native Vertex inference. The managed adapter remains staged until a valid scan and an ambiguous scan both pass the required acceptance packet.&lt;/p&gt;

&lt;p&gt;That choice cost the demo a shinier badge.&lt;/p&gt;

&lt;p&gt;It also proved the safety property I cared about: malformed model output cannot talk the system into trusting it.&lt;/p&gt;

&lt;p&gt;I started this project thinking “fail closed” was an implementation detail.&lt;/p&gt;

&lt;p&gt;It became the strongest product requirement.&lt;/p&gt;

&lt;h2&gt;
  
  
  Rejection is evidence, not interruption
&lt;/h2&gt;

&lt;p&gt;The next design mistake was more subtle.&lt;/p&gt;

&lt;p&gt;A first version of a workflow like this naturally models rejection as an error:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;submit → rejected → failed run
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But an adjuster's rejection can contain the exact fact needed to create the correct revision. If I turn it into a generic exception, I throw away the information that makes autonomous recovery possible.&lt;/p&gt;

&lt;p&gt;Cargo Release models it instead as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;submit v1
  → retain signed rejection + reason + source reference
  → select revision 2
  → correct the declared field
  → submit v2
  → retain acceptance
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The run continues without another human click. The correction is bounded by a typed, validated reason—not an agent improvising a new security document.&lt;/p&gt;

&lt;p&gt;This became a broader lesson:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A useful agentic system does not merely survive the wrong path. It turns the wrong path into the next verified input.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Idempotency is part of the user experience
&lt;/h2&gt;

&lt;p&gt;Event-driven systems are allowed to redeliver. Browsers retry. Operators double-click. Remote partners time out after doing the work but before returning the response.&lt;/p&gt;

&lt;p&gt;If “one attestation → eight actions” becomes sixteen actions under retry, the metric is theatre.&lt;/p&gt;

&lt;p&gt;So the count is derived from durable, unique receipt kinds, event types, and delivered notifications. Duplicate events converge on one mission. Atomic leases permit one active writer. Partner receipts are issuer-bound, signed, digest-addressed, and valid only from an allowed prior state. Slack delivery is post-read-back and idempotent.&lt;/p&gt;

&lt;p&gt;The managed concurrency probe delivered the same casualty six times across three Cloud Run instances. Every request returned successfully. The database retained one declaration, one run, and one human gate.&lt;/p&gt;

&lt;p&gt;That test changed how I think about “autonomy.”&lt;/p&gt;

&lt;p&gt;An autonomous system is not one that performs many actions. It is one that still performs the right number of actions when the infrastructure behaves normally—which includes duplication, delay, and retry.&lt;/p&gt;

&lt;h2&gt;
  
  
  Additional models, deliberately outside authority
&lt;/h2&gt;

&lt;p&gt;The project also integrates three additional Google AI models, each downstream of the authority boundary:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Gemma 4&lt;/strong&gt; reviews a sanitized owner-bond packet against a constrained checklist.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Gemini Embedding 2&lt;/strong&gt; ranks eight reviewed synthetic cases after deterministic filtering.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Veo 3.1 Fast&lt;/strong&gt; creates a four-second post-release training replay in private Cloud Storage.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All three produce visible receipts. All three return &lt;code&gt;release_authority=false&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The Veo replay is intentionally not attached to the authoritative Slack notice. It is training material, not evidence. A generated video should never become proof that the event it depicts actually happened.&lt;/p&gt;

&lt;p&gt;That separation matters more than the number of models in the stack.&lt;/p&gt;

&lt;h2&gt;
  
  
  The live proof
&lt;/h2&gt;

&lt;p&gt;The final continuous demo begins on the public Cloud Run deployment and shows the exact &lt;code&gt;.run.app&lt;/code&gt; URL beside a fresh native Eventarc mission and Pub/Sub message ID.&lt;/p&gt;

&lt;p&gt;The recorded mission is &lt;code&gt;mission-13820650dbee&lt;/code&gt;; its Pub/Sub message is &lt;code&gt;21614781193876288&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;From there, one uninterrupted live application execution shows:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;authenticated intake;&lt;/li&gt;
&lt;li&gt;hostile-text quarantine;&lt;/li&gt;
&lt;li&gt;the prepared visual evidence and its truth label;&lt;/li&gt;
&lt;li&gt;the sole owner attestation;&lt;/li&gt;
&lt;li&gt;v1 rejection and retained reason;&lt;/li&gt;
&lt;li&gt;automatic v2 correction;&lt;/li&gt;
&lt;li&gt;five verified receipts and carrier read-back;&lt;/li&gt;
&lt;li&gt;physical cargo moving to &lt;code&gt;RELEASED&lt;/code&gt; while adjustment remains &lt;code&gt;OPEN&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;the matching marked Slack consequence and &lt;code&gt;1 → 8/8&lt;/code&gt; proof metric.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The original v6 application source is preserved separately at 3 minutes 16.84 seconds with zero cuts, splices, or speed changes. In the 3-minute-28.80-second v7 master, its product-execution portion remains continuous through the completed consequence and proof metric. Only then does a disclosed 12-second Google Cloud Console insert show project &lt;code&gt;ata-2026-cargo&lt;/code&gt;, &lt;code&gt;cargo-release-controller&lt;/code&gt;, &lt;code&gt;us-central1&lt;/code&gt;, the same mission filter, and &lt;code&gt;GET /v1/missions/mission-13820650dbee 200 OK&lt;/code&gt;. The architecture footage then resumes and explains the exact Google Cloud service path. The two master edit boundaries around the Console insert are explicitly disclosed.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fdpv9f3s00y4fg85j4xrv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fdpv9f3s00y4fg85j4xrv.png" alt="Marked Slack consequence linked to the released synthetic mission" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What I learned
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. The safest architecture begins with verbs.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Who may read? Who may propose? Who may write? Who may attest? Who may issue a receipt? Product names come after those answers.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. A model receipt is not an authority receipt.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Provenance, confidence, schema version, and source digest make model output inspectable. They do not make it true or authorized.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Human-in-the-loop should name the human's actual decision.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The operator does not click “approve AI.” They attest one owner-bound fact. Everything else is bounded execution or independent receipt verification.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Preserve failure as data.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The rejected v1 is more valuable than a generic exception because it contains the reason that selects v2.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Truth labels beat implied sophistication.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;NATIVE&lt;/code&gt;, &lt;code&gt;ADAPTER&lt;/code&gt;, and &lt;code&gt;FIXTURE&lt;/code&gt; are visible per mission. A managed service existing somewhere in the project does not upgrade a fixture run into native proof.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;6. Generated media belongs after the decision boundary.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Veo can teach the workflow after release. It cannot prove the workflow before release.&lt;/p&gt;

&lt;h2&gt;
  
  
  What this does not do
&lt;/h2&gt;

&lt;p&gt;Cargo Release is a fictional, synthetic architecture demonstration.&lt;/p&gt;

&lt;p&gt;It does not decide coverage, liability, contribution, legal sufficiency, or a real General Average adjustment. It does not communicate with a real cargo owner, insurer, adjuster, carrier, terminal, or vessel. “Released” means the synthetic mission reached its deterministic terminal state after verified synthetic receipts.&lt;/p&gt;

&lt;p&gt;The live visual extraction is truthfully labelled as a deterministic fixture while the managed Vertex adapter remains staged. The partner services are identity-isolated fixtures, not real commercial integrations.&lt;/p&gt;

&lt;p&gt;Those are limits, not footnotes.&lt;/p&gt;

&lt;p&gt;They are the line between demonstrating an authority architecture and pretending to operate one.&lt;/p&gt;

&lt;h2&gt;
  
  
  The takeaway
&lt;/h2&gt;

&lt;p&gt;The easy version of this project was an agentic supply-chain control tower.&lt;/p&gt;

&lt;p&gt;The interesting version was a system that could coordinate across multiple parties while remaining constitutionally incapable of impersonating any of them.&lt;/p&gt;

&lt;p&gt;That is why the final screen does not say “AI approved.”&lt;/p&gt;

&lt;p&gt;It says the owner attested, the insurer guaranteed, the adjuster accepted, the carrier read back, and the deterministic controller verified every transition.&lt;/p&gt;

&lt;p&gt;The agents did the coordination.&lt;/p&gt;

&lt;p&gt;They never held the key.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Try it:&lt;/strong&gt; &lt;a href="https://cargo-release-web-1015646664425.us-central1.run.app" rel="noopener noreferrer"&gt;https://cargo-release-web-1015646664425.us-central1.run.app&lt;/a&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Inspect the proof mission:&lt;/strong&gt; &lt;a href="https://cargo-release-web-1015646664425.us-central1.run.app/?mission=mission-13820650dbee" rel="noopener noreferrer"&gt;https://cargo-release-web-1015646664425.us-central1.run.app/?mission=mission-13820650dbee&lt;/a&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Source:&lt;/strong&gt; &lt;a href="https://github.com/Zen-cronic/cargo-release" rel="noopener noreferrer"&gt;https://github.com/Zen-cronic/cargo-release&lt;/a&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Demo:&lt;/strong&gt; &lt;a href="https://youtu.be/mBSkNDSCHJY" rel="noopener noreferrer"&gt;https://youtu.be/mBSkNDSCHJY&lt;/a&gt;&lt;/p&gt;

</description>
      <category>googlecloud</category>
      <category>ai</category>
      <category>agents</category>
      <category>showdev</category>
    </item>
    <item>
      <title>The Destination Had No Weather Station. So I Stopped Asking for an Airport Code.</title>
      <dc:creator>Kaung Zin Hein</dc:creator>
      <pubDate>Mon, 31 Aug 2026 22:05:17 +0000</pubDate>
      <link>https://dev.to/zin_kg/the-destination-had-no-weather-station-so-i-stopped-asking-for-an-airport-code-3961</link>
      <guid>https://dev.to/zin_kg/the-destination-had-no-weather-station-so-i-stopped-asking-for-an-airport-code-3961</guid>
      <description>&lt;p&gt;How I built Waterline to turn route geometry and scattered evidence into a pilot-authorized plan and a realtime follower room that cannot change flight authority.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This article was created for the purposes of entering the All Things Agentic Hackathon.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The destination was a lake.&lt;/p&gt;

&lt;p&gt;The briefing workflow wanted an aerodrome identifier.&lt;/p&gt;

&lt;p&gt;There was no useful destination code to enter. There was no weather station at the destination to query either.&lt;/p&gt;

&lt;p&gt;That did not mean there was no evidence. Route-level notices existed. Nearby stations were reporting weather. A local condition card identified a landing obstruction. The pilot still needed a responsible person following the flight.&lt;/p&gt;

&lt;p&gt;The evidence was there. The natural lookup key was not.&lt;/p&gt;

&lt;p&gt;That is the contradiction behind Waterline: a flight can have a real route, real hazards, and real human accountability even when the destination is absent from the identifier-first workflow.&lt;/p&gt;

&lt;p&gt;My first design decision was therefore not a model choice. It was a data-model choice.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Stop asking the lake for an airport code. Start with geometry.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That change led to the second, more important rule:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Realtime coordination does not require realtime authority.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Waterline can assemble evidence and open a live room for a flight follower. Neither the model nor the conversation is allowed to approve the route.&lt;/p&gt;

&lt;h2&gt;
  
  
  Geometry became the key
&lt;/h2&gt;

&lt;p&gt;For the deployed scenario, the pilot selects Toronto Pearson (&lt;code&gt;CYYZ&lt;/code&gt;), Lady Evelyn Lake, and a cruise altitude.&lt;/p&gt;

&lt;p&gt;Waterline resolves those endpoints to a line, then uses PostGIS to create a ten-nautical-mile route corridor and an altitude band. The database—not a language model—decides which notices intersect that corridor, overlap the flight level, and remain valid for the flight window. PostGIS documents &lt;code&gt;ST_Buffer&lt;/code&gt; as the operation that produces the polygon around a line or geography; Waterline uses that deterministic geometry to reduce a FIR-wide set to the hazards that touch this flight.&lt;/p&gt;

&lt;p&gt;A FIR is a Flight Information Region. A NOTAM is a time-sensitive notice about an aeronautical facility, service, procedure, or hazard. A METAR is a coded observation from a weather station. NAV CANADA's own flight-planning page describes its Weather and NOTAM data as geographically referenced, searchable around an aerodrome, navigation aid, or FIR.&lt;/p&gt;

&lt;p&gt;Lady Evelyn Lake still has no destination METAR. Waterline does not pretend otherwise. It gathers nearby real observations, calculates a bounded stationless read, and keeps the distance, source stations, spread, and confidence visible. The interface calls it &lt;strong&gt;inference, not measurement&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This distinction is load-bearing. A fluent sentence cannot turn nearby weather into a destination observation.&lt;/p&gt;

&lt;h2&gt;
  
  
  The wrong path earns the right plan
&lt;/h2&gt;

&lt;p&gt;The local condition evidence is a prepared synthetic card for the Lady Evelyn scenario. It is visibly labelled &lt;code&gt;FIXTURE&lt;/code&gt; in the product and film.&lt;/p&gt;

&lt;p&gt;Gemini extracts a typed record from that image: lake, validity window, observed sector, obstruction, and confidence. Deterministic validation binds the result to the source digest and schema. A hostile note embedded in the image tells the model to ignore the safety rules and authorize dispatch.&lt;/p&gt;

&lt;p&gt;Waterline does not hide that text. It records its hash and quarantines it. The note creates no trusted fact, memory, or state transition.&lt;/p&gt;

&lt;p&gt;The accepted fact is narrower: the east cove has a log boom across the approach.&lt;/p&gt;

&lt;p&gt;That one fact changes the plan.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;east-cove route v1
  → deterministic obstruction check
  → REJECTED
  → west-cove route v2 proposed
  → ATTESTATION REQUIRED
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fb3o7bvxdzplelfvc0gsr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fb3o7bvxdzplelfvc0gsr.png" alt="Waterline rejects east-cove v1 after validating the prepared condition card and proposes west-cove v2 for pilot review" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The failure is not demo decoration. It is the causal reason the route revision exists. The model may explain why west cove is the candidate sector, but deterministic code owns the rejection and the state graph.&lt;/p&gt;

&lt;p&gt;Then Waterline stops.&lt;/p&gt;

&lt;h2&gt;
  
  
  The one decision the agent cannot make
&lt;/h2&gt;

&lt;p&gt;The pilot sees the full evidence stack: the route corridor, source receipts, stationless weather confidence, hostile-text quarantine, rejected v1, and proposed v2.&lt;/p&gt;

&lt;p&gt;The status is &lt;code&gt;ATTESTATION REQUIRED&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;No agent can click through it. No follower can click through it. The authenticated pilot performs one owner-bound attestation by selecting &lt;strong&gt;Attest &amp;amp; open follower room&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;That action atomically writes one Cloud SQL receipt. The receipt commits the mission, the one-hour expiry, the room reference, and the SHA-256 of the capability token. It does not store the raw signed token.&lt;/p&gt;

&lt;p&gt;The browser receives a QR code and a copyable link. The invitation contains no phone number, pilot identity, or mutable route field. Possession grants access to one temporary coordination room—not permission to alter the briefing.&lt;/p&gt;

&lt;p&gt;The state now reads &lt;code&gt;HANDOFF READY · WAITING FOR FOLLOWER&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The consequence arrives in both browsers
&lt;/h2&gt;

&lt;p&gt;The responsible person opens the link on a phone-sized browser. Firebase Anonymous Authentication creates a temporary browser identity. A Cloud Run authorization bridge validates the signed capability and expiry, then creates exactly one mission-scoped follower membership.&lt;/p&gt;

&lt;p&gt;After that bridge, both browsers talk directly to Firestore under Security Rules. Firestore's &lt;code&gt;onSnapshot()&lt;/code&gt; listener delivers the initial room state and subsequent updates. The follower can send one fixed acknowledgement—&lt;code&gt;Following acknowledged&lt;/code&gt;—and plain-text messages up to 500 characters. There are no attachments, edits, deletes, typing indicators, arbitrary recipients, or presence tracking.&lt;/p&gt;

&lt;p&gt;The acknowledgement changes the pilot's presentation to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;FOLLOWING ACTIVE · LIVE VIA FIRESTORE
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F129z3p1i2znxfee9t97i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F129z3p1i2znxfee9t97i.png" alt="The follower acknowledgement and message appear in the deployed pilot cockpit while Cloud SQL authority remains unchanged" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the recorded deployed run, the acknowledgement appeared on the cockpit in 309 milliseconds. The follower's text reached the pilot in 224 milliseconds. The pilot's reply reached the follower in 854 milliseconds.&lt;/p&gt;

&lt;p&gt;Those are observations from one recorded mission, not latency promises.&lt;/p&gt;

&lt;p&gt;The consequential boundary is simpler than the timings:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Chat changes who is informed. It does not change what is authorized.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Replay had to return the same room
&lt;/h2&gt;

&lt;p&gt;Browsers refresh. Pilots double-click. Networks fail after a server has committed work but before the response arrives.&lt;/p&gt;

&lt;p&gt;If replay opened a second room, Waterline would turn a safety feature into ambiguity.&lt;/p&gt;

&lt;p&gt;So Cloud SQL claims the handoff with one idempotency key. The invitation is reconstructed from durable mission inputs and the persisted expiry. Waterline hashes the reconstructed token and compares it with the stored digest before returning it.&lt;/p&gt;

&lt;p&gt;The accepted proof refreshed the follower page and restored all three messages. Replaying the pilot command returned the same receipt, room, token digest, and expiry. Firestore still contained one thread.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fisczqr9csjdyyo11jg7c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fisczqr9csjdyyo11jg7c.png" alt="Waterline replay returns the original receipt, room, capability digest, and expiry without creating another thread" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is why the database stores a digest instead of the raw capability. Restoration remains possible, but a SQL read cannot reveal a usable invitation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Four systems, four permissions
&lt;/h2&gt;

&lt;p&gt;The architecture makes more sense after seeing the consequence.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F2chtkohebgr3l2lo6b52.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F2chtkohebgr3l2lo6b52.png" alt="Waterline's deployed architecture separates pilot authority and Cloud SQL mission state from the temporary Firestore coordination room" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Layer&lt;/th&gt;
&lt;th&gt;Job&lt;/th&gt;
&lt;th&gt;What it cannot do&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Google ADK + Vertex AI Gemini&lt;/td&gt;
&lt;td&gt;Coordinate eight scoped readers, extract typed evidence, rank, and compose a sourced proposal&lt;/td&gt;
&lt;td&gt;Write mission authority or attest for the pilot&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Public and private Cloud Run services&lt;/td&gt;
&lt;td&gt;Host the Next.js cockpit, exact signed relay, Firebase bridge, and private FastAPI/ADK service&lt;/td&gt;
&lt;td&gt;Invent a route decision or broaden a command&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cloud SQL PostgreSQL + PostGIS + pgvector&lt;/td&gt;
&lt;td&gt;Own missions, route revisions, append-only events, attestation, spatial filtering, owner-scoped recall, expiry, and the duplicate-safe receipt&lt;/td&gt;
&lt;td&gt;Delegate authoritative writes to chat or model prose&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Firebase Auth + Cloud Firestore&lt;/td&gt;
&lt;td&gt;Bind two temporary members and deliver acknowledgement plus bounded realtime text&lt;/td&gt;
&lt;td&gt;Change route, attestation, SQL receipt, or mission status&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Cloud Run service identities let the public web revision invoke the private agent and access Google services without a downloaded service-account key. The deployed private agent has exactly one Cloud Run invoker: the web service account.&lt;/p&gt;

&lt;p&gt;The eight ADK agents have different work because separation is more useful than agent count: resolve geometry, ingest live inputs, filter the corridor, recall reviewed evidence, infer nearby weather, compose, verify, and open the already-attested room. The final &lt;code&gt;FollowingAgent&lt;/code&gt; still passes through a deterministic callback before its tool can run.&lt;/p&gt;

&lt;p&gt;Two additional Google models sit outside the authority boundary. &lt;code&gt;gemini-embedding-001&lt;/code&gt; creates a 768-dimensional destination vector for owner-scoped reviewed recall. If embedding fails, memory is disabled and every candidate resurfaces. Gemma 4 (&lt;code&gt;google/gemma-4-26b-a4b-it-maas&lt;/code&gt;) may reorder the complete NOTAM set for the reading budget, but a cardinality check prevents it from removing a notice. If Gemma fails, deterministic order remains.&lt;/p&gt;

&lt;p&gt;Model failure therefore increases what the pilot sees. It never suppresses a hazard.&lt;/p&gt;

&lt;h2&gt;
  
  
  Three failures that tightened the boundary
&lt;/h2&gt;

&lt;p&gt;The interesting bugs were not crashes. They were cases where the system could have appeared successful while proving the wrong thing.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. The pilot could acknowledge as the follower
&lt;/h3&gt;

&lt;p&gt;The first Firestore rule required the fixed acknowledgement text, but it did not require the sender role to be &lt;code&gt;follower&lt;/code&gt;. A pilot member could create the same acknowledgement and make the cockpit appear active without a responsible follower.&lt;/p&gt;

&lt;p&gt;The fix added an explicit role check and an emulator regression test that proves pilot acknowledgement is denied. The final suite covers unauthenticated, unbound, expired, cross-mission, spoofed UID/role, oversized, extra-field, update, delete, and pilot-acknowledgement denial.&lt;/p&gt;

&lt;p&gt;The lesson: validating content is not enough when the actor is part of the fact.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. A realtime page never became “network idle”
&lt;/h3&gt;

&lt;p&gt;The deployed verifier originally waited for Playwright's &lt;code&gt;networkidle&lt;/code&gt; state after opening and reloading the follower page. A healthy Firestore listener is deliberately long-lived, so network silence was the wrong definition of readiness.&lt;/p&gt;

&lt;p&gt;I changed the proof to wait for &lt;code&gt;domcontentloaded&lt;/code&gt; and then assert the visible &lt;code&gt;LIVE VIA FIRESTORE&lt;/code&gt; state. The same fix sanitizes any handoff capability from error text before writing a report.&lt;/p&gt;

&lt;p&gt;The lesson: test the product's contract, not a browser heuristic that contradicts the product.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. The newest model was not always available
&lt;/h3&gt;

&lt;p&gt;During launch load, the preferred Gemini Flash endpoint intermittently returned transient 429/503 responses. Waterline now retries with bounded backoff and falls through a 3.7 → 3.6 → 3.5 Flash chain. Every model clears the event's Gemini 3.5-or-newer requirement, and the deterministic evidence gate remains identical whichever model answers.&lt;/p&gt;

&lt;p&gt;The lesson: model availability can change the reader, but it must not change the constitution.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the proof actually established
&lt;/h2&gt;

&lt;p&gt;The Matilda v6 film records mission &lt;code&gt;mission-11d9e8bf923c4e76aeb0&lt;/code&gt; on the deployed &lt;code&gt;.run.app&lt;/code&gt; service.&lt;/p&gt;

&lt;p&gt;One pilot attestation produced:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;one Cloud SQL handoff receipt;&lt;/li&gt;
&lt;li&gt;one Firestore thread;&lt;/li&gt;
&lt;li&gt;two scoped members, &lt;code&gt;pilot&lt;/code&gt; and &lt;code&gt;follower&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;one fixed acknowledgement;&lt;/li&gt;
&lt;li&gt;one text message in each direction;&lt;/li&gt;
&lt;li&gt;restored history after reload;&lt;/li&gt;
&lt;li&gt;the identical receipt, invitation, token digest, and expiry on replay;&lt;/li&gt;
&lt;li&gt;zero browser errors.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The backend suite passed 54 tests, the web suite passed 16, the Firestore Rules emulator passed 6, and the production build passed. The 3:47.133 master is 1920×1080 H.264 with English narration and AAC audio. Its first six seconds are visibly labelled synthetic domain illustrations. The deployed product then runs as one uninterrupted 1× execution through duplicate-safe replay. A disclosed native Google Cloud Logs Explorer insert shows the exact mission, private agent revision, timestamp, agent URL, and successful request status before the repository architecture closes the film.&lt;/p&gt;

&lt;p&gt;That continuity distinction matters. The complete master is not “all live” or end-to-end continuous. It is two truth-labelled context shots, a continuous operational product execution, a disclosed native Console proof, and repository architecture.&lt;/p&gt;

&lt;h2&gt;
  
  
  The limits are part of the design
&lt;/h2&gt;

&lt;p&gt;Waterline is a hackathon prototype, not an official aviation briefing service and not flight advice.&lt;/p&gt;

&lt;p&gt;The Lady Evelyn condition card is synthetic. Five Ontario water destinations are curated. The video uses a deployed phone-sized browser surface rather than footage of a physical handset. The follower room is short-lived coordination, not dispatch, flight-plan filing, emergency monitoring, or presence tracking.&lt;/p&gt;

&lt;p&gt;The deployment reads a publicly reachable NAV CANADA CFPS Weather/NOTAM endpoint, but written authorization for this software integration has not been established. NAV CANADA's terms restrict copying and software integration absent permission. I therefore do not describe the endpoint as an open or authorized API. OurAirports station coordinates come from a separately identified public-domain dataset.&lt;/p&gt;

&lt;p&gt;Firestore TTL eventually cleans up expired documents; Waterline's Security Rules stop access at the recorded expiry without waiting for deletion.&lt;/p&gt;

&lt;p&gt;Most importantly, Waterline does not decide whether a flight is safe. It organizes evidence, exposes uncertainty, enforces one route-change workflow, and preserves the pilot's decision.&lt;/p&gt;

&lt;h2&gt;
  
  
  Six rules I would reuse
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Choose the real key before choosing the model.&lt;/strong&gt; If the destination identifier is missing, geometry may be the stable object the workflow actually owns.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Make inference look different from measurement.&lt;/strong&gt; Preserve source distance, confidence, and provenance instead of letting fluent prose erase uncertainty.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Bind facts to actors.&lt;/strong&gt; “Acknowledged” is incomplete unless the system proves who was allowed to acknowledge.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Keep fast coordination outside durable authority.&lt;/strong&gt; Firestore can update both screens instantly while Cloud SQL remains the only mission ledger.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Design replay as a first-class path.&lt;/strong&gt; One human decision should not multiply rooms, receipts, or consequences under retry.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fail toward more review.&lt;/strong&gt; If embeddings, ranking, or a model fail, surface more evidence and keep the gate closed.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Waterline began with a missing airport code.&lt;/p&gt;

&lt;p&gt;It ended with a clearer division of responsibility: geometry finds the evidence, Gemini and ADK assemble the proposal, deterministic policy rejects the wrong path, the pilot attests, Cloud SQL remembers, and Firestore keeps one follower informed.&lt;/p&gt;

&lt;p&gt;The room is realtime.&lt;/p&gt;

&lt;p&gt;The authority is not.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Try the deployed app:&lt;/strong&gt; &lt;a href="https://waterline-web-2hjaxuzova-uc.a.run.app" rel="noopener noreferrer"&gt;https://waterline-web-2hjaxuzova-uc.a.run.app&lt;/a&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Read the source:&lt;/strong&gt; &lt;a href="https://github.com/Zen-cronic/waterline" rel="noopener noreferrer"&gt;https://github.com/Zen-cronic/waterline&lt;/a&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Watch the verified demo:&lt;/strong&gt; &lt;a href="https://youtu.be/05H46M1ir-o" rel="noopener noreferrer"&gt;https://youtu.be/05H46M1ir-o&lt;/a&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;View the Devpost project:&lt;/strong&gt; &lt;a href="https://devpost.com/software/waterline" rel="noopener noreferrer"&gt;https://devpost.com/software/waterline&lt;/a&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Upstream contribution:&lt;/strong&gt; &lt;a href="https://github.com/google/adk-python/issues/6968" rel="noopener noreferrer"&gt;&lt;code&gt;google/adk-python#6968&lt;/code&gt;&lt;/a&gt; — open&lt;/p&gt;

</description>
      <category>ai</category>
      <category>googlecloud</category>
      <category>agents</category>
      <category>showdev</category>
    </item>
    <item>
      <title>AI Video Needs CI More Than Better Prompts</title>
      <dc:creator>Kaung Zin Hein</dc:creator>
      <pubDate>Mon, 20 Jul 2026 20:49:27 +0000</pubDate>
      <link>https://dev.to/zin_kg/ai-video-needs-ci-more-than-better-prompts-3lb0</link>
      <guid>https://dev.to/zin_kg/ai-video-needs-ci-more-than-better-prompts-3lb0</guid>
      <description>&lt;p&gt;Here I'll share what I built for Track 2 of the Global AI Hackathon Series with Qwen Cloud, and what it taught me about testing things you can't see.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;My expensive little problem&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I generated a five-second video clip. The first frame looked perfect.&lt;/p&gt;

&lt;p&gt;Then I watched the other four seconds.&lt;/p&gt;

&lt;p&gt;The camera drifted left. My brief said hold static.&lt;/p&gt;

&lt;p&gt;Here's the part that &lt;em&gt;irritates&lt;/em&gt; me: I found out &lt;strong&gt;after&lt;/strong&gt; I paid. On Qwen Cloud's Wan models a clip is a fixed five seconds of premium quota whether it's usable or garbage. The bill doesn't care.&lt;/p&gt;

&lt;p&gt;Text models don't work like this. You read the answer, you see it's wrong, you move on. The artifact and the verdict show up together and being wrong costs you a few hundred tokens.&lt;/p&gt;

&lt;p&gt;Video fails &lt;em&gt;in motion&lt;/em&gt;. The failure lives in frames you haven't looked at yet.&lt;/p&gt;

&lt;p&gt;So you pay first, and find out second.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;But it gets worse...&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The obvious build for this track is a premise-in, episode-out generator. I started there. Within a couple of days I had something that produced a demo reel.&lt;/p&gt;

&lt;p&gt;But demo reels hide the interesting failures.&lt;/p&gt;

&lt;p&gt;Every bad take that reaches your final render is money you already spent. And I kept asking myself a question that had nothing to do with generation:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Can the system tell whether the video obeyed the brief, before it spends premium budget on it?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;That question has a name in software. It's CI.&lt;/p&gt;

&lt;p&gt;And almost nobody is running it on generated video.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;So why bother? Don't we just prompt better?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That was my first instinct too. Write better prompts, get better clips.&lt;/p&gt;

&lt;p&gt;But a prompt is not a contract. It's too easy to rewrite, stretch, and forget as an artifact moves between models. You can't assert against a prompt. You can't fail a build with one.&lt;/p&gt;

&lt;p&gt;Before I burned a week on this bet, I wanted to know it wasn't just a slogan I liked the sound of. So I counted. Twice.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Test 1 — the simulated field.&lt;/strong&gt; I ran 15 independent LLM brainstorms over this track's public brief. Two model families, 14 personas, none of them seeing my repo or each other. Around 150 ideas.&lt;/p&gt;

&lt;p&gt;All 15 produced a generator.&lt;/p&gt;

&lt;p&gt;Zero produced a way to check whether the generated episode came out right.&lt;/p&gt;

&lt;p&gt;Two of them even emitted the phrase "CI for AI-generated video" &lt;em&gt;verbatim&lt;/em&gt; — and then bolted it onto a generator anyway.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Test 2 — the observed field.&lt;/strong&gt; Two days before the deadline I read the eight most substantial shipped entries in this track's public GitHub field. Every one routes its quality checks through a token-billed model call. Six of the eight import no computer-vision library at all. None ships a closed assertion vocabulary. None can gate a video it didn't itself generate.&lt;/p&gt;

&lt;p&gt;Then I found this line in the config of a shipping logline-to-video pipeline:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;DAILIES_QC&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;   &lt;span class="c1"&gt;# off = faster pipeline
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Someone built a review stage. Named it dailies. Shipped it switched &lt;strong&gt;off&lt;/strong&gt;. For speed.&lt;/p&gt;

&lt;p&gt;That's the whole problem in one line.&lt;/p&gt;

&lt;p&gt;When the gate lives &lt;em&gt;inside&lt;/em&gt; the generator's codebase, the gate is the first thing traded away for throughput.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Time to build the tests instead&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In film production, &lt;em&gt;dailies&lt;/em&gt; are the screening where the crew watches yesterday's footage before more money is spent shooting on top of it. It's the daily quality gate.&lt;/p&gt;

&lt;p&gt;So that's the name. &lt;strong&gt;Dailies.&lt;/strong&gt; The review stage that can't be quietly switched off, because it doesn't belong to the pipeline it judges.&lt;/p&gt;

&lt;p&gt;It reads frames, not generator internals. Point it at any mp4 from any model.&lt;/p&gt;

&lt;p&gt;Here's how it works.&lt;/p&gt;

&lt;p&gt;You write what a shot has to do. Every take gets measured against it before it ships. A take that misses gets one bounded repair attempt. A take that still misses never reaches your cut.&lt;/p&gt;

&lt;p&gt;A spec is a short program in a &lt;strong&gt;closed assertion DSL — ten sentence types across three tiers&lt;/strong&gt;. The compiler translates each sentence into a call in a shared check library, and rejects anything outside the grammar &lt;em&gt;before a single token is spent&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Send it something it doesn't recognize and &lt;code&gt;parse_assertions&lt;/code&gt; raises. Send &lt;code&gt;{"type": "vibe_check"}&lt;/code&gt; to the MCP server and it comes back &lt;code&gt;isError&lt;/code&gt;, not a guess.&lt;/p&gt;

&lt;p&gt;That rejection is the literal compile error in "CI for generated video."&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Assertion type&lt;/th&gt;
&lt;th&gt;Tier&lt;/th&gt;
&lt;th&gt;Compiles to&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;duration_between&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;A · deterministic&lt;/td&gt;
&lt;td&gt;clip length within bounds&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;brightness_range&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;A · deterministic&lt;/td&gt;
&lt;td&gt;mean-luma within bounds&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;flicker_below&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;A · deterministic&lt;/td&gt;
&lt;td&gt;inter-frame luma std under threshold&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;scene_cuts&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;A · deterministic&lt;/td&gt;
&lt;td&gt;HSV-histogram cut count at or under max&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;camera_motion&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;A · deterministic&lt;/td&gt;
&lt;td&gt;optical-flow pan direction&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;palette_deltae&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;A · deterministic&lt;/td&gt;
&lt;td&gt;dominant-color ΔE to a brand palette&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;subject_present&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;0 · pre-render still&lt;/td&gt;
&lt;td&gt;subject recognizable in the t2i still&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;identity_consistent&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;B · advisory&lt;/td&gt;
&lt;td&gt;VLM: same identity across frames&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;action_completed&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;B · advisory&lt;/td&gt;
&lt;td&gt;VLM: the briefed action visibly completes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;title_card_present&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;B · advisory&lt;/td&gt;
&lt;td&gt;VLM: a title / text card is visible&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Notice there's an organizational idea hiding in that table.&lt;/p&gt;

&lt;p&gt;Right now, the person who &lt;em&gt;defines&lt;/em&gt; "correct" — brand, legal, marketing — is coupled to the person who &lt;em&gt;operates&lt;/em&gt; the generator. They're joined by one overworked reviewer eyeballing every clip.&lt;/p&gt;

&lt;p&gt;The stakeholder writes these assertions once, in plain language. Every shot gets tested against them automatically.&lt;/p&gt;

&lt;p&gt;Spec-driven development, for video.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The tiers are boring on purpose&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Not every check deserves the same budget. So the cascade runs cheapest-and-most-certain first.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tier-A is deterministic OpenCV.&lt;/strong&gt; Duration, brightness, flicker, scene cuts, optical-flow camera motion, palette ΔE. Zero tokens, so it runs on &lt;em&gt;every take&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;It's deliberately unglamorous. OpenCV has no idea whether your story works. But it cheaply catches a huge amount of broken video, and it never has an opinion it can't defend with a number.&lt;/p&gt;

&lt;p&gt;Measured over 25 iterations: all six checks on a 5-second clip cost a &lt;strong&gt;median 317 ms&lt;/strong&gt; of CPU. Nothing else.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tier-B is Qwen-VL, and it's advisory.&lt;/strong&gt; A VLM is good at "does this appear to match the brief." But a model judgment is softer evidence than a pixel measurement — so Tier-B flags for the human and never blocks promotion.&lt;/p&gt;

&lt;p&gt;Deterministic checks are the foundation. Model-graded judgment sits on top. Never underneath.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tier-0 is a still-image pre-screen.&lt;/strong&gt; Before any motion is generated, a &lt;code&gt;wan2.1-t2i-plus&lt;/code&gt; still renders at roughly 1/25th of a video's cost, and &lt;code&gt;qwen-vl-plus&lt;/code&gt; gets asked one question: is the briefed subject even in the frame?&lt;/p&gt;

&lt;p&gt;If a prompt can't render its own subject as a still, paying for motion just buys you the same lesson at 25× the price.&lt;/p&gt;

&lt;p&gt;Only after surviving all that does a shot earn promotion:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;premise → script + specs (qwen-plus) → compiled assertion checklist
        → Tier-0 still pre-screen (wan2.1-t2i-plus)
        → [human review gate — the one checkpoint, before any video spend]
        → drafts (wan2.1-t2v-turbo)
        → Tier-A CV (deterministic, zero tokens) + Tier-B VLM (qwen-vl-plus, advisory)
        → bounded prompt-repair + retake (qwen-plus)
        → promote passing shots (wan2.2-i2v-flash, anchored on the approved frame)
        → narration, one voice per character (qwen3-tts-flash)
        → ffmpeg assembly → certified episode, with sound
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A rendered architecture diagram was a required deliverable anyway, so here's the same thing drawn formally. One convention worth knowing: &lt;strong&gt;red is reserved for the two paths that matter most&lt;/strong&gt; — a spec rejected before any spend, and a blocking Tier-A fail.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fsseyqykv6kqhbkogozi9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fsseyqykv6kqhbkogozi9.png" alt=" " width="800" height="725"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Two human roles that today collapse into one exhausted reviewer. The &lt;strong&gt;stakeholder&lt;/strong&gt; owns "correct" and authors the spec once. The &lt;strong&gt;operator&lt;/strong&gt; is the only human in the loop at runtime, at the single gate before any video is paid for.&lt;/p&gt;

&lt;p&gt;Level 2 answers the question the hackathon actually asked — how Qwen Cloud connects to the frontend, backend, and store:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fccmqm3c28ge829cywnot.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fccmqm3c28ge829cywnot.png" alt=" " width="800" height="1148"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That was the design.&lt;/p&gt;

&lt;p&gt;Then I ran it for real, and reality started correcting me.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The rule that kept saving me: let the model choose, never let it spell&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Before the war stories, one design decision that turned out to matter more than anything else I did.&lt;/p&gt;

&lt;p&gt;That closed vocabulary started as an assertion-layer detail. It ended up being the rule the whole system runs on.&lt;/p&gt;

&lt;p&gt;There are three places where a Qwen model makes a real decision in Dailies. In all three, it emits a &lt;em&gt;choice from a set the server owns&lt;/em&gt; — never the artifact itself.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Where&lt;/th&gt;
&lt;th&gt;The model emits&lt;/th&gt;
&lt;th&gt;The server produces&lt;/th&gt;
&lt;th&gt;The failure it prevents&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Assertions&lt;/td&gt;
&lt;td&gt;a &lt;code&gt;type&lt;/code&gt; from a closed set + typed params&lt;/td&gt;
&lt;td&gt;a call into the check library&lt;/td&gt;
&lt;td&gt;a check that means something other than what it says&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Pipeline topology&lt;/td&gt;
&lt;td&gt;run &lt;strong&gt;parameters&lt;/strong&gt; (&lt;code&gt;premise&lt;/code&gt;, &lt;code&gt;pack&lt;/code&gt;, &lt;code&gt;max_shots&lt;/code&gt;, &lt;code&gt;custom_checks&lt;/code&gt;)&lt;/td&gt;
&lt;td&gt;the canonical node/edge graph&lt;/td&gt;
&lt;td&gt;a structurally malformed run&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Narration casting&lt;/td&gt;
&lt;td&gt;a &lt;code&gt;speaker&lt;/code&gt; — a character &lt;em&gt;name&lt;/em&gt;
&lt;/td&gt;
&lt;td&gt;a voice from a probed roster&lt;/td&gt;
&lt;td&gt;a &lt;strong&gt;silent&lt;/strong&gt; hole in a certified episode&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;That middle row became my headline demo.&lt;/p&gt;

&lt;p&gt;You type a request in plain language. &lt;code&gt;qwen-plus&lt;/code&gt; calls a &lt;code&gt;build_pipeline_graph&lt;/code&gt; tool with &lt;code&gt;tool_choice="auto"&lt;/code&gt;. The server deterministically expands those parameters into the graph the run executes, rendered live in React Flow off the same 2.5-second poll the dashboard already uses.&lt;/p&gt;

&lt;p&gt;So "an agent wired the pipeline" is a claim I can make without flinching. The model authored the run. It &lt;em&gt;could not&lt;/em&gt; have emitted a broken graph, because it never emitted topology at all.&lt;/p&gt;

&lt;p&gt;This is the difference between validating the model's output and making invalid output unrepresentable.&lt;/p&gt;

&lt;p&gt;Validation is a check you can forget to run. Or run in only one of two code paths — which I did, and I'll get to that.&lt;/p&gt;

&lt;p&gt;A parameter contract is a shape the bad value cannot fit through.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The day my green tests lied to me&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Every end-to-end test I'd written used synthetic clips. A fake Wan client returning generated mp4s so I could exercise the pipeline for free.&lt;/p&gt;

&lt;p&gt;That validates control flow. And nothing about the API's contract.&lt;/p&gt;

&lt;p&gt;A fake client can't reject a request the real service would reject.&lt;/p&gt;

&lt;p&gt;So I built a fixtures mode. Real Wan client, real Tier-A, real Tier-B, real assembly — with only the two non-deterministic text stages pinned to fixed prompts. (Prompts are cache keys, so a pinned run replays identically at zero quota.)&lt;/p&gt;

&lt;p&gt;Then I ran it cold, against the real API, for the first honest time.&lt;/p&gt;

&lt;p&gt;It found four bugs.&lt;/p&gt;

&lt;p&gt;Seventy-nine passing tests had missed every single one.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Bug&lt;/th&gt;
&lt;th&gt;Why 79 passing tests missed it&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;wan2.2-t2v-plus&lt;/code&gt; &lt;strong&gt;rejects &lt;code&gt;1280*720&lt;/code&gt;&lt;/strong&gt; — so &lt;em&gt;every premium promotion the project had ever made had silently failed&lt;/em&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;_promote&lt;/code&gt; treats a failed promote as "keep the passing draft," so a rejected final and a healthy skip produced identical state. The premium tier — my entire wedge — had never actually run.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;The budget governor asked the cache about the wrong resolution key for finals, calling every cached final "fresh"&lt;/td&gt;
&lt;td&gt;Under judge mode that would have &lt;em&gt;refused free replays during judging&lt;/em&gt; — the one thing the live URL depends on.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;The ledger wrote an empty note for both a no-op and a hard failure&lt;/td&gt;
&lt;td&gt;Which is precisely how the first two hid. The audit trail didn't audit.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;state.json&lt;/code&gt; was write-only — snapshots atomically written, never read back&lt;/td&gt;
&lt;td&gt;Every redeploy silently discarded every run a viewer had made, while my architecture diagram promised state persists across restarts.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Sit with that first row for a second.&lt;/p&gt;

&lt;p&gt;My entire pitch is that generated video ships unverified because nobody runs the claim against the artifact.&lt;/p&gt;

&lt;p&gt;And my own premium tier had been dead for the project's whole life. In a repo whose thesis is a conformance gate.&lt;/p&gt;

&lt;p&gt;The gate caught its own maker.&lt;/p&gt;

&lt;p&gt;I fixed all four in one commit, each with a regression test I verified by reverting the fix and watching the test fail. But this is the line I wrote in the log afterward, and it's the one I keep coming back to:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Mocks test the code you wrote. Fixtures test the assumption you made. This bug lived in the gap.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A mock returns what you told it to. So a suite of mocks can only ever confirm your own mental model. It re-asserts your assumptions back at you, in green.&lt;/p&gt;

&lt;p&gt;The real contract lives at the boundary with the external service. The only test that touches it is one that actually calls the thing.&lt;/p&gt;

&lt;p&gt;If you're integrating any generative API — spend the tokens on one real end-to-end run early. It's the cheapest bug-finder you'll ever build.&lt;/p&gt;

&lt;p&gt;There was a fifth of the same family, and it's the one I'd hand to a test-design skeptic.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;subject_present&lt;/code&gt; — my Tier-0 check — was declared, marked blocking-class, and evaluated by &lt;em&gt;nothing&lt;/em&gt;. All three runtimes wired it to &lt;code&gt;lambda spec, still: []&lt;/code&gt;, while the pipeline dutifully generated &lt;strong&gt;and billed&lt;/strong&gt; a still for every shot, then stored the empty list it got back.&lt;/p&gt;

&lt;p&gt;A green suite couldn't catch that. Because of one line:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;take&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;passed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;results&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;advisory&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="n"&gt;Status&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FAIL&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A check that returns &lt;strong&gt;no result&lt;/strong&gt; and a check that &lt;strong&gt;passes&lt;/strong&gt; are the same empty list.&lt;/p&gt;

&lt;p&gt;Wiring it to a real &lt;code&gt;qwen-vl-plus&lt;/code&gt; read costs 325 tokens per shot to avoid a 5-second premium clip. I measured it in both directions — present subject and absent — because a check that only ever answers PASS is not a check.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The receipt that made me believe in the thing&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Run &lt;code&gt;3e1f628d4acf&lt;/code&gt;, shot 0, contract &lt;code&gt;camera_motion: static&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The turbo draft passed cleanly at optical-flow magnitude &lt;code&gt;|v|=0.30&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Then the premium &lt;code&gt;wan2.2-t2v-plus&lt;/code&gt; render came back drifting left at &lt;code&gt;|v|=0.92&lt;/code&gt;, and failed the same contract the draft had passed.&lt;/p&gt;

&lt;p&gt;The gate did exactly what it exists for. Rejected the premium clip. Certified the cheaper draft.&lt;/p&gt;

&lt;p&gt;Working as designed — but now my episode was stuck with the lesser render.&lt;/p&gt;

&lt;p&gt;So I built targeted repair.&lt;/p&gt;

&lt;p&gt;Tier-A doesn't just say a check failed. It keeps the per-frame series behind each measurement, so a failure carries a &lt;em&gt;time window&lt;/em&gt;. Here it placed the drift at &lt;strong&gt;0.4s–3.6s&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;That window gives you an anchor: the last good frame, at 0.2s. A frame-anchored Wan model (&lt;code&gt;wan2.2-i2v-flash&lt;/code&gt;) re-renders from that frame forward, Tier-A re-verifies, and a passing patch re-cuts the episode.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;before (premium, take 1)&lt;/th&gt;
&lt;th&gt;after (patch)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;camera_motion&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;FAIL&lt;/strong&gt; — drifting left, `\&lt;/td&gt;
&lt;td&gt;v\&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;flicker / brightness / duration / cuts&lt;/td&gt;
&lt;td&gt;pass&lt;/td&gt;
&lt;td&gt;pass&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Cost: &lt;strong&gt;5 video-seconds&lt;/strong&gt; on the i2v free-tier pool, plus one {% raw %}&lt;code&gt;qwen-plus&lt;/code&gt; repair call.&lt;/p&gt;

&lt;p&gt;The premium look, recovered under contract, by the same gate that rejected it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;My best idea was only half right&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That receipt made me greedy.&lt;/p&gt;

&lt;p&gt;If anchoring on a good frame rescues a &lt;em&gt;broken&lt;/em&gt; clip, why not anchor everything?&lt;/p&gt;

&lt;p&gt;The reasoning felt airtight. Draft, repair, and final were three independent rolls from the same prompt — three separate lotteries — so a certified episode could look like three different films of the same script.&lt;/p&gt;

&lt;p&gt;Anchor the retake on the last good frame. Anchor the promotion on the frame the human approved. Every take of a shot inherits one continuous look.&lt;/p&gt;

&lt;p&gt;Same primitive, generalized. I shipped it.&lt;/p&gt;

&lt;p&gt;Then I ran it on real Wan output. It was wrong in two specific, measurable places.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. An anchor can't fix a defect that has no "before."&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Shot 1 asserts &lt;code&gt;camera_motion: right&lt;/code&gt;. Its first draft came back static — &lt;code&gt;|v| = 0.005&lt;/code&gt; against a &lt;code&gt;0.4&lt;/code&gt; threshold — with Tier-A localizing the failure to &lt;code&gt;fail_window_s [0.0, 5.33]&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The entire clip.&lt;/p&gt;

&lt;p&gt;There's exactly one frame before that window. Frame 0. And anchoring the retake there pinned the exact staticness the retake existed to remove.&lt;/p&gt;

&lt;p&gt;The anchored retake measured &lt;code&gt;|v| = 0.112&lt;/code&gt;. Still a FAIL.&lt;/p&gt;

&lt;p&gt;A fresh &lt;code&gt;t2v&lt;/code&gt; roll on the same repaired prompt reached &lt;code&gt;|v| = 0.745 'right'&lt;/code&gt; and passed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. An anchor frame carries composition. It does not carry motion.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This one I did not see coming.&lt;/p&gt;

&lt;p&gt;I took that approved rightward pan — &lt;code&gt;|v| = 0.745 'right'&lt;/code&gt; — and promoted it by anchoring at &lt;code&gt;0.1s&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The premium final came back panning &lt;strong&gt;the other way&lt;/strong&gt;. &lt;code&gt;|v| = 6.15 'left'&lt;/code&gt;. Failed re-verify.&lt;/p&gt;

&lt;p&gt;A single frame encodes framing, lighting, wardrobe, palette. It encodes nothing about which direction the camera was travelling when that frame was taken.&lt;/p&gt;

&lt;p&gt;So the model just invents one.&lt;/p&gt;

&lt;p&gt;The rule those two measurements produced is now code, not prompt advice:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Anchor to preserve. Re-roll to change.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Concretely: &lt;code&gt;_anchor_for_retake&lt;/code&gt; returns &lt;code&gt;None&lt;/code&gt; when the failure window opens at &lt;code&gt;t = 0&lt;/code&gt;, so a whole-clip defect re-rolls from the corrected prompt instead. And a shot whose contract asserts camera motion &lt;strong&gt;skips promotion entirely&lt;/strong&gt; — the clip that satisfied the contract is the clip that ships.&lt;/p&gt;

&lt;p&gt;That second consequence is my favourite number in the whole project. Look at the ledger for a certified three-shot batch:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Stage&lt;/th&gt;
&lt;th&gt;Calls&lt;/th&gt;
&lt;th&gt;Billed&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;drafting&lt;/code&gt; (&lt;code&gt;wan2.1-t2v-turbo&lt;/code&gt;)&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;20 video-s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;promoting&lt;/code&gt; (&lt;code&gt;wan2.2-i2v-flash&lt;/code&gt;, frame-anchored)&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;2&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;10 video-s&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Three shots certified. &lt;strong&gt;Two&lt;/strong&gt; promotions.&lt;/p&gt;

&lt;p&gt;The missing one is the shot with the motion contract.&lt;/p&gt;

&lt;p&gt;So verification here isn't only rejecting bad output. It's &lt;em&gt;deleting a generation the run would otherwise have paid for&lt;/em&gt;, because measurement proved that generation could only make things worse.&lt;/p&gt;

&lt;p&gt;A quality gate that &lt;strong&gt;reduces&lt;/strong&gt; spend is a much easier thing to sell than one that adds to it.&lt;/p&gt;

&lt;p&gt;Both findings cost one clip each to discover. 10 seconds out of a 600-second budget.&lt;/p&gt;

&lt;p&gt;And notice which half of my idea survived. "Anchor for visual continuity" was right. "Anchoring beats re-rolling" was an unexamined extension of it, and it took two real generations to pull them apart.&lt;/p&gt;

&lt;p&gt;When a primitive works beautifully in the case you built it for, the temptation is to extend it by resemblance.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Every bug I found was the same bug&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Here's the postscript, and it's the most uncomfortable finding in my log.&lt;/p&gt;

&lt;p&gt;The promotion path and the &lt;em&gt;manual&lt;/em&gt; re-render button computed their anchors in two separate places.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;pipeline.py&lt;/code&gt; learned the &lt;code&gt;t=0&lt;/code&gt; rule. &lt;code&gt;patch.py&lt;/code&gt; had its own &lt;code&gt;anchor_second&lt;/code&gt;, which clamped happily to &lt;code&gt;0.0&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;So for another full day, the button in my UI cheerfully offered — and the endpoint faithfully performed — precisely the move I had just measured as useless.&lt;/p&gt;

&lt;p&gt;No test caught it. And the reason is worth stating plainly:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Both surfaces agreed with themselves.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Each was internally consistent. Nothing in the suite asserted they agreed with &lt;em&gt;each other&lt;/em&gt;. It only surfaced because someone finally clicked the button.&lt;/p&gt;

&lt;p&gt;There's a third instance lurking in my deploy runbook. The budget governor wraps &lt;code&gt;gen_video_fn&lt;/code&gt; — but promotion now renders through &lt;code&gt;patch_video_fn&lt;/code&gt;, deliberately unwrapped so anchored work draws the separate i2v pool instead of competing with drafts.&lt;/p&gt;

&lt;p&gt;Correct decision. Unintended consequence: &lt;code&gt;fresh_final_cap&lt;/code&gt; no longer bounds a live run.&lt;/p&gt;

&lt;p&gt;The safety rail didn't break. The thing it guarded moved out from under it.&lt;/p&gt;

&lt;p&gt;Now line up every bug this project has found:&lt;/p&gt;

&lt;p&gt;· a fallback that returns the success value on failure&lt;br&gt;
· a missing result indistinguishable from a passing one&lt;br&gt;
· two code paths deriving the same value independently&lt;br&gt;
· a wrapper whose subject moved&lt;/p&gt;

&lt;p&gt;Not one of them failed loudly.&lt;/p&gt;

&lt;p&gt;Every single one presented as success.&lt;/p&gt;

&lt;p&gt;Which is, uncomfortably, the exact thing my product exists to catch. Generated video ships unverified because a bad clip and a good clip both look like &lt;em&gt;output&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Giving it a voice (and the roster the API won't tell you)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Wan's video models return silent clips. So my certified episode was silent.&lt;/p&gt;

&lt;p&gt;Listing the models available to my key turned up 149 of them, including the &lt;code&gt;qwen3-tts-flash&lt;/code&gt; voice family. A 107-character line synthesizes in 2.4 seconds.&lt;/p&gt;

&lt;p&gt;Easy win. Except for two things.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The twelve-hour episode.&lt;/strong&gt; The returned WAV is &lt;em&gt;streamed&lt;/em&gt;, so its header declares an effectively infinite length. A ~7-second clip reports &lt;strong&gt;44,739 seconds&lt;/strong&gt; to both &lt;code&gt;wave&lt;/code&gt; and &lt;code&gt;ffprobe&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Anything that trusts that header to size the output produces a half-day-long file.&lt;/p&gt;

&lt;p&gt;My assembler survives because &lt;code&gt;-shortest&lt;/code&gt; bounds every segment by its &lt;em&gt;video&lt;/em&gt;, and a paired &lt;code&gt;apad&lt;/code&gt; stops a short narration line from truncating the video the other way. Verified: a 5.00s clip muxed with that 44,739s-declaring WAV comes out at exactly 5.00s.&lt;/p&gt;

&lt;p&gt;Never trust a container's self-reported duration for a stream. Bound it by something you &lt;em&gt;do&lt;/em&gt; know.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The roster you can't list.&lt;/strong&gt; Narration shipped with one hardcoded voice, so every character sounded identical.&lt;/p&gt;

&lt;p&gt;Giving a cast distinct voices means knowing which voices this account may actually use. And the API won't say:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;400 InvalidParameter: Invalid voice specified, the requested voice does not exist
                      or is not licensed for use—please select a supported voice.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That message enumerates nothing.&lt;/p&gt;

&lt;p&gt;And &lt;em&gt;"not licensed for use"&lt;/em&gt; means availability is an &lt;strong&gt;account&lt;/strong&gt; property, not a model property. So the roster has to be probed, not read.&lt;/p&gt;

&lt;p&gt;I fired 20 candidate names at &lt;code&gt;qwen3-tts-flash&lt;/code&gt;. Got 200-with-audio for all 20:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Cherry&lt;/code&gt; · &lt;code&gt;Ethan&lt;/code&gt; · &lt;code&gt;Nofish&lt;/code&gt; · &lt;code&gt;Jennifer&lt;/code&gt; · &lt;code&gt;Ryan&lt;/code&gt; · &lt;code&gt;Katerina&lt;/code&gt; · &lt;code&gt;Elias&lt;/code&gt; · &lt;code&gt;Jada&lt;/code&gt; · &lt;code&gt;Dylan&lt;/code&gt; · &lt;code&gt;Sunny&lt;/code&gt; · &lt;code&gt;Li&lt;/code&gt; · &lt;code&gt;Marcus&lt;/code&gt; · &lt;code&gt;Roy&lt;/code&gt; · &lt;code&gt;Peter&lt;/code&gt; · &lt;code&gt;Rocky&lt;/code&gt; · &lt;code&gt;Kiki&lt;/code&gt; · &lt;code&gt;Eric&lt;/code&gt; · &lt;code&gt;Serena&lt;/code&gt; · &lt;code&gt;Chelsie&lt;/code&gt; · &lt;code&gt;Aiden&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Which brings back the rule from earlier. My script agent emits a &lt;code&gt;speaker&lt;/code&gt; — a character name. The server casts the voice from that probed roster.&lt;/p&gt;

&lt;p&gt;The model &lt;em&gt;cannot&lt;/em&gt; emit an invalid voice, because it never emits a voice at all.&lt;/p&gt;

&lt;p&gt;That closure earns its keep here more than anywhere. Because this failure is &lt;strong&gt;silent&lt;/strong&gt;: an unlicensed voice degrades that shot to silence rather than failing the run. A certified episode would just have a hole in it, and nothing would say so.&lt;/p&gt;

&lt;p&gt;One more detail that's load-bearing. Casting is by &lt;strong&gt;order of first appearance&lt;/strong&gt;, fixed at scripting time — not by hashing the character's name.&lt;/p&gt;

&lt;p&gt;A hash can collide and hand two characters one voice with nothing to signal it. An ordinal is equally deterministic, so a re-run casts identically and every narration cache key still hits.&lt;/p&gt;

&lt;p&gt;That key is &lt;code&gt;sha1(model|voice|text)&lt;/code&gt;. Unstable casting would silently re-synthesize every line on a replay that was supposed to be free.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Making it survive the judges&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A gate is only real if someone can click it. And generated media is slow and quota-sensitive — exactly the wrong properties for a live demo.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A content-addressed cache.&lt;/strong&gt; Identical &lt;code&gt;(model, prompt, seed, size)&lt;/code&gt; requests replay from disk for free:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;billed video-seconds&lt;/th&gt;
&lt;th&gt;wall clock&lt;/th&gt;
&lt;th&gt;shots certified&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Cold (2 uncached finals)&lt;/td&gt;
&lt;td&gt;10 s (~$3.00 est.)&lt;/td&gt;
&lt;td&gt;207 s&lt;/td&gt;
&lt;td&gt;3/3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Warm (everything cached)&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;0 s ($0.00)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;6 s&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;3/3&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Re-certifying real 1080p video costs zero video quota. Across the entire life of this project, my honest end-to-end runs have spent &lt;strong&gt;35 video-seconds. Total. Ever.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A real deployment.&lt;/strong&gt; The backend runs on an Alibaba Cloud Simple Application Server in &lt;code&gt;us-west-1&lt;/code&gt; — nginx serving the SPA on &lt;code&gt;:80&lt;/code&gt;, proxying &lt;code&gt;/api&lt;/code&gt; to a uvicorn app, bind-mounted volume so cache and run-state survive restarts. A push to &lt;code&gt;main&lt;/code&gt; triggers a GitHub Actions job that SSHes into the box, rebuilds, and gates on the health check.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A catalog deliberately kept off the critical path.&lt;/strong&gt; Finished runs publish into a Postgres 18 sidecar with media in a private Alibaba OSS bucket, addressed by content hash.&lt;/p&gt;

&lt;p&gt;It's additive and flag-gated (&lt;code&gt;CATALOG_ENABLED&lt;/code&gt;, default off). Live runs stay on the in-memory store. A run gets mirrored only once it has &lt;em&gt;finished&lt;/em&gt;. Publishing tolerates a dead database or unreachable bucket and never raises.&lt;/p&gt;

&lt;p&gt;Why? Because a storage outage must not fail a run that already passed its gates. The conformance verdict is the product. Archiving it has a lower right to fail.&lt;/p&gt;

&lt;p&gt;One thing bit me immediately, and it's a direct consequence of my own determinism: &lt;strong&gt;media paths are many-to-one against content.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Deterministic runs produce byte-identical episodes. So ~40 project paths collapsed onto 13 objects.&lt;/p&gt;

&lt;p&gt;That's the cache working as designed. It also means the path→hash mapping needs its own &lt;code&gt;media_paths&lt;/code&gt; table — not a column on the object, where it would keep only the last path written and 404 every other one.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fn2q8jhxclmu7t936xwyg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fn2q8jhxclmu7t936xwyg.png" alt=" " width="800" height="340"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The deploy had its own small war stories. A plan upgrade that grew the cloud disk but not the partition inside it — grow the partition &lt;em&gt;first&lt;/em&gt;, then the filesystem, because a filesystem can't stretch past its partition. And the discovery that this box is Alibaba Cloud Linux 3, RHEL-family, so it's &lt;code&gt;dnf&lt;/code&gt;, not &lt;code&gt;apt&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The kind of thing you only learn by actually putting compute on the cloud, instead of calling its APIs from your laptop.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why this isn't just a demo&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The engine has no coupling to the generator, because its checks take &lt;em&gt;frames&lt;/em&gt;, not generator internals.&lt;/p&gt;

&lt;p&gt;So it lifts out. It's exposed as an MCP server — the same primitive coding agents already speak — runnable as a package:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;uvx &lt;span class="nt"&gt;--from&lt;/span&gt; &lt;span class="s1"&gt;'.[mcp]'&lt;/span&gt; dailies-mcp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;ListTools&lt;/code&gt; returns &lt;strong&gt;two&lt;/strong&gt; tools, and the pair is the point:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;run_shot_tests&lt;/code&gt;&lt;/strong&gt; — zero-token, deterministic Tier-A CV, runs on any mp4. The model-agnostic claim, made executable. It &lt;strong&gt;reports&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;patch_clip&lt;/code&gt;&lt;/strong&gt; — localizes the first blocking failure in time, anchors a Wan i2v regeneration just before it, re-verifies, and reports &lt;code&gt;patched&lt;/code&gt; only if the retake passes. It &lt;strong&gt;acts&lt;/strong&gt;, and spends one generation to do it.&lt;/p&gt;

&lt;p&gt;Watching a Qwen agent drive this loop was genuinely satisfying. It calls the free tool. Gets back a real &lt;code&gt;FAIL — camera static, |v|=0.00&lt;/code&gt;. Explains it in plain English. Then &lt;em&gt;offers&lt;/em&gt; the repair — naming it correctly as keyframe-to-video generation, which it only knows because &lt;code&gt;ListTools&lt;/code&gt; handed it &lt;code&gt;patch_clip&lt;/code&gt;'s description.&lt;/p&gt;

&lt;p&gt;It never fires it, because its system message forbids the tool that spends quota.&lt;/p&gt;

&lt;p&gt;A gate an agent can read is a gate an agent can act on.&lt;/p&gt;

&lt;p&gt;Both ends of that loop are mine. Dailies is an MCP &lt;em&gt;producer&lt;/em&gt;, and the client consuming it is a Qwen-Agent &lt;code&gt;Assistant&lt;/code&gt; with my own server in its &lt;code&gt;mcpServers&lt;/code&gt; block.&lt;/p&gt;

&lt;p&gt;That same engine is reachable three ways — a native function-calling tool, a Qwen-Agent custom skill via &lt;code&gt;@register_tool&lt;/code&gt;, and the MCP server — over one shared core that imports neither &lt;code&gt;openai&lt;/code&gt; nor &lt;code&gt;qwen_agent&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Let me be honest about the edges, because the whole ethos here is not claiming what the engine can't do.&lt;/p&gt;

&lt;p&gt;Assertions are per-shot and evaluated whole-clip. There's no audio transcript check, no OCR, no time-windowing (a "logo in the first 3 seconds" check), no episode-level concept yet.&lt;/p&gt;

&lt;p&gt;When a rule needs a modality the vocabulary lacks, the compiler &lt;strong&gt;omits it rather than approximating&lt;/strong&gt; it with a type that means something else. Known gap: that omission is currently silent.&lt;/p&gt;

&lt;p&gt;Those are roadmap, not shipped features.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What Qwen Cloud actually gave me&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The integration splits along a line the platform draws for you, and picking the right side per capability is most of what "sophisticated use" means here.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;OpenAI-compatible endpoint&lt;/strong&gt; (&lt;code&gt;dashscope-intl.aliyuncs.com/compatible-mode/v1&lt;/code&gt;) fronts everything text- and vision-shaped. &lt;code&gt;qwen-plus&lt;/code&gt; for scripting, repair, and both function-calling loops. &lt;code&gt;qwen-vl-plus&lt;/code&gt; for Tier-0 and Tier-B verdicts.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;native DashScope task API&lt;/strong&gt; handles the media models, because generation is long-running and the OpenAI-compatible shape has no vocabulary for it. &lt;code&gt;wan2.1-t2v-turbo&lt;/code&gt; drafts, &lt;code&gt;wan2.2-i2v-flash&lt;/code&gt; frame-anchored finals and repairs, &lt;code&gt;wan2.1-t2i-plus&lt;/code&gt; Tier-0 stills, &lt;code&gt;qwen3-tts-flash&lt;/code&gt; narration.&lt;/p&gt;

&lt;p&gt;Video generation is &lt;em&gt;mandatorily&lt;/em&gt; asynchronous — create with &lt;code&gt;X-DashScope-Async: enable&lt;/code&gt;, then poll. And it carries a gotcha I'm very glad I found on day one, at zero cost:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;HTTP 200 on create does not mean the request was valid.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Validation surfaces asynchronously, on the first poll. So retries must branch on the polled &lt;code&gt;task_status&lt;/code&gt;, never the POST's status code. (The image endpoint, confusingly, validates &lt;em&gt;synchronously&lt;/em&gt; and returns a 400.)&lt;/p&gt;

&lt;p&gt;One more finding I'd reuse anywhere: the video endpoints accept a base64 &lt;code&gt;data:&lt;/code&gt; URI in place of an image URL. That's what my entire repair feature depends on, because a frame extracted on a &lt;code&gt;127.0.0.1&lt;/code&gt; box has no public URL and now needs no upload step.&lt;/p&gt;

&lt;p&gt;And notice what's &lt;em&gt;missing&lt;/em&gt; from that model list. The deterministic tier.&lt;/p&gt;

&lt;p&gt;Tier-A is OpenCV. It calls nothing. The Qwen surface gets spent on generation and judgment — never on measurement.&lt;/p&gt;

&lt;p&gt;Which is the whole reason measurement can run on every take.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key Takeaways:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Test the artifact, not the prompt.&lt;/strong&gt; Orchestrating models is only half the problem, and it's the easy half. The hard half — the one almost nobody demos — is deciding &lt;em&gt;when not to call the expensive model&lt;/em&gt;, and being able to prove with a number that the thing you didn't render was one you were right to reject.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;A mock can only confirm your own mental model.&lt;/strong&gt; It returns what you told it to, so a suite of mocks re-asserts your assumptions back at you in green. The real contract lives at the boundary with the external service. If you're integrating any generative API, spend the tokens on one real end-to-end run &lt;em&gt;early&lt;/em&gt;. Cheapest bug-finder you'll ever build.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Let the model choose, never let it spell.&lt;/strong&gt; Don't validate the model's output — make invalid output unrepresentable. Ask what the model actually needs to &lt;em&gt;decide&lt;/em&gt;, which is almost always far less than what you're asking it to &lt;em&gt;emit&lt;/em&gt;. A closed vocabulary, a parameter contract, a probed roster: three shapes a bad value can't fit through.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Generalize by measurement, not by resemblance.&lt;/strong&gt; My best idea worked beautifully in the case I built it for, so I extended it everywhere by analogy. Two real generations proved half of it wrong. The failure mode isn't that the primitive is bad — it's that you've silently changed what you're asking it to preserve.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Watch for the bugs that present as success.&lt;/strong&gt; A fallback returning the success value. A missing result that reads as a passing one. Two code paths deriving the same value independently. A wrapper whose subject moved. None of these fail loudly, and green tests love them.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;So, here's the recap:&lt;/p&gt;

&lt;p&gt;· AI video fails in motion, after you've already paid for it&lt;br&gt;
· The fix isn't better prompts — it's a spec you can assert against&lt;br&gt;
· Deterministic checks first, model judgment on top, never underneath&lt;br&gt;
· Verification doesn't just reject bad output; sometimes it deletes spend&lt;br&gt;
· Every bug worth finding looked like success first&lt;/p&gt;

&lt;p&gt;Dailies is open source (MIT), built for Track 2 of the Global AI Hackathon Series with Qwen Cloud, and deployed on Alibaba Cloud.&lt;/p&gt;

&lt;p&gt;Go test your generated video like you test your code.&lt;/p&gt;

&lt;p&gt;Happy shipping!&lt;/p&gt;

</description>
      <category>qwen</category>
      <category>alibaba</category>
      <category>cloud</category>
      <category>ai</category>
    </item>
    <item>
      <title>How to contribute to a large codebase?</title>
      <dc:creator>Kaung Zin Hein</dc:creator>
      <pubDate>Thu, 03 Oct 2024 03:19:56 +0000</pubDate>
      <link>https://dev.to/zin_kg/how-to-contribute-to-a-large-codebase-2ho0</link>
      <guid>https://dev.to/zin_kg/how-to-contribute-to-a-large-codebase-2ho0</guid>
      <description>&lt;p&gt;&lt;em&gt;A step-by-step guide on contributing to open-source projects with thousands of lines of code&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;As a budding open-source contributor, I was at a loss when I found a lack of resources on how to get started. Other than a few good guides, most of the advice is general and, often, shallow. &lt;strong&gt;I felt like the concrete steps were brushed off and left to the readers to figure out for themselves.&lt;/strong&gt; Which, in a sense, makes for a great learning experience. At the same time, I felt overwhelmed by the number of projects on GitHub, by the number of issues in major projects. &lt;/p&gt;

&lt;p&gt;Even for a developer with years of experience, approaching a new codebase takes domain-specific knowledge and patience. On top of that, errors thrown when navigating through the code maze may not even be due to a lack of skills - &lt;strong&gt;poorly documented build guides, platform incompatibility&lt;/strong&gt;, etc., may explain why the repository you just cloned doesn’t work.&lt;/p&gt;

&lt;p&gt;With that said, a pre-requisite before diving into a large codebase is to get familiar with contributing to small-to-medium-sized repositories. The best projects to contribute to are ones you’re most knowledgeable about, ones that you’re most familiar with. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;But here’s the catch.&lt;/strong&gt; A lot of what we use daily may not be a simple library that solves one thing. It may well be a full-blown framework or a full-stack application. That’s why it’s important to have honed in on the foundational concepts and the semantics of your language. I don’t mean mastery - which is a continuous pursuit, rather than an accomplishment - I’m referring to an &lt;strong&gt;attempt&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Your attempt at trying to master something.&lt;/strong&gt; For example, I wrote a few &lt;a href="https://www.npmjs.com/settings/zin_kg/packages" rel="noopener noreferrer"&gt;npm modules&lt;/a&gt; to better familiarize myself with the native Node.js APIs. Why Node.js? Because my goal was/is contribute and learn from other web technologies built on the Javascript ecosystem. I’ll talk more about writing utilities in another guide. &lt;/p&gt;

&lt;p&gt;For now, here’s my approach when dealing with a large open-source repository:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Use the tool so you understand, what some call, the business problem.&lt;/strong&gt;&lt;br&gt;
&lt;em&gt;How is it helping customers or developers?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The ideal project to contribute to is one whose API you’ve been using regularly. Whose functions and classes you know well enough to integrate it into your applications and other projects. Familiarity with the public implementations lend itself to understanding the internal code better. If it’s a project you’re completely new to but are willing to dig into, the “Getting Started” guide from the official docs is a great starting point. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Start with the &lt;em&gt;what&lt;/em&gt;.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Reading a codebase in general terms (the main functions, the entry point, the layers, etc.) is a good practice. But what’s even more effective? A targeted approach. &lt;/p&gt;

&lt;p&gt;Trying to solve an issue and following the code trail that the problem leads to, may not cover as many lines of code as passively reading, but it puts to test your understanding of a small subset of the repository. Here's a task for you: open an issue you’ve run into (ideal) or pick up a manageable issue. This approach, &lt;strong&gt;compounded over time, issues, and PRs&lt;/strong&gt;, can lead to deeper understanding. &lt;/p&gt;

&lt;p&gt;It’s tricky to define ‘manageable’ because not every project owner assigns ‘good-first-issue’ or ‘up-for-grabs’ labels. And depending on the project, even issues with those beginner-friendly tags may still seem daunting. Which brings us to the next step.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Analyze how existing modules and tests are set up.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Take those as reference in laying out the structure of your code and tests. For example, when adding a new plugin, study how other integrations are written and copy the outline of the corresponding tests.&lt;/p&gt;

&lt;p&gt;Doing so ensures that you’re following best practices that are &lt;strong&gt;specific&lt;/strong&gt; to the repository at hand and staying in sync with other contributors’ code style.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Write down the build and test process.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Note-taking doesn’t get the credit it deserves especially in the software development circle. That’s because note-taking is a skill many haven’t mastered yet, or not willing to try at all. &lt;/p&gt;

&lt;p&gt;Instead of looking for &lt;strong&gt;patterns&lt;/strong&gt;, some mark everything down, quickly leading to burnout. Building and testing are processes at the core of most projects. They are the steps you take after making any sort of change. If you’re dealing with a repository more than once (not a &lt;a href="https://opensauced.pizza/blog/yolo-coder" rel="noopener noreferrer"&gt;YOLO contribution&lt;/a&gt;), it’s worth the time to jot down exactly how a change in the code is tested. &lt;/p&gt;

&lt;p&gt;Likewise, in a mono-repo, you don’t want to waste time trying to build and test every package when the changes you’ve made only affect one or a few. But wait, can’t the compiling and testing for one package be done via a script each? Probably yes. But when you’re fiddling with more than a single package and their workspace dependencies, the processes tend to involve a couple of steps. &lt;/p&gt;

&lt;p&gt;The practice is beneficial in 2 main ways: &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A)&lt;/strong&gt; When you return to an issue after taking a break, all the steps you’d taken last time are right before you. So, &lt;strong&gt;you can focus on the problem-solving part immediately&lt;/strong&gt;, instead of trying to recall what you did the last time for building/testing/modifying configs. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;B)&lt;/strong&gt; When tackling a similar issue, you can follow the same process, instead of figuring out the steps from scratch. This saves time! Which matters a lot when your goal is to ship quality features/fixes as quick as possible. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Apply forensics on the commit history of a particular block of code.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When figuring out why a piece of code is implemented, reviewing not only the related PRs, but also the surrounding discussion (comments, reviews, linked issues/PRs) leaves clues - &lt;strong&gt;often outright solutions&lt;/strong&gt;. This step helps you learn about the thought process and the decisions that were formed by other contributors before you arrived. For example, you can check why the author introduced a new utility function or how a bug was fixed. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;6. Take feedback from maintainers/major contributors to heart.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;No one’s more familiar with the codebase than those who’ve spent months and years working on it. Try to fix the pain points that they’ve brought up, especially in a code review. &lt;/p&gt;

&lt;p&gt;On the other hand, don’t be too sorry to point out their misunderstanding of the intent of your code or to state your doubt on their arguments. Open-minded senior devs are willing to elaborate and are, well, open to feedback themselves. &lt;/p&gt;




&lt;h2&gt;
  
  
  Summary with Actions
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. Use the product/library/framework.&lt;/strong&gt;&lt;br&gt;
Action: If it’s not a tool you’re already familiar with, try it out to get the hang of it. Start from the official docs. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Follow a bottom-up approach.&lt;/strong&gt;&lt;br&gt;
Action: Open or pick up an issue. Analyze the necessary code files and functions as you try to solve the issue. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Look at the structure of existing modules and tests.&lt;/strong&gt;&lt;br&gt;
Action: Analyze and apply a similar (or sometimes the same) structure to your code.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Write down the build and test process.&lt;/strong&gt;&lt;br&gt;
Action: Record how exactly you compile and test the code involved in your PR. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Learn from the past.&lt;/strong&gt;&lt;br&gt;
Action: Review the commit history and the related conversations, code reviews, and comments. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;6. Accept constructive feedback.&lt;/strong&gt;&lt;br&gt;
Action: Review and try to resolve the code reviews from senior contributors. Don’t hesitate to explain any misunderstanding.  &lt;/p&gt;

&lt;p&gt;Happy contributing!&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>community</category>
      <category>github</category>
    </item>
    <item>
      <title>Filtering in ExpressJS</title>
      <dc:creator>Kaung Zin Hein</dc:creator>
      <pubDate>Fri, 16 Aug 2024 23:29:16 +0000</pubDate>
      <link>https://dev.to/zin_kg/filtering-in-expressjs-8ng</link>
      <guid>https://dev.to/zin_kg/filtering-in-expressjs-8ng</guid>
      <description>&lt;p&gt;How I implemented the filter feature in my volunteer management application&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This article is part of the series explaining the principles and algorithms implemented in my capstone web application project. You can check out the app &lt;a href="https://volunteer-mern.vercel.app/" rel="noopener noreferrer"&gt;here&lt;/a&gt;. Or view the &lt;a href="https://github.com/Zen-cronic/volun-mern" rel="noopener noreferrer"&gt;source code&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;A major ingredient for modern management applications (be it content, e-commerce, customer, or financial) is the filter feature, alongside sorting and searching. Here’s how I’ve implemented it in my web app. It filters volunteer events in the backend, according to the filter category sent by the client.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzoce1yf6ipaet4xitzig.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzoce1yf6ipaet4xitzig.png" alt="Filtering for events located externally (outside the organization) and with open shift positions&lt;br&gt;
" width="800" height="406"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The goal here is to build a custom filter feature using what Express can offer, without depending on any third-party library. So, I decided to make use of the request-response lifecycle and the “locals” property of the response.&lt;/p&gt;

&lt;p&gt;Following the modern MCV architecture for ExpressJS applications, I’ve refactored the previous code by separating business logic from the controller. This logic is contained in service functions. Let’s take a look at the filter controller first.&lt;/p&gt;
&lt;h2&gt;
  
  
  Filter events controller
&lt;/h2&gt;

&lt;p&gt;This controller is an array of request handlers, each wrapped in an express-async-handler function to manage asynchronous errors. Its length depends on the number of filter categories that are stored as constants. As of now, these are:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Event date (date)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Event venue (venue)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Events with open positions (isOpen)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Events that are happening in the future (isUpcoming)&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Plus, the service function of the last handler is responsible for curating the filtered results (event IDs) from the above 4 filters and sorting each result based on how many filter categories it falls under. So, I’ve got an array of 5 request handlers.&lt;/p&gt;

&lt;p&gt;Let’s examine the request handler for the event venue category (venue).&lt;/p&gt;
&lt;h2&gt;
  
  
  Filter Events by Venue
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;filterEventsHandler&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="c1"&gt;//venue filter&lt;/span&gt;
  &lt;span class="nf"&gt;asyncHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nf"&gt;objKeysIncludes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;FILTER_OPTIONS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;VENUE&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;venue&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;locals&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;filteredVenue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;filterEventsByVenue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;venue&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}),&lt;/span&gt;

&lt;span class="c1"&gt;//...more handlers &lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Inside the handler, there’s a helper function that checks whether or not req.body (sent from the client) includes the category “venue”. This function serves as a form of data validation for the user input.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;objKeysIncludes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;checked&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;obj&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;)){&lt;/span&gt;
        &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Obj param must be an object&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;checked&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If it’s included, the value of the venue is extracted (e.g., {venue: “External”}), after which it’s processed by the service that filters events by venue. The result is an array of event IDs, which are then stored in res.locals property. The data/variable stored() in res.locals is not shared between requests as they belong only to the current request-response cycle. If the client didn’t include the “venue” filter, this request handler is skipped by returning the next function.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nf"&gt;objKeysIncludes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;FILTER_OPTIONS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;VENUE&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;venue&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;locals&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;filteredVenue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;filterEventsByVenue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;venue&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Even after storing the filtered result in res.locals, next has to be called, moving on to the following handler that checks for another filter category.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final Handler
&lt;/h2&gt;

&lt;p&gt;After repeating this process for all categories, we arrive at the last handler. Its service function (filterEvents) sorts all the filtered event IDs from res.locals, attaches the filter tags that each event belongs to, and returns a sorted array of events based on the number of tags.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;  &lt;span class="c1"&gt;//sorted filter&lt;/span&gt;
  &lt;span class="nf"&gt;asyncHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;filteredResultsByKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;filteredAllIds&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;idsWithTags&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;sortedIdsWithTags&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;filterEvents&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;locals&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="nx"&gt;filteredResultsByKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;filteredAllIds&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;idsWithTags&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;sortedIdsWithTags&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}),&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let’s see how it works.&lt;/p&gt;

&lt;p&gt;The values of the properties in &lt;code&gt;res.locals&lt;/code&gt; stored by the preceding filter handlers are assigned to respective variables. Object destructing is not used because the client may not have selected all filter categories, making these variables undefined.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;filterEvents&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;filterObj&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;resLocals&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;filteredVenue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;resLocals&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;filteredVenue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;filteredDate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;resLocals&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;filteredDate&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;filteredIsOpen&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;resLocals&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;filteredIsOpen&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;filteredIsUpcoming&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;resLocals&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;filteredIsUpcoming&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;//...&lt;/span&gt;
&lt;span class="nx"&gt;Then&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;filteredResultsByKey&lt;/span&gt; &lt;span class="nx"&gt;object&lt;/span&gt; &lt;span class="nx"&gt;is&lt;/span&gt; &lt;span class="nx"&gt;declared&lt;/span&gt; &lt;span class="nx"&gt;which&lt;/span&gt; &lt;span class="nx"&gt;will&lt;/span&gt; &lt;span class="nx"&gt;house&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;filter&lt;/span&gt; &lt;span class="nf"&gt;category &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;g&lt;/span&gt;&lt;span class="p"&gt;.,&lt;/span&gt; &lt;span class="nx"&gt;venue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;isOpen&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;and&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;corresponding&lt;/span&gt; &lt;span class="nx"&gt;filtered&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;property&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="nx"&gt;See&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;example&lt;/span&gt; &lt;span class="nx"&gt;below&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;where&lt;/span&gt; &lt;span class="nx"&gt;each&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt; &lt;span class="nx"&gt;ID&lt;/span&gt; &lt;span class="nx"&gt;qualifies&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;selected&lt;/span&gt; &lt;span class="nx"&gt;venue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;

&lt;span class="c1"&gt;// {"venue": [id1, id2, id3]}&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;filteredResultsByKey&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;

&lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;filterObj&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;filterKey&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;switch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;filterKey&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="nx"&gt;FILTER_OPTIONS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;DATE&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nx"&gt;filteredResultsByKey&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;filteredResultsByKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;filterKey&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="nx"&gt;filteredDate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;};&lt;/span&gt;
        &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

      &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="nx"&gt;FILTER_OPTIONS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;IS_OPEN&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nx"&gt;filteredResultsByKey&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;filteredResultsByKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;filterKey&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="nx"&gt;filteredIsOpen&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;};&lt;/span&gt;

        &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

      &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="nx"&gt;FILTER_OPTIONS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;VENUE&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;// filteredResultsByKey[filterKey] = filteredVenue&lt;/span&gt;

        &lt;span class="nx"&gt;filteredResultsByKey&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;filteredResultsByKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;filterKey&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="nx"&gt;filteredVenue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;};&lt;/span&gt;

        &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

      &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="nx"&gt;FILTER_OPTIONS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;IS_UPCOMING&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nx"&gt;filteredResultsByKey&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;filteredResultsByKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;filterKey&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="nx"&gt;filteredIsUpcoming&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;};&lt;/span&gt;

      &lt;span class="nl"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, the property values of filteredResultsByKey are turned into a 1-D array (from a 2-D array). This service function returns an array of event IDs, each with only one occurrence, which is stored in the filteredAllIds variable.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;filteredAllIds&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;filterArrSortLoose&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;values&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;filteredResultsByKey&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;//filterArrSortLoose helper&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;filterArrSortLoose&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;twoDArr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;twoDArr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;every&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isArray&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;each elem must be an arr - an arr of arr&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;oneDArr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;twoDArr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;flatMap&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;matchIds&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;

  &lt;span class="nx"&gt;oneDArr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;matchIds&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;matchIds&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;matchIds from loose filter: &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;matchIds&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;matchIds&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Filter Tags
&lt;/h2&gt;

&lt;p&gt;Finally, it’s time for the most challenging task yet. Assign filter tags to each event ID. To do so, we need to relate the filteredResultsByKey object and filteredAllIds array, resulting in an idsWithTags array.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;//filteredResultsByKey&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="nl"&gt;filterKey1&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;id1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;id2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;id3&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="nx"&gt;filterKey2&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;id3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;id1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;id4&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;//filteredAllIds&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;id1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;id2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;id3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;id4&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="c1"&gt;//filteredResultsByKey + filteredAllIds -&amp;gt; idsWithTags&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;
 &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;id1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="na"&gt;filterKey1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;filterValue&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;filterKey2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;filterValue&lt;/span&gt;&lt;span class="p"&gt;}]&lt;/span&gt;
 &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;id2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="na"&gt;filterKey2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;filterValue&lt;/span&gt;&lt;span class="p"&gt;}]},&lt;/span&gt;
 &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;id3&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="na"&gt;filterKey1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;filterValue&lt;/span&gt;&lt;span class="p"&gt;}]}.&lt;/span&gt;
 &lt;span class="p"&gt;...&lt;/span&gt;
 &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Remember that an event ID can appear under more than one filter category. In this case, we assign all the associated filter tags to the event ID object.&lt;/p&gt;

&lt;p&gt;In the following nested loop, the outer loop iterates over all filtered IDs, and the inner loop runs through each entry of the filteredResultsByKey object.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;  &lt;span class="nx"&gt;filteredAllIds&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;entries&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;filteredResultsByKey&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(([&lt;/span&gt;&lt;span class="nx"&gt;filterKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;filterKeyVal&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;entries&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;filterObj&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;filterKey&lt;/span&gt;
      &lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;//...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For each event ID, we must find the corresponding filter category it belongs to by iterating through each entry in the filteredResultsByKey and cross-checking with req.body (filterObj).&lt;/p&gt;

&lt;p&gt;If the key from the &lt;code&gt;req.body&lt;/code&gt; equals the current key of &lt;code&gt;filteredResultsByKey&lt;/code&gt;, we access the value of the key (e.g., in &lt;code&gt;{date: “2023–12–31”&lt;/code&gt;, 2023–12–31 is the value). This filter category value (filterKeyVal object) and the filter key are appended as a filter tag for each qualifying event ID.&lt;/p&gt;

&lt;p&gt;If the current event id (outer loop) is included in a property array of filteredResultsByKey (inner), there are two possible scenarios:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;The event ID object is already included in the idsWithTags array, which means the event qualifies for more than one filter category.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The event ID object is not included yet.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Both scenarios are determined by finding in the idsWithTags array an object whose eventId property has the same value as the current event id. The responsible helper function returns an index number if found, and -1 if not found.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;isEventIdAlrExists&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;elemObjPropValIncludes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="nx"&gt;idsWithTags&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;eventId&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="nx"&gt;id&lt;/span&gt;
        &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="c1"&gt;//...&lt;/span&gt;

&lt;span class="c1"&gt;//helper to determine if current event ID is already in idsWithTags&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;elemObjPropValIncludes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;propKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;checkedPropVal&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;


    &lt;span class="c1"&gt;//propKey must exists in all objs in the array&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;obj&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;hasOwn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nx"&gt;propKey&lt;/span&gt;&lt;span class="p"&gt;)))){&lt;/span&gt;

        &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`all elem obj in the arr must contain propKey: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;propKey&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; : as a property key`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;


    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;included&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findIndex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;obj&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;propKey&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;checkedPropVal&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;included&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nx"&gt;Dealing&lt;/span&gt; &lt;span class="kd"&gt;with&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;second&lt;/span&gt; &lt;span class="nx"&gt;scenario&lt;/span&gt; &lt;span class="nx"&gt;is&lt;/span&gt; &lt;span class="nx"&gt;simple&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="nx"&gt;We&lt;/span&gt; &lt;span class="nx"&gt;just&lt;/span&gt; &lt;span class="nx"&gt;push&lt;/span&gt; &lt;span class="nx"&gt;an&lt;/span&gt; &lt;span class="nx"&gt;object&lt;/span&gt; &lt;span class="kd"&gt;with&lt;/span&gt; &lt;span class="err"&gt;“&lt;/span&gt;&lt;span class="nx"&gt;eventId&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt; &lt;span class="nx"&gt;and&lt;/span&gt; &lt;span class="err"&gt;“&lt;/span&gt;&lt;span class="nx"&gt;filterTags&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt; &lt;span class="nx"&gt;entries&lt;/span&gt; &lt;span class="nx"&gt;into&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;parent&lt;/span&gt; &lt;span class="nx"&gt;array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;

 &lt;span class="nx"&gt;idsWithTags&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
            &lt;span class="na"&gt;eventId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;filterTags&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;filterKey&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="nx"&gt;filterKeyVal&lt;/span&gt; &lt;span class="p"&gt;}],&lt;/span&gt;
          &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For the first case, however, there’s an extra step involved. We must map through the idsWithTags array until we arrive at the current event. Then, reassign that event ID object with the additional filter category entry it belongs to.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;bufferArr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;idsWithTags&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

            &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;eventId&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

              &lt;span class="nx"&gt;event&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="na"&gt;filterTags&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
                  &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;filterTags&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;filterKey&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="nx"&gt;filterKeyVal&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
                &lt;span class="p"&gt;],&lt;/span&gt;
              &lt;span class="p"&gt;};&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;

            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
          &lt;span class="p"&gt;});&lt;/span&gt;

          &lt;span class="nx"&gt;idsWithTags&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;bufferArr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After assigning tags to each event, we must sort them in descending order based on the number of tags. At the end of the request-response cycle, this final handler returns &lt;code&gt;sortedIdsWithTags&lt;/code&gt; to the client. It’s now the front-end’s job to manage how the events with filtered tags will be displayed.&lt;/p&gt;

&lt;p&gt;That’s it! That’s how I’ve implemented filtering in my Express API using the nature of the request-response cycle and &lt;code&gt;res.locals&lt;/code&gt; property.&lt;/p&gt;

&lt;p&gt;The key takeaways I got from coming up with this feature are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Request-response cycle&lt;/li&gt;
&lt;li&gt;Modular middleware and the role of &lt;code&gt;next()&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Data Validation&lt;/li&gt;
&lt;li&gt;Higher Order functions&lt;/li&gt;
&lt;li&gt;Filtering logic!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Further improvements in the future:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use Map and Set for a simpler data structure&lt;/li&gt;
&lt;li&gt;Implementing Bloom’s filter algorithm&lt;/li&gt;
&lt;li&gt;You can interact with the app live &lt;a href="https://volunteer-mern.vercel.app/" rel="noopener noreferrer"&gt;here&lt;/a&gt;. Or view the code on my &lt;a href="https://github.com/Zen-cronic/volun-mern" rel="noopener noreferrer"&gt;GitHub repo&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

</description>
    </item>
    <item>
      <title>Why write a library?</title>
      <dc:creator>Kaung Zin Hein</dc:creator>
      <pubDate>Fri, 03 May 2024 04:01:54 +0000</pubDate>
      <link>https://dev.to/zin_kg/why-write-a-library-4ceb</link>
      <guid>https://dev.to/zin_kg/why-write-a-library-4ceb</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a blog version of the talk I gave at &lt;a href="https://www.linkedin.com/company/torontojs/"&gt;TorontoJS&lt;/a&gt; Lightning Talks event on Apr 30, 2024.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzicy4szz0l9gmsx08xpb.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzicy4szz0l9gmsx08xpb.jpg" alt="Me at talk event, intro slide" width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  My technical pet peeve
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh7vmgyh5dpuvx9gzhiwd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh7vmgyh5dpuvx9gzhiwd.png" alt="console-log" width="800" height="156"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This &lt;em&gt;irritates&lt;/em&gt; me - typing a variable’s name beside the variable in the log statement. It isn’t that big of a problem for just a few variables here and there. But many variables multiplied by many files in your app? You do the math. &lt;/p&gt;

&lt;p&gt;That's when I realized writing my own &lt;a href="https://github.com/Zen-cronic/scope-logger"&gt;logging library&lt;/a&gt; could save me some headaches.&lt;/p&gt;

&lt;h2&gt;
  
  
  The rant continues...
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsyppqe2w415nu35x5vig.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsyppqe2w415nu35x5vig.png" alt="Many logs to comment and delete" width="678" height="398"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, who enjoys commenting out or deleting log statements before pushing their code to production? I &lt;em&gt;really&lt;/em&gt; don't. &lt;/p&gt;

&lt;p&gt;Fortunately, there are tools available to solve this such as the  &lt;a href="https://github.com/debug-js/debug"&gt;&lt;code&gt;debug&lt;/code&gt; library&lt;/a&gt; which is based on the core NodeJS logging utility. &lt;/p&gt;

&lt;p&gt;We already have a solution. So why bother? Let’s take a look at my personal use case: &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5qodu2hfka2dcik4wb73.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5qodu2hfka2dcik4wb73.png" alt="A variable logged inside nested functions" width="800" height="495"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;More often than not, a variable is logged from within nested function calls, and across multiple files. When I wanted to quickly check from where a variable is being logged (that happens after you’re debugging and have called it a day and you return to it later), I would write the metadata (the function name) &lt;strong&gt;next&lt;/strong&gt; to the log variable. &lt;/p&gt;

&lt;p&gt;Instead of a quick check, this process became quickly &lt;em&gt;tedious&lt;/em&gt;. Here was a use case that i hadn't found any JS library addressing (as far as I know).&lt;/p&gt;

&lt;h2&gt;
  
  
  Time to &lt;em&gt;modify&lt;/em&gt; the wheel!
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftxq3zycdcgs1t5i4y1s1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftxq3zycdcgs1t5i4y1s1.png" alt="My library in action" width="800" height="488"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So, I decided to write a &lt;a href="https://github.com/Zen-cronic/scope-logger"&gt;module&lt;/a&gt; that logs the value of the variable alongside its name without having to type the name manually. And I'll share with you how I did it from scratch. &lt;/p&gt;

&lt;p&gt;Of course, this can be done using &lt;code&gt;console.log()&lt;/code&gt; with the object destructing &lt;code&gt;{ }&lt;/code&gt; property. &lt;/p&gt;

&lt;p&gt;But what &lt;code&gt;console.log()&lt;/code&gt; lacks is the ability to print the &lt;strong&gt;function scopes&lt;/strong&gt; of the logged variable in a developer-friendly way. Here's the output: &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvk655or0g8s1bnq4nwy9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvk655or0g8s1bnq4nwy9.png" alt="My library's output" width="789" height="170"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;By &lt;strong&gt;developer-friendly&lt;/strong&gt;, I mean anyone seeing this log message in their terminal can immediately tell the function scope of the variable being logged. The order of function scopes is parsed from the call stack provided by the NodeJS stack trace API. Hence the name, &lt;a href="https://github.com/Zen-cronic/scope-logger"&gt;&lt;em&gt;scope-logger&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note: “Object.” just means the outermost function is invoked from the global object/topmost level of the file.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Here's the recipe on how to write a library by studying others (in pseudo-code!): &lt;/p&gt;

&lt;h2&gt;
  
  
  Steps.length = 4
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgf1i1izih6hiwlu6w745.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgf1i1izih6hiwlu6w745.png" alt="Library making steps in pseudo-code" width="772" height="552"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 0: Just build it!
&lt;/h2&gt;

&lt;p&gt;“Zero” not only because we are programmers, also because it’s one fundamental step before taking any further. You must be building the Minimum Viable Product (&lt;strong&gt;MVP&lt;/strong&gt;) as soon as possible, or at the very least, a small chunk of it. &lt;/p&gt;

&lt;p&gt;You’re &lt;strong&gt;not&lt;/strong&gt; striving for perfection. You just need a working version.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Start small
&lt;/h2&gt;

&lt;p&gt;As a reference, pick a small library with similar use cases to your idea. &lt;br&gt;
Here’s my criteria for selecting one: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Popular&lt;/strong&gt;: not because it’s the new kid on the block, but because it’s been well-maintained for a long while with a large, active user-base.  &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Well-tested&lt;/strong&gt;: because quality is important - look for integration/e2e tests and unit tests.  &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Challenging enough for analysis&lt;/strong&gt;: you don’t wanna be tackling the Express framework or React on your first go. Pick a library that is considerably smaller, which you can determine by the following factor.   &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Number of dependencies&lt;/strong&gt;: one way to tell if a library is &lt;strong&gt;not&lt;/strong&gt; too challenging to be used as study source is based on the production dependencies count. The fewer the better. For example, I chose &lt;a href="https://github.com/debug-js/debug"&gt;&lt;code&gt;debug&lt;/code&gt;&lt;/a&gt; because it only has 1 dependency (&lt;a href="https://github.com/vercel/ms"&gt;ms&lt;/a&gt;), while the rest of the code relies on core NodeJS modules - which is exactly what I was looking for - to learn how to build a library from scratch, not off the shelf libraries with many external deps, which in turn are based on more deps. There you go, dependency hell.  &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 2: Break it down smaller
&lt;/h2&gt;

&lt;p&gt;After you’ve picked a library, break it down even smaller. Study how the main functions work by replicating their behaviors: &lt;strong&gt;isolate&lt;/strong&gt; those functions, provide input, and see the output.&lt;/p&gt;

&lt;p&gt;This is one of the few times that you should allow yourself to fall into &lt;strong&gt;rabbit holes&lt;/strong&gt;, and really understand the in’s and out’s of each line of code in a function.&lt;/p&gt;

&lt;p&gt;For example: &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flhty7tjo2kzdtm4q7apt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flhty7tjo2kzdtm4q7apt.png" alt="debugjs formatArgs function" width="800" height="443"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is the &lt;code&gt;formatArgs()&lt;/code&gt; function of the &lt;a href="https://github.com/debug-js/debug"&gt;&lt;code&gt;debug&lt;/code&gt;&lt;/a&gt; library. By isolating it, I learned about ANSI colour escape codes, and where and how the properties of one debug instance is used (&lt;code&gt;namespace&lt;/code&gt;, &lt;code&gt;useColours&lt;/code&gt;, and &lt;code&gt;this.colour&lt;/code&gt;)&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: Publish
&lt;/h2&gt;

&lt;p&gt;After you’ve studied other approaches and built your own module, all there's left to do is hit publish, right? Well, not before you complete these three things. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Semantic Versioning&lt;/strong&gt;: for every update (major, minor, or patch) made, increment the version number according to &lt;a href="https://semver.org/"&gt;semantic versioning&lt;/a&gt;. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Changelog/history&lt;/strong&gt;: track and display the updates you’ve made so far - the version number, the date you published it, and a brief description of those changes.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnnhdpfn4h4ee7askboud.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnnhdpfn4h4ee7askboud.png" alt="scope-logger changelog/history" width="550" height="778"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Documentation&lt;/strong&gt;: You cannot expect other developers to magically figure out how to use your library without detailed descriptions of the features. It also serves as a roadmap of what you’ve built. You can either dedicate a whole website for it or simply fill in the &lt;a href="https://github.com/Zen-cronic/scope-logger/#readme"&gt;README.md&lt;/a&gt; file.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Note: I left out &lt;strong&gt;tests&lt;/strong&gt; because we should be writing them as the library is being built, not just before hitting publish.&lt;/em&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  Recipe Recap
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Zero&lt;/strong&gt;: you build a working version.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;One&lt;/strong&gt;: start small by picking a small but challenging enough library to learn from&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Two&lt;/strong&gt;: analyze that library by breaking it down into even smaller pieces&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Three&lt;/strong&gt;: after attaching semantic versioning, changelog, and documentation, hit publish. &lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Breaks are Great!
&lt;/h2&gt;

&lt;p&gt;These steps are in a loop, repeated until it’s time for a &lt;strong&gt;break&lt;/strong&gt;, which is just as important as the preceding steps. &lt;/p&gt;

&lt;p&gt;As a rule of thumb, after publishing your major or minor version, or several patch updates in a row, take your &lt;em&gt;well-deserved&lt;/em&gt; break!&lt;/p&gt;

&lt;p&gt;Taking a break is great for discovering more use cases as you use the library/module you just made in other projects. &lt;/p&gt;

&lt;p&gt;As you might’ve guessed, I did use &lt;a href="https://github.com/Zen-cronic/scope-logger"&gt;&lt;code&gt;scope-logger&lt;/code&gt;&lt;/a&gt; to develop other modules. By doing so, I found features that I &lt;em&gt;really&lt;/em&gt; needed, not just stuff that I thought would be cool to have.&lt;/p&gt;

&lt;p&gt;When a particular use case keeps popping up, that’s my &lt;strong&gt;cue&lt;/strong&gt; to update the library with a new feature to address it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Takeaways:
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Solve your own problems first&lt;/strong&gt;: As a budding developer, how do you go about determining what projects to pursue? The idea for this library occurred to me as I was building projects for my portfolio. With limited industry connections and programming know-how to cater to a target audience, I felt stuck. But there lurked a hidden opportunity. If you're in the same boat, try this: &lt;em&gt;ditch the latest trends, and double down on understanding the nuts and bolts of one technology, to tackle a problem that's currently bogging &lt;strong&gt;you&lt;/strong&gt; down&lt;/em&gt;. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Reinvent the wheel, sometimes&lt;/strong&gt;: And to solve your developer problem, contrary to conventional advice, you must reinvent the wheel to understand in-depth how the wheel is built. In the long haul, the &lt;strong&gt;time&lt;/strong&gt; and &lt;strong&gt;effort&lt;/strong&gt; put into studying a great library, and building one using core modules and fundamental programming principles, is what’s gonna make you &lt;em&gt;stand out&lt;/em&gt;. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Depth &amp;amp;&amp;amp; Breadth (not versus)&lt;/strong&gt;: With that said, depth is &lt;strong&gt;not&lt;/strong&gt; the superior path. Tread both. The &lt;em&gt;breadth&lt;/em&gt; part involves exploring other libraries, studying their differences, and observing patterns that show up repeatedly. &lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;




&lt;p&gt;So, I invite you to try this project idea - create a library by studying great examples. As slow as it may seem, your programming craft will grow exponentially. &lt;/p&gt;

</description>
      <category>library</category>
      <category>node</category>
      <category>javascript</category>
    </item>
  </channel>
</rss>
