Track C: Codex with GPT-6.1-Terra end to end

agent

+11:50

The revised recipes are now being rendered through the last few expressions. I’m also checking that any second-round changes stay confined to the intended face presentation rather than altering body geometry.

  • write_stdinpoll session 61266

    input

    const r=await tools.write_stdin({session_id:61266,chars:"",yield_time_ms:50000,max_output_tokens:3000});text(JSON.stringify(r));
    

    result, 4 lines

    Script running with cell ID 33
    Wall time 31.0 seconds
    Output:
    
  • waitcell 33

    input

    {
      "cell_id": "33",
      "yield_time_ms": 20000
    }

    result, 4 lines

    Script completed
    Wall time 2.7 seconds
    Output:
    {"chunk_id":"fb2045","wall_time_seconds":35.624325656,"exit_code":0,"original_token_count":151,"output":"arm_f_slender ~/Projects/lowmarch-bench/work/c/shot_r1/surprised/painted_arm_f_slender.png 14s\narm_m_youth ~/Projects/lowmarch-bench/work/c/shot_r1/surprised/painted_arm_m_youth.png 13s\narm_f_slender ~/Projects/lowmarch-bench/work/c/shot_r1/wink/painted_arm_f_slender.png 16s\narm_m_youth ~/Projects/lowmarch-bench/work/c/shot_r1/wink/painted_arm_m_youth.png 16s\nshot r1\n~/Projects/lowmarch-bench/work/c/sheet_r1_woman.png (1968, 1144)\n~/Projects/lowmarch-bench/work/c/sheet_r1_youth.png (1968, 1144)\n2026-10-30T12:56:54+08:00\n"}
  • view_image~/Projects/lowmarch-bench/work/c/sheet_r1_woman.png (+1 more)

    input

    const results=await Promise.all([
    tools.view_image({path:"~/Projects/lowmarch-bench/work/c/sheet_r1_woman.png",detail:"original"}),
    tools.view_image({path:"~/Projects/lowmarch-bench/work/c/sheet_r1_youth.png",detail:"original"})
    ]);for(const r of results)image(r.image_url);
    

    result, 4 lines

    Script completed
    Wall time 0.2 seconds
    Output:
    
    sheet_r1_woman.png
    sheet_r1_woman.png
    sheet_r1_youth.png
    sheet_r1_youth.png
  • view_image~/Projects/lowmarch-bench/work/c/shot_r1/joy/painted_arm_m_youth.png (+2 more)

    input

    const r=await Promise.all([
    tools.view_image({path:"~/Projects/lowmarch-bench/work/c/shot_r1/joy/painted_arm_m_youth.png",detail:"original"}),
    tools.view_image({path:"~/Projects/lowmarch-bench/work/c/shot_r1/sad/painted_arm_f_slender.png",detail:"original"}),
    tools.view_image({path:"~/Projects/lowmarch-bench/work/c/shot_r1/wink/painted_arm_m_youth.png",detail:"original"})
    ]);for(const x of r)image(x.image_url);
    

    result, 4 lines

    Script completed
    Wall time 0.1 seconds
    Output:
    
    shot_r1_joy_youth.png
    shot_r1_joy_youth.png
    shot_r1_sad_woman.png
    shot_r1_sad_woman.png
    shot_r1_wink_youth.png
    shot_r1_wink_youth.png
  • exec_commandsource ~/Projects/lowmarch-bench/kit/env-c.sh && sed -n '690,730p' tools/vroid_portrait.py && rg -n 'eye=|iris=|arm_m_youth|arm_f_slender' tools/heads.py art/cast/cast.py review/vroid-02/build.py | head -100 && sed -n '810,850p' tools/vroid_portrait.py && rg -n 'draw_curve_mouth|mouth' tools/export_glb.py | head -60

    command

    source ~/Projects/lowmarch-bench/kit/env-c.sh && sed -n '690,730p' tools/vroid_portrait.py && rg -n 'eye=|iris=|arm_m_youth|arm_f_slender' tools/heads.py art/cast/cast.py review/vroid-02/build.py | head -100 && sed -n '810,850p' tools/vroid_portrait.py && rg -n 'draw_curve_mouth|mouth' tools/export_glb.py | head -60

    result, 114 lines

    Script completed
    Wall time 0.2 seconds
    Output:
        tex = tex.astype(float)
        tex[..., :3] *= (1 - dark)[..., None]
        v._img[src] = np.clip(tex, 0, 255).astype(np.uint8)
    
    
    def reshape(prims, roles, lm, sh):
        """Face length, sculpting, eye size/tilt and mouth width (skeleton and expression are applied
        earlier, when the primitives are built)."""
        ey, cy = lm["eye_y"], lm["chin"][1]
        span = ey - cy
        if sh["face_len"]:
            from vrm import bone_weight
            for p, r in zip(prims, roles):
                if r in SCULPT_ROLES:
                    t = np.clip((ey - p["pos"][:, 1]) / span, 0, None)
                    d = sh["face_len"] * span * np.minimum(t, 1.0)
                    if r == "body" and "J" in p:            # the neck below the head stays where the clothes were fitted
                        d = d * np.clip(bone_weight(p, ("Head",)), 0, 1)
                    p["pos"][:, 1] -= d
            lm = dict(lm, chin=lm["chin"] - [0, sh["face_len"] * span, 0])
        sculpt(prims, roles, lm, sh)
        for p, r in zip(prims, roles):
            P = p["pos"]
            if sh["mouth"] != 1.0 and r == "mouth":
                P[:, 0] = lm["mouth"][0] + (P[:, 0] - lm["mouth"][0]) * sh["mouth"]
            if r in ("iris", "highlight") and sh.get("iris", 1.0) != 1.0:      # smaller irises read older
                for c in (lm["eyeL"], lm["eyeR"]):
                    side = (P[:, 0] < 0) if c[0] < 0 else (P[:, 0] >= 0)
                    q = P[side] - c
                    q[:, :2] *= sh["iris"]
                    P[side] = c + q
            if r in ("iris", "white", "highlight", "line") and (sh["eye"] != 1 or sh["eye_tilt"]):
                for c in (lm["eyeL"], lm["eyeR"]):
                    side = (P[:, 0] < 0) if c[0] < 0 else (P[:, 0] >= 0)
                    q = P[side] - c
                    q[:, :2] *= sh["eye"]
                    q[:, 1] += sh["eye_tilt"] * np.sign(c[0]) * q[:, 0] * 0.4
                    P[side] = c + q
    
    
    class Portrait:
    tools/heads.py:636:        start = dict(dict(eye=1.0, iris=1.0, mouth=1.0), **spec.get("sculpt", {}))     # where each control starts
    art/cast/cast.py:258:    "arm_m_youth": _head("young", hair="g", z=0.4, g=0.6),
    art/cast/cast.py:259:    "arm_f_slender": _head("young", hair="j", j=1),
    art/cast/cast.py:268:                "arm_m_heavy": "brown", "arm_m_brute": "black", "arm_m_old": "grey", "arm_m_youth": "blond",
    art/cast/cast.py:269:                "arm_f_slender": "blond", "arm_f_average": "brown", "arm_f_strong": "red", "arm_f_sexy": "black",
    art/cast/cast.py:271:EYE_COLOURS = {"arm_m_heroic": "blue", "arm_f_sexy": "green", "arm_f_slender": "blue", "arm_m_old": "grey",
    art/cast/cast.py:272:               "arm_f_old": "grey", "arm_m_youth": "amber"}
    art/cast/cast.py:290:    "arm_m_youth": ("Man, youth", "m", "ref_m_youth", dict(relax=4)),
    art/cast/cast.py:291:    "arm_f_slender": ("Woman, slender", "f", "ref_f_slender", dict(relax=4, bust_shape=dict(spread=0.008, drop=0.005, flat=0.25))),
    art/cast/cast.py:308:        shape=dict(eye=1.14, head=0.93, neck=1.14, chest=1.10, shoulders=1.28, arms=1.10, torso=1.06,
    art/cast/cast.py:347:                        mh=MH_BRUTE, beard=("full", 0.06), age_lines=0.4, iris=0.88, blush=0.3,
    art/cast/cast.py:352:                            mh=MH_F_VETERAN, age_lines=0.5, iris=0.84, blush=0.0, mouth=1.05,
    art/cast/cast.py:385:                        skin="fair", mh=MH_BRUTE, beard=("full", 0.06), age_lines=0.4, iris=0.88, blush=0.3,
    art/cast/cast.py:417:                   eye=0.92, neck=1.2, chest=1.06, rest={"Fcl_EYE_Close": 0.2, "Fcl_BRW_Angry": 0.35}),
    art/cast/cast.py:423:                   nose=0.4, nose_w=1.0, eye=0.95, mouth=1.15, neck=1.45, chest=1.18,
    art/cast/cast.py:429:        shape=dict(head=1.05, face_len=-0.08, jaw=-0.3, chin_len=-0.3, eye=1.08, neck=0.85, chest=0.92),
    art/cast/cast.py:439:        shape=dict(face_len=0.06, jaw=-0.3, chin_len=0.3, eye=0.95, eye_tilt=0.25, mouth=0.9,
            neck = (Wn[names["J_Bip_C_Neck"]][:3, 3], Wn[names["J_Bip_C_Head"]][:3, 3]) \
                if "J_Bip_C_Neck" in names and "J_Bip_C_Head" in names else None
            face_normals(self.prims, self.roles, lm_now, sh["face_normals"], sh["hair_normals"], neck=neck)
            for pc, rl in shadow_cards(self.prims, self.roles, lm_now, sh["shadow_cards"], neck):
                self.prims.append(pc)
                self.roles.append(rl)
            if pose is not target_pose and any(not np.allclose(pose.get(k_, np.eye(4)), target_pose.get(k_, np.eye(4)))
                                               for k_ in set(pose) | set(target_pose)):
                repose(self.v, [p for p in self.prims if not p.get("world")], pose, target_pose)
            names = self.v.nodes_by_name()
            Wn = self.v.node_world()
            self.eye = (Wn[names["J_Adj_L_FaceEye"]][:3, 3] + Wn[names["J_Adj_R_FaceEye"]][:3, 3]) / 2
            self.chin_y = self.lm["chin"][1]
            self.tex = {}
            for k, p in enumerate(self.prims):
                if self.roles[k] in ("line", "brow", "iris", "highlight", "white", "hair", "mouth"):
                    src = self._hair_v if (hair_from and "_HAIR" in p["material"]) else self.v
                    t = src.material_texture(p["mi"])
                    if t is not None and self.roles[k] == "line":
                        # VRoid's upper lid is a thick graded band over the iris; keep its dark core only
                        t = t.copy()
                        t[..., 3] = np.where(t[..., :3].mean(-1) < LID_CORE, t[..., 3], 0)
                    if t is not None:
                        self.tex[k] = t
            # painted face marks (lip line, nose) from the face texture, grown so they survive the vote
            from scipy.ndimage import binary_dilation, label
            self.marks = {}
            self.mouth_pts = None
            self.mouth_curve = None
            for k, p in enumerate(self.prims):
                if self.roles[k] != "face":
                    continue
                t = self.v.material_texture(p["mi"])
                if t is None:
                    continue
                th, tw = t.shape[:2]
                vv, uu = np.mgrid[0:th, 0:tw]
                vv, uu = (vv + 0.5) / th, (uu + 0.5) / tw
                win = ((uu > MARK_WINDOW["u"][0]) & (uu < MARK_WINDOW["u"][1])
                       & (vv > MARK_WINDOW["v"][0]) & (vv < MARK_WINDOW["v"][1]))
                raw = (t[..., :3].mean(-1) / 255 < FACE_MARK) & (t[..., 3] > 0) & win
    5:the viewer can toggle and x-ray them. Face, eye, line, brow, mouth and hair keep VRoid's textures
    18:TEXTURED = ("face", "iris", "white", "highlight", "line", "brow", "mouth", "hair")
    22:             "grass": "c", "dirt": "f", "stone": "l", "mouth": "2", "line": "o", "iris": "s", "white": "w",
    31:    if role in ("face", "body", "shadow", "iris", "white", "highlight", "line", "brow", "mouth"):
    185:    bands per role, the lights, body colliders, cloth grids and the mouth curve (model space,
    197:             "mouth": dict(mode="flat", color=hexp("1")), "white": dict(mode="flat", color=hexp("w")),
    227:    if getattr(portrait, "mouth_curve", None) is not None:
    232:        _, i = cKDTree(allp).query(portrait.mouth_curve)
    233:        curve = ((portrait.mouth_curve + alln[i] * 0.0015) * FLIP).tolist()
    237:        img = Image.fromarray(np.where(m == 1, 128, 0).astype(np.uint8), "L")     # nose mark only; the mouth is a line
    269:                mouth_curve=curve, mouth_bone="J_Bip_C_Head", ink=dict(o=hexp("o"), skin=hexp("1"), hair=hexp("A")),
    

agent

+12:53

The sheets show clearer angry and surprised brows, but the first-round sad and angry mouths read almost flat, and the youth’s wink still looks half open. I’m revising those shapes, strengthening the eyelid closure, and reducing the brow overlay before the next comparison.

  • exec_commandsource ~/Projects/lowmarch-bench/kit/env-c.sh && cat >> "$WORK/NOTES.md" <<'EOF'

    command

    source ~/Projects/lowmarch-bench/kit/env-c.sh && cat >> "$WORK/NOTES.md" <<'EOF'
    
    ## Round 1 — 12:44:40–12:56:54 (12m 14s)
    
    Separated brows, eyes and mouths in the recipes, keeping neutral and the basic vowel targets; added a depth-limited brow-over-bangs pass. The reference relies on clear brow/eyelid silhouettes and distinct mouth shapes, so the recipes aim for independent acting instead of the stock ALL controls. The first capture stopped partway through, so completed the missing images with a resumable copy of the kit script.
    
    The sheets and 30-degree views show more legible angry, sad and surprised brows, but the overlay is too strong, particularly at neutral. Sad and angry mouths are nearly flat; youth joy and wink retain visible iris/white through the nearly closed lids. The 30-degree views retain the expressions but expose the same eyelid problem. Surprise is smaller than intended; I is a slightly clearer opening than before.
    EOF
    python3 - <<'PY'
    from pathlib import Path
    p=Path('review/vroid-02/index.html')
    s=p.read_text().replace('col = mix(col, brow.rgb, 0.85);','col = mix(col, brow.rgb, 0.55);')
    p.write_text(s)
    p=Path('art/expressions/armory.txt')
    s=p.read_text().replace('Fcl_EYE_Joy:1;Fcl_MTH_Joy:0.8','Fcl_EYE_Joy:1;Fcl_EYE_Close:0.35;Fcl_MTH_Joy:0.8').replace('Fcl_MTH_Down:0.8','Fcl_MTH_Angry:1').replace('Fcl_MTH_Down:0.7','Fcl_MTH_Sorrow:1').replace('Fcl_MTH_O:0.45','Fcl_MTH_O:0.7').replace('Fcl_EYE_Close_R:1;','Fcl_EYE_Close_R:1.5;')
    p.write_text(s)
    PY
    cp art/expressions/armory.txt "$WORK/expr_list.txt" && $KIT/build_expr.sh "$WORK/expr_list.txt" joy angry sad surprised wink && date -Is

    result, 4 lines

    Script completed
    Wall time 1.2 seconds
    Output:
    {"chunk_id":"9780b4","wall_time_seconds":1.001765008,"session_id":53935,"original_token_count":0,"output":""}
  • write_stdinpoll session 53935

    input

    const r=await tools.write_stdin({session_id:53935,chars:"",yield_time_ms:50000,max_output_tokens:3000});text(JSON.stringify(r));
    

    result, 4 lines

    Script running with cell ID 38
    Wall time 31.0 seconds
    Output:
    
  • waitcell 38

    input

    {
      "cell_id": "38",
      "yield_time_ms": 20000
    }

    result, 4 lines

    Script completed
    Wall time 13.5 seconds
    Output:
    {"chunk_id":"66006a","wall_time_seconds":46.339387279,"exit_code":0,"original_token_count":22,"output":"built joy\nbuilt angry\nbuilt sad\nbuilt surprised\nbuilt wink\n2026-10-30T12:58:19+08:00\n"}
  • exec_commandsource ~/Projects/lowmarch-bench/kit/env-c.sh && $KIT/shoot_expr.sh "$LOWMARCH_REPO/review/vroid-02/index.html" r2 && $KIT/sheets.sh r2 'Round 2: softer brows and eyelid and mouth revisions' && date -Is

    command

    source ~/Projects/lowmarch-bench/kit/env-c.sh && $KIT/shoot_expr.sh "$LOWMARCH_REPO/review/vroid-02/index.html" r2 && $KIT/sheets.sh r2 'Round 2: softer brows and eyelid and mouth revisions' && date -Is

    result, 4 lines

    Script completed
    Wall time 1.2 seconds
    Output:
    {"chunk_id":"1aa7d4","wall_time_seconds":1.001800269,"session_id":25485,"original_token_count":0,"output":""}
  • write_stdinpoll session 25485

    input

    const r=await tools.write_stdin({session_id:25485,chars:"",yield_time_ms:50000,max_output_tokens:3000});text(JSON.stringify(r));
    

    result, 4 lines

    Script running with cell ID 40
    Wall time 31.0 seconds
    Output:
    
  • waitcell 40

    input

    {
      "cell_id": "40",
      "yield_time_ms": 20000
    }

    result, 4 lines

    Script completed
    Wall time 17.3 seconds
    Output:
    {"chunk_id":"dcdaca","wall_time_seconds":50.000953243,"session_id":25485,"original_token_count":0,"output":""}
  • view_image~/Projects/lowmarch-bench/work/c/shot_r2/angry/painted_arm_f_slender.png

    input

    const im=await tools.view_image({path:"~/Projects/lowmarch-bench/work/c/shot_r2/angry/painted_arm_f_slender.png",detail:"original"});image(im.image_url);
    

    result, 4 lines

    Script completed
    Wall time 0.0 seconds
    Output:
    
    shot_r2_angry_woman.png
    shot_r2_angry_woman.png

agent

+15:00

The second angry close-up now has a distinct frown, and the softened brow is less dominant. I’m watching for a separate limitation: some closed mouth lines are very faint in the painted renderer.

  • exec_commandsource ~/Projects/lowmarch-bench/kit/env-c.sh && sed -n '850,920p' tools/vroid_portrait.py && sed -n '215,245p' tools/export_glb.py && rg -n 'mouth_curve|mouthCurve|mouthBone|mouth_bone|mouth' review/vroid-02/index.html | head -70

    command

    source ~/Projects/lowmarch-bench/kit/env-c.sh && sed -n '850,920p' tools/vroid_portrait.py && sed -n '215,245p' tools/export_glb.py && rg -n 'mouth_curve|mouthCurve|mouthBone|mouth_bone|mouth' review/vroid-02/index.html | head -70

    result, 107 lines

    Script completed
    Wall time 0.3 seconds
    Output:
                raw = (t[..., :3].mean(-1) / 255 < FACE_MARK) & (t[..., 3] > 0) & win
                grown = binary_dilation(raw, iterations=MARK_GROW) & win
                # 2 = mouth (dark line), 1 = nose mark (one tone softer)
                self.marks[k] = np.where(grown, np.where(vv >= MARK_WINDOW["nose_below"], 2, 1), 0).astype(np.uint8)
                if self.mouth_pts is None and raw.any():
                    lab, n = label(raw)
                    if n:
                        widths = [np.ptp(np.nonzero(lab == i)[1]) for i in range(1, n + 1)]
                        ys, xs = np.nonzero(lab == 1 + int(np.argmax(widths)))
                        th, tw = raw.shape
                        ends = [(xs.min() + 0.5, ys[xs == xs.min()].mean()), (xs.max() + 0.5, ys[xs == xs.max()].mean()),
                                (xs.mean(), ys.mean())]
                        face_prims = [q for q, r in zip(self.prims, self.roles) if r == "face"]
                        pts = [uv_to_3d(face_prims, (ex / tw, ey / th)) for ex, ey in ends]
                        if pts[0] is not None and pts[1] is not None:
                            if pts[2] is None:
                                pts[2] = (pts[0] + pts[1]) / 2
                            self.mouth_pts = pts
                        # the painted line's centre, traced across: a 3D curve that hugs the lips
                        lab_m = lab == 1 + int(np.argmax(widths))
                        curve = []
                        for x_ in np.linspace(xs.min(), xs.max(), 24):
                            col = np.nonzero(lab_m[:, int(round(x_))])[0]
                            if len(col):
                                q = uv_to_3d(face_prims, ((x_ + 0.5) / tw, (col.mean() + 0.5) / th))
                                if q is not None:
                                    curve.append(q)
                        self.mouth_curve = np.array(curve) if len(curve) >= 4 else None
    
        def frame(self, view="bust", pitch=None, w=None, h=None):
            """The view's camera (self.camera, which the live viewer uses) without rendering."""
            return self._frame(view, pitch, w, h)[0]
    
        def _frame(self, view, pitch, w, h):
            if view == "bust":
                w, h = w or BUST_SIZE[0], h or BUST_SIZE[1]
                pitch = 4 if pitch is None else pitch
                pivot = np.array([0, self.lm["eye_y"] - 0.02, self.eye[2]])
                s = BUST_EYE_CHIN * SS / self.span
                (cx, cy), ref_y = (BUST_EYE_AT[0] * SS, BUST_EYE_AT[1] * SS), self.lm["eye_y"]
            else:
                w, h = w or BATTLE_SIZE[0], h or BATTLE_SIZE[1]
                pitch = 10 if pitch is None else pitch
                pivot = np.zeros(3)
                s = BATTLE_PX_PER_M * SS
                (cx, cy), ref_y = (BATTLE_GROUND_AT[0] * SS, BATTLE_GROUND_AT[1] * SS), 0.0
            self.camera = dict(view=view, w=w, h=h, pitch=pitch, px_per_m=s / SS, pivot=(pivot * FLIP).tolist(),
                               pivot_px=[cx / SS, (cy - (pivot[1] - ref_y) * s) / SS])
            return self.camera, (w, h, pitch, pivot, s, cx, cy, ref_y)
    
        def render(self, yaw=35, pitch=None, view="bust", smooth=None, w=None, h=None):
            """view 'bust': the 96x80 portrait framed on the face. view 'battle': the 240x160 battle
            scene, whole figure on the ground; scenery stays put while the character turns."""
            _, (w, h, pitch, pivot, s, cx, cy, ref_y) = self._frame(view, pitch, w, h)
            W, H = w * SS, h * SS
            R = camera_rotation(yaw, pitch)
            Rw = camera_rotation(0, pitch)
    
            def projector(Rm):
                def project(P):
                    q = ((P - pivot) * FLIP) @ Rm.T
                    return np.stack([cx + q[:, 0] * s, cy - (q[:, 1] + pivot[1] - ref_y) * s, q[:, 2]], -1)
                return project
            project = projector(R)
            project_w = projector(Rw)
    
            keep = [k for k, p in enumerate(self.prims)
                    if self.roles[k] != "skip" and len(p["tri"])
                    and (view != "bust" or p.get("world") or p["pos"][np.unique(p["tri"])][:, 1].max() > self.chin_y - 0.45)]
            prims = [dict(self.prims[k], _screen=project_w(self.prims[k]["pos"])) if self.prims[k].get("world")
                     else self.prims[k] for k in keep]
            t = np.clip(((pts - A) @ ab) / (ab @ ab), 0, 1)
            d = np.linalg.norm(pts - (A + t[:, None] * ab), axis=1)
            caps.append(dict(a=(A * FLIP).tolist(), b=(B * FLIP).tolist(), r=float(np.percentile(d, 70) + 0.012),
                             bones=[a, b]))
        cloth = {}
        for p in portrait.prims:
            if p["material"] in CLOTH and "grid" in p:
                trims, band, collide = CLOTH[p["material"]]
                cloth[p["material"]] = dict(u=int(p["grid"][0]), v=int(p["grid"][1]), trims=list(trims), band=band,
                                            collide=list(collide) if collide else None, closed=bool(p.get("closed")),
                                            edges="hem" if p["material"] in CLOTH_HEM_ONLY else "all")
        curve = None
        if getattr(portrait, "mouth_curve", None) is not None:
            face = [p for p, r in zip(portrait.prims, portrait.roles) if r == "face"]
            allp = np.concatenate([p["pos"] for p in face])
            alln = np.concatenate([p["nrm"] for p in face])
            from scipy.spatial import cKDTree
            _, i = cKDTree(allp).query(portrait.mouth_curve)
            curve = ((portrait.mouth_curve + alln[i] * 0.0015) * FLIP).tolist()
        marks = None
        if getattr(portrait, "marks", None):
            m = next(iter(portrait.marks.values()))
            img = Image.fromarray(np.where(m == 1, 128, 0).astype(np.uint8), "L")     # nose mark only; the mouth is a line
            b = io.BytesIO()
            img.save(b, "PNG", optimize=True)
            import base64
            marks = base64.b64encode(b.getvalue()).decode()
        # painted renderer: a material kind and one base colour per role; the shader builds the ramp
        pc = dict(signature="#7d1e2c", doublet="#2a2d3d", heraldry="#dfe2e8", leather="#5f3e2b", boot="#4a3326", glove="#5f3e2b",
                  steel="#a6adbb", gold="#b08b3f", hair=hexp("C"), trim="#b08b3f")
        pc.update(getattr(portrait, "paint", None) or {})
    243:const ROLE_ID = { face: 1, body: 2, hair: 3, line: 4, iris: 5, white: 6, highlight: 7, brow: 8, mouth: 9, cloth: 10, hair_b: 11 };
    
  • exec_commandsource ~/Projects/lowmarch-bench/kit/env-c.sh && rg -n 'uFaceTex|uSkinTone|face.*tex|mouth_curve' review/vroid-02/index.html tools/export_glb.py | head -90 && sed -n '420,470p' review/vroid-02/index.html

    command

    source ~/Projects/lowmarch-bench/kit/env-c.sh && rg -n 'uFaceTex|uSkinTone|face.*tex|mouth_curve' review/vroid-02/index.html tools/export_glb.py | head -90 && sed -n '420,470p' review/vroid-02/index.html

    result, 66 lines

    Script completed
    Wall time 0.5 seconds
    Output:
    tools/export_glb.py:227:    if getattr(portrait, "mouth_curve", None) is not None:
    tools/export_glb.py:232:        _, i = cKDTree(allp).query(portrait.mouth_curve)
    tools/export_glb.py:233:        curve = ((portrait.mouth_curve + alln[i] * 0.0015) * FLIP).tolist()
    tools/export_glb.py:269:                mouth_curve=curve, mouth_bone="J_Bip_C_Head", ink=dict(o=hexp("o"), skin=hexp("1"), hair=hexp("A")),
    review/vroid-02/index.html:345:  uniform int uFaceTex; uniform int uDecal; uniform vec3 uMotif; uniform vec3 uBand; uniform vec3 uSkinTone; uniform int uShadeOnly;
    review/vroid-02/index.html:444:      if (uFaceTex == 1) col *= clamp(tex.rgb / uSkinRef, 0.55, 1.05);
    review/vroid-02/index.html:445:      if (uSkinRamp == 0) col *= uSkinTone;                            // older builds: one tint over the light skin
    review/vroid-02/index.html:817:    uGrain: { value: 0.05 }, uFaceTex: { value: 0 }, uDecal: { value: decal ? 1 : 0 }, uBand: { value: null },
    review/vroid-02/index.html:818:    uSkinTone: { value: new THREE.Vector3(1, 1, 1) }, uShadeOnly: { value: 0 },
    review/vroid-02/index.html:831:    const c = hex(P.base); u.uSkinTone.value.set(c.r / 0.973, c.g / 0.882, c.b / 0.835);
    review/vroid-02/index.html:833:  if (role === "face" && map) u.uFaceTex.value = 1;
        if (uAlpha == 2 && (tex.a < 0.5 || dot(tex.rgb, vec3(1.0 / 3.0)) >= 0.42)) discard;
        if (uPass == 1) { gl_FragColor = uInfo; return; }
        vec3 n = normalize(vN); if (!gl_FrontFacing) n = -n;
        vec3 v = normalize(vView);
        float lit = dot(n, uKey) * 0.5 + 0.5;
        if (uShadeOnly == 1) lit = min(lit, 0.37);                        // shadow cards only ever darken skin, to a soft shade
        else if (uCastOn == 1 && uKind == 1 && int(uInfo.x * 255.0 + 0.5) == 2 && castShadow() > 0.5)
          lit = min(lit, 0.37);                                           // body skin under the jaw's or the hair's shadow
        float g1 = vnoise(vObj * 40.0), g2 = vnoise(vObj * 150.0);
        vec3 col;
        if (uKind == 0 || uKind == 5 || uKind == 6) {                    // cloth, leather, ground
          vec3 hb = rgb2hsv(uBase);
          bool cool = hb.x > 0.42 && hb.x < 0.86;
          float sh = uKind == 5 ? 0.93 : (cool ? 0.70 : 0.96);
          float li = cool ? 0.52 : 0.13;
          vec3 c0 = tone(uBase, sh, 0.09, 1.12, 0.40), c1 = tone(uBase, sh, 0.05, 1.08, 0.64);
          vec3 c3 = tone(uBase, li, 0.03, 0.80, 1.20);
          float l = lit + (g1 - 0.5) * uGrain - (uKind == 6 ? 0.22 : 0.0);  // ground: a flat top sits at the base colour
          col = mix(c0, c1, st(l, 0.30)); col = mix(col, uBase, st(l, 0.50)); col = mix(col, c3, st(l, 0.91));
          if (uKind == 5) col *= 0.965 + 0.07 * vnoise(vObj * 22.0);       // mottled leather
        } else if (uKind == 1) {                                           // skin: pale, nearly unshaded from the front
          vec3 sL = vec3(0.973, 0.882, 0.835), sS = vec3(0.776, 0.659, 0.608), sC = vec3(0.451, 0.322, 0.310);
          if (uSkinRamp == 1) { sL = uSkinL; sS = uSkinS; sC = uSkinC; }   // the character's tone, designed per tone
          col = mix(sC, sS, st(lit, 0.20)); col = mix(col, sL, st(lit, 0.38));
          if (uFaceTex == 1) col *= clamp(tex.rgb / uSkinRef, 0.55, 1.05);
          if (uSkinRamp == 0) col *= uSkinTone;                            // older builds: one tint over the light skin
        } else if (uKind == 2) {                                           // hair: four even bands, hard strand highlights
          float strand = dot(tex.rgb, vec3(1.0 / 3.0));
          vec3 c0 = tone(uBase, 0.72, 0.07, 1.10, 0.45), c1 = tone(uBase, 0.72, 0.035, 1.05, 0.68);
          vec3 c2 = tone(uBase, 0.56, 0.02, 0.92, 1.10), c3 = tone(uBase, 0.56, 0.03, 0.55, 1.42);
          float l = lit + (strand - 0.6) * 0.12;
          col = mix(c0, c1, st(l, 0.40)); col = mix(col, uBase, st(l, 0.56)); col = mix(col, c2, st(l, 0.84));
          float sp = dot(n, normalize(uKey + v)) + (strand - 0.6) * 0.18;
          col = mix(col, c3, st(sp, 0.90) * (1.0 - st(sp, 0.985)));
        } else if (uKind == 3 || uKind == 4) {                             // steel, gold
          bool plate = vPlate.x > 0.5;
          float e = vPlate.y, w = vPlate.z;
          bool gilt = uKind == 4 || (plate && w > 0.0 && e < w);            // an outline plate's gold border
          col = metal(gilt, gilt && uKind == 3 ? uGold : uBase, n, v, lit, plate ? vPlate.w : -1.0);
          if (plate && w > 0.0) {                                           // engraved lines: one inside the border, one on its seam
            float aa = fwidth(e) * 1.2 + 1e-5;
            float l1 = 1.0 - smoothstep(0.0010, 0.0010 + aa, abs(e - (w + 0.0050)));
            float l2 = 1.0 - smoothstep(0.0006, 0.0006 + aa, abs(e - w));
            col = mix(col, col * 0.42, max(l1, l2 * 0.8));
          }
        } else if (uKind == 7) {                                           // iris
          float l = dot(tex.rgb, vec3(1.0 / 3.0));
          col = l < 0.3 ? mix(uEye[0], uEye[1], l / 0.3) : mix(uEye[1], uEye[2], clamp((l - 0.3) / 0.6, 0.0, 1.0));
        } else if (uKind == 8) { col = tex.rgb; }
        else { col = uFlat; }
        if (vPlate.x > 0.5 && vPlate.z > 0.0 && uKind != 3 && uKind != 4) {   // a cloth outline piece's gold border,
    
  • exec_commandsource ~/Projects/lowmarch-bench/kit/env-c.sh && rg -n 'MARK_WINDOW|FACE_MARK|MARK_GROW' tools/vroid_portrait.py && sed -n '45,85p' tools/vroid_portrait.py && date -Is

    command

    source ~/Projects/lowmarch-bench/kit/env-c.sh && rg -n 'MARK_WINDOW|FACE_MARK|MARK_GROW' tools/vroid_portrait.py && sed -n '45,85p' tools/vroid_portrait.py && date -Is

    result, 54 lines

    Script completed
    Wall time 0.3 seconds
    Output:
    43:FACE_MARK = 0.70        # face-texture texels darker than this are painted lines (lip line, nose mark)
    44:MARK_GROW = 4           # texels of dilation so a 1.5 mm painted line survives the 4x4 vote
    47:MARK_WINDOW = dict(u=(0.32, 0.68), v=(0.58, 0.86), nose_below=0.70)
    848:            win = ((uu > MARK_WINDOW["u"][0]) & (uu < MARK_WINDOW["u"][1])
    849:                   & (vv > MARK_WINDOW["v"][0]) & (vv < MARK_WINDOW["v"][1]))
    850:            raw = (t[..., :3].mean(-1) / 255 < FACE_MARK) & (t[..., 3] > 0) & win
    851:            grown = binary_dilation(raw, iterations=MARK_GROW) & win
    853:            self.marks[k] = np.where(grown, np.where(vv >= MARK_WINDOW["nose_below"], 2, 1), 0).astype(np.uint8)
    LIP_DROP = 0.014        # UV distance below the lip line that gets the lower-lip shade
    # VRoid face textures share one layout: marks only count inside the nose-and-mouth window
    MARK_WINDOW = dict(u=(0.32, 0.68), v=(0.58, 0.86), nose_below=0.70)
    
    # High-resolution pixel rendering (2026-10-08): a 640x360 base screen (scales cleanly to 1080p/4K).
    BUST_SIZE, BUST_EYE_CHIN, BUST_EYE_AT = (192, 160), 38.0, (92, 60)   # portrait: canvas, eye-to-chin px, eye line
    BATTLE_SIZE, BATTLE_PX_PER_M, BATTLE_GROUND_AT = (640, 360), 90.0, (420, 318)   # battle: canvas, scale, feet
    SUN = np.array([-0.30, 0.85, 0.45]) / np.linalg.norm([-0.30, 0.85, 0.45])   # scenery light (camera space)
    LID_CORE = 70                               # eyeline texels darker than this are the lash line
    LIGHT = np.array([0.08, 0.06, 1.0]) / np.linalg.norm([0.08, 0.06, 1.0])
    SKIN_BANDS = [(0.80, "5"), (0.62, "4"), (0.38, "3"), (-9, "2")]
    HAIR_BANDS = [(0.86, "E"), (0.66, "D"), (0.42, "C"), (-9, "B")]
    CLOTH_BANDS = [(0.85, "P"), (0.6, "M"), (0.35, "L"), (-9, "K")]
    # costume materials: role -> bands (metal has a narrow bright streak and hard darks)
    MATERIALS = {"coat": CLOTH_BANDS,
                 "signature": CLOTH_BANDS,                   # the character's one colour (tabard, mantle, shield)
                 "doublet": [(0.85, "T"), (0.6, "S"), (0.35, "R"), (-9, "Q")],
                 "heraldry": [(0.85, "O"), (0.6, "N"), (0.35, "J"), (-9, "F")],
                 "cape": [(0.85, "X"), (0.6, "W"), (0.35, "V"), (-9, "U")],
                 "metal": [(0.975, "9"), (0.86, "8"), (0.55, "7"), (-9, "6")],
                 "gold": [(0.80, "I"), (0.45, "H"), (-9, "G")],
                 "leather": [(0.75, "x"), (0.4, "v"), (-9, "u")],
                 "boot": [(0.80, "x"), (0.45, "v"), (-9, "u")],
                 "glove": [(0.75, "x"), (0.4, "v"), (-9, "u")],
                 "steel": [(0.90, "9"), (0.70, "8"), (0.40, "7"), (-9, "6")],
                 "grass": [(0.90, "d"), (0.70, "c"), (0.40, "b"), (-9, "a")],
                 "dirt": [(0.70, "i"), (0.35, "f"), (-9, "e")],
                 "stone": [(0.80, "m"), (0.45, "l"), (-9, "k")]}
    WORLD_ROLES = ("grass", "dirt", "stone")
    DARKER = {c: tbl[min(i + 1, len(tbl) - 1)][1] for tbl in MATERIALS.values() for i, (_, c) in enumerate(tbl)}
    FLIP = np.array([-1.0, 1.0, -1.0])          # VRoid faces -z; we want the face toward +z (the viewer)
    
    
    def role_of(material):
        for frag, role in ROLES:
            if frag in material:
                return role
        return "cloth"
    
    
    def bands(v, table):
    2026-10-30T12:59:37+08:00
    
  • exec_commandsource ~/Projects/lowmarch-bench/kit/env-c.sh && rg -n 'function rawTex|rawTex =' review/vroid-02/index.html && sed -n '238,260p' review/vroid-02/index.html && date -Is

    command

    source ~/Projects/lowmarch-bench/kit/env-c.sh && rg -n 'function rawTex|rawTex =' review/vroid-02/index.html && sed -n '238,260p' review/vroid-02/index.html && date -Is

    result, 29 lines

    Script completed
    Wall time 0.4 seconds
    Output:
    294:const rawTex = t => { if (!t) return null; const c = t.clone(); c.colorSpace = THREE.NoColorSpace; c.needsUpdate = true; return c; };
      sword: "Sword", weapon: "Weapon", helmet: "Helmet", hood: "Hood", padding: "Padded coat", mail: "Mail",
      terrain: "Ground" };
    const COSTUME = new Set(["tunic", "tails", "belt", "trousers", "boots", "gloves", "collar", "pauldron", "cape", "trim",
      "doublet", "plate", "tabard", "mantle", "shield", "dress", "helmet", "hood", "padding", "mail"]);
    // role ids for the info pass (features 4-9 get no inner lines; hair 3 and 11 shade the forehead)
    const ROLE_ID = { face: 1, body: 2, hair: 3, line: 4, iris: 5, white: 6, highlight: 7, brow: 8, mouth: 9, cloth: 10, hair_b: 11 };
    let nextRole = 12;
    const roleId = r => (ROLE_ID[r] ??= nextRole++);
    const VIEW_YAW = { duel: 0, battle: 60, bust: 30, lineup: 20, compare: 0 };
    const state = { view: "duel", who: CAM.characters[0].name, yaw: 0, mode: "painted", skin: "", toon: true, xray: false, hidden: new Set(),
                    cloth: true, wind: false, playing: false, stepped: false, clip: "clash", pose: "out", compare: [], motion: "still",
                    physics: true };
    const charDef = name => CAM.characters.find(c => c.name === name);
    // a workshop page (camera.json "page"): its own title and notes, and no duel
    const PAGE = CAM.page || null;
    const NO_DUEL = PAGE?.duel === false;
    if (PAGE) {
      document.title = `${PAGE.title} · Lowmarch`;
      document.querySelector(".brand .eyebrow").textContent = PAGE.eyebrow || "Lowmarch";
      document.querySelector(".brand h1").textContent = PAGE.title;
      if (PAGE.notes) document.querySelector("#panel section ul").innerHTML = PAGE.notes;
    }
    // the armory: bodies compared side by side (the Compare view) in three poses, instead of clips and a lineup
    2026-10-30T12:59:42+08:00
    
  • view_image~/Projects/lowmarch-bench/work/c/shot_r2/joy/painted_arm_m_youth.png

    input

    const im=await tools.view_image({path:"~/Projects/lowmarch-bench/work/c/shot_r2/joy/painted_arm_m_youth.png",detail:"original"});image(im.image_url);
    

    result, 4 lines

    Script completed
    Wall time 0.1 seconds
    Output:
    
    shot_r2_joy_youth.png
    shot_r2_joy_youth.png
  • write_stdinpoll session 25485

    input

    const r=await tools.write_stdin({session_id:25485,chars:"",yield_time_ms:50000,max_output_tokens:3000});text(JSON.stringify(r));
    

    result, 4 lines

    Script completed
    Wall time 10.1 seconds
    Output:
    {"chunk_id":"cde04a","wall_time_seconds":10.099555241,"exit_code":143,"original_token_count":0,"output":""}
  • exec_commandsource ~/Projects/lowmarch-bench/kit/env-c.sh && bash "$WORK/shoot_resume.sh" "$LOWMARCH_REPO/review/vroid-02/index.html" r2 && "$KIT/sheets.sh" r2 'Round 2: softer brows and eyelid and mouth revisions' && date -Is

    command

    source ~/Projects/lowmarch-bench/kit/env-c.sh && bash "$WORK/shoot_resume.sh" "$LOWMARCH_REPO/review/vroid-02/index.html" r2 && "$KIT/sheets.sh" r2 'Round 2: softer brows and eyelid and mouth revisions' && date -Is

    result, 4 lines

    Script completed
    Wall time 1.2 seconds
    Output:
    {"chunk_id":"ca6800","wall_time_seconds":1.000316822,"session_id":73102,"original_token_count":0,"output":""}

agent

+15:44

The revised joy now closes the youth’s eyes cleanly at both angles; the first version left a strip of iris visible. I’m finishing the second sheet to check whether the same approach helps the wink.

  • write_stdinpoll session 73102

    input

    const r=await tools.write_stdin({session_id:73102,chars:"",yield_time_ms:50000,max_output_tokens:3000});text(JSON.stringify(r));
    

    result, 4 lines

    Script running with cell ID 49
    Wall time 31.0 seconds
    Output:
    
  • waitcell 49

    input

    {
      "cell_id": "49",
      "yield_time_ms": 20000
    }

    result, 4 lines

    Script completed
    Wall time 13.1 seconds
    Output:
    {"chunk_id":"021856","wall_time_seconds":50.000916716,"session_id":73102,"original_token_count":103,"output":"arm_f_slender ~/Projects/lowmarch-bench/work/c/shot_r2/lip_U/painted_arm_f_slender.png 13s\narm_m_youth ~/Projects/lowmarch-bench/work/c/shot_r2/lip_U/painted_arm_m_youth.png 10s\narm_f_slender ~/Projects/lowmarch-bench/work/c/shot_r2/neutral/painted_arm_f_slender.png 11s\narm_m_youth ~/Projects/lowmarch-bench/work/c/shot_r2/neutral/painted_arm_m_youth.png 9s\n"}
  • write_stdinpoll session 73102

    input

    const r=await tools.write_stdin({session_id:73102,chars:"",yield_time_ms:50000,max_output_tokens:3000});text(JSON.stringify(r));
    

    result, 4 lines

    Script running with cell ID 50
    Wall time 31.0 seconds
    Output:
    
  • waitcell 50

    input

    {
      "cell_id": "50",
      "yield_time_ms": 20000
    }

    result, 4 lines

    Script completed
    Wall time 16.3 seconds
    Output:
    {"chunk_id":"829fc8","wall_time_seconds":50.001212875,"session_id":73102,"original_token_count":101,"output":"arm_f_slender ~/Projects/lowmarch-bench/work/c/shot_r2/sad/painted_arm_f_slender.png 11s\narm_m_youth ~/Projects/lowmarch-bench/work/c/shot_r2/sad/painted_arm_m_youth.png 9s\narm_f_slender ~/Projects/lowmarch-bench/work/c/shot_r2/shout/painted_arm_f_slender.png 10s\narm_m_youth ~/Projects/lowmarch-bench/work/c/shot_r2/shout/painted_arm_m_youth.png 13s\n"}

agent

+17:29

The neutral and sad variants have rendered with the softer overlay. The remaining captures will complete the comparison before I settle the final recipe values.

  • write_stdinpoll session 73102

    input

    const r=await tools.write_stdin({session_id:73102,chars:"",yield_time_ms:50000,max_output_tokens:3000});text(JSON.stringify(r));
    

    result, 4 lines

    Script running with cell ID 51
    Wall time 31.0 seconds
    Output:
    
  • waitcell 51

    input

    {
      "cell_id": "51",
      "yield_time_ms": 20000
    }

    result, 4 lines

    Script completed
    Wall time 17.0 seconds
    Output:
    {"chunk_id":"ad6344","wall_time_seconds":50.001210595,"session_id":73102,"original_token_count":102,"output":"arm_f_slender ~/Projects/lowmarch-bench/work/c/shot_r2/smile/painted_arm_f_slender.png 15s\narm_m_youth ~/Projects/lowmarch-bench/work/c/shot_r2/smile/painted_arm_m_youth.png 12s\narm_f_slender ~/Projects/lowmarch-bench/work/c/shot_r2/smug/painted_arm_f_slender.png 13s\narm_m_youth ~/Projects/lowmarch-bench/work/c/shot_r2/smug/painted_arm_m_youth.png 11s\n"}
  • write_stdinpoll session 73102

    input

    const r=await tools.write_stdin({session_id:73102,chars:"",yield_time_ms:50000,max_output_tokens:3000});text(JSON.stringify(r));
    

    result, 4 lines

    Script running with cell ID 52
    Wall time 31.0 seconds
    Output: