DEV Community

Cover image for Pattern-Coding with Time: Phase-Synced Software Generation Across Languages (with BINFLOW)
Peace Thabiwa
Peace Thabiwa

Posted on

Pattern-Coding with Time: Phase-Synced Software Generation Across Languages (with BINFLOW)

đź§­ Pattern-Coding with Time: Phase-Synced Software Generation Across Languages (with BINFLOW)

Build software as a living rhythm instead of a pile of files.
Generate Python/TypeScript/Rust/Go code from the same time-labeled patterns, keep devs in flow, and let the system evolve without losing coherence.


Why this matters (for senior builders)

We’re great at structure (DDD, hexagonal, clean architecture), but we’re still shipping code like it’s a static snapshot. Teams lose context across sprints, microservices drift, and “rewrites” nuke alignment.

BINFLOW (time-labeled binary) gives us a way to encode when/why a unit exists, not just what it is. When you attach phase + time to patterns and components, you can:

  • Generate consistent multi-language services from the same pattern definition
  • Orchestrate work in phases (Focus, Loop, Transition, Emergence…)
  • Keep developers “in the game” with a Phase Sync Maker that aligns code, docs, tests, and prompts to the current phase of work

This post ships a concrete blueprint + code you can adapt today.


Core concepts (quick mental model)

  • BINFLOW Phase — minimal rhythm ontology:

    • focus (implement) · loop (iterate/tests) · transition (refactor/migrate) · pause (stabilize) · emergence (R&D spike)
  • Pattern — language-agnostic template for a capability (REST service, queue worker, vector indexer, etc.)

  • Phase Sync Maker (PSM) — a tiny CLI + spec that renders patterns into language stacks, phase-aware

  • Resonance Profile — per-dev preferences (dense code vs verbose, strict types vs flexible) used at generation time

  • Time Labels — every artifact carries (timestamp, phase) in metadata and commit trailers for lineage


Repo shape (monorepo or polyrepo)

flow/
  patterns/                 # language-agnostic templates
    rest-service/
      manifest.yml
      templates/
        python/
          main.py.hbs
          pyproject.toml.hbs
        typescript/
          src/index.ts.hbs
          package.json.hbs
        rust/
          src/main.rs.hbs
          Cargo.toml.hbs
        go/
          main.go.hbs
      tests/
        contract.md.hbs
  phase/
    phase.config.yml        # team rhythms, gating rules
    workflows/
      focus.yml
      loop.yml
      transition.yml
  tools/
    psm/                    # Phase Sync Maker (CLI)
      psm.py
  services/                 # generated code lands here
Enter fullscreen mode Exit fullscreen mode

Pattern Manifest (language-agnostic)

patterns/rest-service/manifest.yml

pattern: rest-service
version: 0.4
inputs:
  name: string
  stack: enum[python, typescript, rust, go]
  domain: string
  routes:
    - path: string
      method: enum[GET,POST,PUT,DELETE]
      schema: jsonschema
phase_overrides:
  focus:
    testing: minimal
    logging: concise
  loop:
    testing: contract+property
    logging: verbose
  transition:
    migrations: true
  emergence:
    feature_flags: allow_experimental
outputs:
  artifacts:
    - code
    - tests
    - openapi
    - runbook
binflow:
  phase_trailers: true   # add trailers to commits
Enter fullscreen mode Exit fullscreen mode

Generate the same service in 4 languages (Phase-aware)

CLI (PSM):

psm gen rest-service \
  --name inventory-api \
  --stack python \
  --domain inventory \
  --routes '[
    {"path":"/items","method":"GET","schema":{"type":"object"}},
    {"path":"/items","method":"POST","schema":{"type":"object"}}
  ]' \
  --phase focus \
  --resonance dense
Enter fullscreen mode Exit fullscreen mode

Python (FastAPI) output (excerpt)

services/inventory-api-python/main.py

# @binflow: phase=focus ts=2025-10-25T08:10:00Z
from fastapi import FastAPI
from pydantic import BaseModel

app = FastAPI(title="inventory-api", version="0.1.0")

class Item(BaseModel):
    id: str | None = None
    name: str
    qty: int = 0

@app.get("/items")
def list_items():
    # focus: minimal path to green
    return {"items": []}

@app.post("/items")
def create_item(item: Item):
    return {"ok": True, "item": item}
Enter fullscreen mode Exit fullscreen mode

TypeScript (Express) output (excerpt)

services/inventory-api-ts/src/index.ts

// @binflow: phase=focus ts=2025-10-25T08:10:00Z
import express from "express";
const app = express();
app.use(express.json());

app.get("/items", (_req, res) => res.json({ items: [] }));
app.post("/items", (req, res) => res.json({ ok: true, item: req.body }));

app.listen(3000, () => console.log("inventory-api up on 3000"));
Enter fullscreen mode Exit fullscreen mode

Rust (Axum) output (excerpt)

// @binflow: phase=focus ts=2025-10-25T08:10:00Z
use axum::{routing::{get, post}, Json, Router};
use serde::{Deserialize, Serialize};

#[derive(Serialize, Deserialize)]
struct Item { id: Option<String>, name: String, qty: i32 }

#[tokio::main]
async fn main() {
    let app = Router::new()
        .route("/items", get(list_items))
        .route("/items", post(create_item));

    axum::Server::bind(&"0.0.0.0:3000".parse().unwrap())
        .serve(app.into_make_service()).await.unwrap();
}

async fn list_items() -> Json<serde_json::Value> {
    Json(serde_json::json!({"items":[]}))
}
async fn create_item(Json(item): Json<Item>) -> Json<serde_json::Value> {
    Json(serde_json::json!({"ok":true,"item":item}))
}
Enter fullscreen mode Exit fullscreen mode

Go (Chi) output (excerpt)

// @binflow: phase=focus ts=2025-10-25T08:10:00Z
package main

import (
  "encoding/json"
  "net/http"
  "github.com/go-chi/chi/v5"
)

type Item struct { ID *string `json:"id,omitempty"`; Name string `json:"name"`; Qty int `json:"qty"` }

func main() {
  r := chi.NewRouter()
  r.Get("/items", func(w http.ResponseWriter, r *http.Request) {
    json.NewEncoder(w).Encode(map[string]any{"items":[]Item{}})
  })
  r.Post("/items", func(w http.ResponseWriter, r *http.Request) {
    var it Item; _ = json.NewDecoder(r.Body).Decode(&it)
    json.NewEncoder(w).Encode(map[string]any{"ok":true,"item":it})
  })
  http.ListenAndServe(":3000", r)
}
Enter fullscreen mode Exit fullscreen mode

Phase-aware twist:
In focus we generate the thinnest “green path.”
Switch to loop and PSM injects contract tests, richer logging, request/response validation, and property tests (quickcheck/proptest/fast-check), per language.


Phase Sync Maker (PSM) — tiny CLI spec

tools/psm/psm.py (sketch):

#!/usr/bin/env python3
import json, os, sys, datetime
from jinja2 import Environment, FileSystemLoader
from pathlib import Path

PHASE = os.getenv("BINFLOW_PHASE", "focus")
TS = datetime.datetime.utcnow().isoformat() + "Z"

def render(pattern, stack, ctx):
    env = Environment(loader=FileSystemLoader(f"patterns/{pattern}/templates/{stack}"))
    outdir = Path(f"services/{ctx['name']}-{stack}")
    outdir.mkdir(parents=True, exist_ok=True)
    for tpl in env.list_templates():
        if not tpl.endswith(".hbs"): continue
        txt = env.get_template(tpl).render(**ctx, binflow={"phase":PHASE,"ts":TS})
        dest = outdir / tpl.replace(".hbs","")
        dest.parent.mkdir(parents=True, exist_ok=True)
        dest.write_text(txt)

if __name__ == "__main__":
    # read args (omit for brevity)
    payload = json.loads(sys.stdin.read())
    render("rest-service", payload["stack"], payload)
Enter fullscreen mode Exit fullscreen mode

Phase rules (merge during render):

  • focus: minimal deps, minimal logs, smoke tests only
  • loop: add contract/property tests, structured logs, OpenAPI validator
  • transition: migration scripts, changelog, deprecation adapters
  • emergence: feature-flagged branches, telemetry experiments

Temporal tests (stop shipping ghost regressions)

Tests that understand time and validate phase transitions, not just outputs.

TypeScript (Vitest + fast-check)

import { fc } from "fast-check";
import { derivePhase } from "../src/phase"; // your phase function

describe("phase transitions", () => {
  it("eventually leaves focus within N commits", () => {
    fc.assert(fc.property(fc.array(fc.string(), {minLength:3, maxLength:30}), (events) => {
      let phase = "focus";
      let left = false;
      for (const e of events) {
        phase = derivePhase(phase, e);
        if (phase !== "focus") { left = true; break; }
      }
      return left;
    }), { numRuns: 50 });
  });
});
Enter fullscreen mode Exit fullscreen mode

Python (Hypothesis)

from hypothesis import given, strategies as st
from phase import derive_phase

@given(st.lists(st.text(min_size=1), min_size=3, max_size=30))
def test_focus_does_not_stick_forever(events):
    phase = "focus"; moved = False
    for e in events:
        phase = derive_phase(phase, e)
        if phase != "focus":
            moved = True; break
    assert moved
Enter fullscreen mode Exit fullscreen mode

Commit trailers + CI phase gates

Git trailer:

git commit -m "Add POST /items" -m "Phase: focus" -m "Binflow-TS: 2025-10-25T08:14:21Z"
Enter fullscreen mode Exit fullscreen mode

GitHub Actions: .github/workflows/loop.yml

name: binflow-loop
on:
  push:
    branches: [ main ]
jobs:
  loop-tests:
    if: "contains(github.event.head_commit.message, 'Phase: loop')"
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with: { node-version: '20' }
      - run: npm ci && npm run test:contracts
Enter fullscreen mode Exit fullscreen mode

Policy: PRs marked Phase: transition must show migration scripts; Phase: emergence must be behind feature flags. Make it non-negotiable via CI.


Keeping programmers “in the game”

  • Resonance profiles: generator respects personal style (tabs/spaces, log density, error ergonomics).
  • Phase-aware prompts: your AI assistant reviews only what’s relevant to this phase, not the whole repo.
  • Pattern catalogs: senior devs codify best practice once; PSM replicates it safely across stacks.
  • Side-by-side diffs: compare Python vs Rust generation of the same pattern to spot semantic drift.

Example: add a queue worker (all stacks, 1 command)

psm gen queue-worker \
  --name stock-updater \
  --stack rust \
  --domain inventory \
  --topic inventory.stock.changed \
  --phase loop
Enter fullscreen mode Exit fullscreen mode

Generates:

  • Consumer loop + backoff
  • Schema validators (serde/jsonschema)
  • Contract tests for message shape
  • Structured logs & metrics (phase-aware verbosity)

Switch to --stack typescript or --stack go and get equivalent behavior with TS (zod/ajv) or Go (go-playground/chi + testcontainers).


Migration play: transition phase recipe

When APIs change:

  1. Mark PR Phase: transition
  2. PSM generates compat adapters (old → new), deprecation headers, DB migrations
  3. CI enforces that adapters exist and tests cover both versions
  4. After rollout, PR Phase: pause to codify the new baseline docs

Tooling you can wire in today

  • Templates: Jinja2/Handlebars/Nunjucks
  • Contracts: OpenAPI + JSON Schema → generate types/clients in all languages
  • Property tests: fast-check (TS), Hypothesis (Py), proptest/quickcheck (Rust), gopter (Go)
  • Tracing: OpenTelemetry; include phase & ts in spans
  • Feature flags: OpenFeature/Unleash; only activate in emergence

TL;DR for your team

  • Define patterns once (REST, queue, batch, vector).
  • Generate per-language code phase-aware.
  • Enforce phase gates in CI so cadence stays sane.
  • Keep devs in flow with resonance profiles and time-aware tests.
  • Treat software as rhythm + patterns, not static files.

BINFLOW gives you the missing axis: time.
PSM makes it practical.


Call to action

If you want this as a starter repo (PSM CLI + patterns + workflows), say the word — I’ll package a minimal, batteries-included template you can clone and extend with your own patterns and stacks.

Top comments (0)