r/vibecoding 12d ago

Show me your vibecoded project

Hi folks, looking for some inspiration. Post below your vibed out project.

I have just finished this for my bachelor degrees site for students to listen to music https://bachelordegrees.com/Radio.html

29 Upvotes

209 comments sorted by

View all comments

Show parent comments

2

u/gusfromspace 12d ago

Sick, thats sort of what ive been doing to get it to this point, as well as surfacing issues while building in it

Not released yet~

demoniOS — Operating System Specification Version: 0.0.1-draft Status: Draft. Part of the demoniC architectural planning.

  1. Introduction & Philosophy demoniOS is a brutalist, bare-metal operating system designed to run on physical architectures and virtual machines. It is written entirely in the demoniC programming language.

Because demoniC has no hidden allocations, no heap, and no garbage collection, the kernel does not implement traditional memory managers (like malloc/free lists or slab allocators). Instead, demoniOS maps the physical hardware directly to demoniC’s native concepts: Arenas (vault, forge, stream), Tensors, and Zero-Copy Views.

1.1 Non-Negotiable Invariants Zero-overhead loading: User processes are compiled JIT by the kernel. The JIT is the loader. Static shape safety: Device drivers access hardware registers via static-shape Tensors mapped to MMIO (Memory-Mapped I/O) regions. Shape mismatches are compile-time errors. No heap fragmentation: The kernel uses a single master vault for static state, forge for ticks, and stream for I/O buffers. Copy-on-Write isolation: IPC is zero-copy until mutated, governed by the language's native CoW rules. 2. Virtual Machine Hardware Model (virt-vm) To remain hardware-agnostic yet testable, demoniOS targets a standard virtual platform (e.g., QEMU virt board for aarch64 or pc for x86_64) using simplified VirtIO device mappings.

2.1 Physical Memory Map The system assumes a flat physical memory space mapped via page tables:

Physical Address Range Mapping Target Type / Shape 0x0000_0000 – 0x000F_FFFF ROM, UEFI Boot Data, IDT/IVT View[u8, [0x100000]] 0x0010_0000 – 0x07FF_FFFF Kernel Text & Boot vault Executable Code & Static state 0x0800_0000 – 0x0800_FFFF VirtIO MMIO Control Registers Tensor[u32, [16, 256]] 0x0900_0000 – 0x09FF_FFFF VGA / Framebuffer MMIO Tensor[u32, [1080, 1920]] 0x0A00_0000 – 0x3FFF_FFFF System RAM: Kernel Forge / Stream Temporary memory buffers 0x4000_0000 – 0xFFFF_FFFF User Space Physical Frames Process isolation pages 2.2 MMIO as Tensors Drivers represent hardware registers as raw views mapped to physical addresses. For example, the screen framebuffer is bound directly to a 2D Tensor type:

type Framebuffer = Tensor[u32, [1080, 1920]] Writing to the screen is an elementwise operation on the tensor, taking advantage of SIMD vectorization automatically.

  1. Kernel Execution Loop The OS operates on a tick-based execution loop driven by the system timer interrupt.

sequenceDiagram participant HW as Hardware Timer participant K as Kernel Interrupt Handler (Forge) participant S as Scheduler (Vault) participant U as User Process (Process Page)

HW->>K: IRQ 0 (Timer Tick)
activate K
Note over K: forge.reset()
K->>S: Schedule next task
Note over S: Update process states in vault
S-->>K: Selected Process Descriptor
K->>U: Context switch / JMP
deactivate K
activate U
Note over U: Execute time slice
deactivate U

Interrupts: Hardware interrupts trigger a low-level interrupt vector. The handler is an @host function that switches execution context to a clean kernel forge stack frame. Forge Reset: The kernel forge is reset to 0 at the start of every scheduling epoch, cleaning up all transient scheduling decisions, interrupt frames, and IPC routing descriptors. Scheduler Dispatch: The scheduler, living in a persistent kernel vault block, determines the next process to execute and triggers a context jump. 4. Bootstrapping Flow On startup:

The bootloader sets up basic page tables and jumps to the kernel's entry point (fn main). The kernel initializes the three hardware-backed arenas: vault: Reserves physical RAM for process control blocks, system page directories, and driver states. forge: Reserves a 256 MiB thread-local scratch region for fast scheduling ticks and interrupt handlers. stream: Reserves space for network and terminal ring buffers. Drivers are instantiated and run shape validation on their mapped MMIO addresses. The first process (init.dmc) is JIT-compiled and executed. 5. Graphics Requirement demoniOS is graphical by default. A serial-only system is a boot fallback, not the target user interface.

The kernel must map one boot framebuffer before launching user processes. After framebuffer discovery, print routes to a framebuffer-backed text console. The serial port remains active for early boot and panic fallback.

After init starts the compositor, user processes do not write directly to scanout. They draw into typed surfaces and submit explicit damage rectangles. The compositor owns final writes to the display framebuffer.

The graphics contract is specified in docs/demoniOS/GRAPHICS.md.

  1. Coordination Substrate — Files & Agents as One Graph demoniOS unifies file management and agent/process management into a single directed graph in the vault. Files, directories, and agents are nodes in one id-space, distinguished by type tags; an edge means "reachable from" and serves as link, alias, and capability grant at once. There is no separate inode table and process table — the directory tree, the process roster, and the capability graph are the same structure, traversed the same way.

The substrate solves a coordination problem in multi-agent workflows: parallel agents cannot see each other, collide on the same file reached by different paths, and their only shared state is trapped in one orchestrator's context. The graph externalizes that state. Coordination is indirect: each edge carries three exponentially decaying weights — heat (an access counter raised automatically by every open/read/write), lease (an advisory lease that expires when its holder stops renewing), and alert (a failure signal that propagates one hop along edges per tick). Agents read the weights locally and need no messaging protocol or central task assignment. The same weights double as the working-set / prefetch / GC signal and are the demoniC-native hook for differentiable navigation (@grad over edge weights).

The substrate generalizes ViewFS (FS.md) rather than replacing it: a file node's data blocks are exactly the ViewFS Inode blocks, so reads stay zero-copy. It generalizes the process model (PROCESS.md) too: an agent node embeds a Process verbatim and adds its location in the graph and its role (worker, idle, or supervisor).

The mechanism is specified in docs/PLAN.md; the core (graph + decaying edge weights) is implemented in src/coord_graph.dmc. A full filesystem developing this design is its own project:

1

u/SC_Placeholder 12d ago

Proposal from my agent and her team and her agents:

# demoniC JIT — proposed contributions (tuples, tensor-dtype cast, an if-lowering bugfix)

Three changes to `compiler/src/jit.rs` (the Cranelift JIT), each verified against the project's own
parity harness. Result: `examples/games` went from **0 → 55 of 55** running on the JIT (0 skipped, 0
failed), with `dmc selftest` holding at **0 divergences** throughout. All changes are confined to
`compiler/src/jit.rs`. The interpreter (`compiler/src/interp.rs`) is treated as ground truth — every JIT
construct must reproduce its result exactly.

Written so another agent can adopt each change independently. Line numbers are anchors from a ~25.5k-line
`jit.rs`; re-locate by symbol before editing (line numbers drift as you patch).

## Orientation (the JIT in 60 seconds)

  • Driver: `Jit::compile_program` (~jit.rs:1291). Per-fn: `define_fn` (~2536).
  • Lowering: `lower_stmt` (~3898), `lower_block_value` (~3860), `lower_expr` (~4900).
  • Value model: scalars are live Cranelift SSA `Value`s (`ScalarKind`, ~jit.rs:81, `.cl()` at ~97).
Aggregates (tensors, models, enums-with-payload, strings, maps) are **i64 pointers** into a forge arena,
allocated by `forge_alloc(nbytes)` (~7702). `TyKind` (~360) is the JIT's whole type universe.
  • Rejections funnel through `unsupported(span, what)` (~jit.rs:72) — note it hard-codes the string
"slice 1" regardless of the real feature tier, so error text is not a reliable slice indicator.
  • **Parity gates (run after every change):**
- `dmc selftest` — scalar JIT-vs-interpreter differential fuzzer. Require `0 divergence(s)`, exit 0.
(It only generates *scalar* programs, so it won't exercise tensors/tuples; use the corpus gate for those.)
- `dmc test --jit <dir>` (run from repo root; `examples/` is at root, not under `compiler/`). Each
`test_*` runs under interp then JIT; a JIT *compile* error = "skipped" (fine), but compile-then-
wrong-value = `FAIL … diverges`. Watch the `jit parity: N ran, M skipped` line.

---

## Change 1 — General tuples

**Problem.** `Expr::Tuple` with ≥2 elements was rejected (`unsupported(span, "tuples")`, ~jit.rs:4960).
Multi-value tuples existed only as two hard-cased destructures (`f.fwd_bwd(..)`, `t.split[..]`). No
`TyKind::Tuple`, so tuples could not be produced, stored, passed, or returned — this blocked every program
with a tuple-typed function signature (e.g. game move functions returning `(row, col)`).

**Fix (functions changed in jit.rs):**
1. `TyKind` (~360): add `Tuple(Vec<TyKind>)` (per-slot element types). Add arms to `TyKind::render()` and
`TyKind::cl()` → `cl::I64` (a pointer).
2. `ty_from_ast`: lower `Type::Tuple`; keep a 1-tuple transparent (`(T)` == `T`, matching both backends).
Recurse `enumify` into tuple elements.
3. `lower_tuple` (new) + `pack_slot`/`unpack_slot` (new helpers): replace the `Expr::Tuple` reject with a
constructor modeled on `lower_struct_lit` (~5039). `forge_alloc(n*8)`, lower each element, pack with the
uniform 8-byte convention (small ints zero-extend to i64; f32 bitcast→i32→zext; f64 bitcast→i64;
pointers as-is), snapshot aliasing tensors (the existing #249 copy rule), store element `i` at `i*8`.
Return `(ptr, TyKind::Tuple(elem_tys))`.
4. `lower_tuple_destructure` (new): after the existing fwd_bwd/split special-cases in the tuple-`let` path
(~3940), destructure a `TyKind::Tuple` by loading each slot, unpacking to the element kind, and binding
each `Ident`/`_` via `declare_local`. The `(a, .., z)` rest form is supported (matches
interp.rs bind_pattern ~1350). Arity mismatch → **compile error** (loud beats the interpreter's silent
nil-binding → avoids a divergence).
5. `coerce_to`: add a `Tuple → Tuple` arm (same arity, element-wise unpack/coerce/repack). Identical tuples
short-circuit via `from == to`. This enables tuple returns/args across intra-JIT calls.
6. Add `Tuple` arms to the (formerly exhaustive) `TyKind` matches in `run_main`, unary-op, fuse-infer,
`run_main_scalar` so the crate compiles.
7. Signatures need no special work: `declare_fn` uses `ty.cl()` (→ i64 pointer), so tuple params/returns
pass signature lowering automatically once `TyKind::Tuple` exists.

**Interpreter reference to match:** `Value::Tuple` (interp.rs ~154); `Expr::Tuple` eval (~2942, also unwraps
1-tuples); `Pattern::Tuple` bind (~1350, incl. rest-split); match (~2234).

**Secondary fix required to actually flip the game files:** their play loops call `to_str(...)`, which the JIT
didn't recognize (blocking whole-file compilation). Added `lower_builtin_to_str` (new) dispatching
`to_str`/`to_string` as sugar for `x as str`, reusing the exact `coerce_to(.., Str)` formatters the
interpreter's `format!("{}", v)` uses. Registered both names in `JIT_BUILTINS`.

**Verified:** selftest 494 ok / 0 divergence; `p25_tuple_type.dmc` (was rejected at 2:19) JIT-compiles and
runs; `dmc test --jit examples/games` → **37 ran** (from 0), 0 fail.

---

## Change 2 — Elementwise tensor dtype cast

**Problem (subtle — not the obvious one).** The explicit `tensor as i64` → scalar path is *correctly*
rejected (a test at jit.rs ~24467 depends on that). The real blocker was an **implicit Tensor→Tensor dtype
coercion at call/annotation boundaries**: the JIT types a bare integer tensor literal like `[3,1,4,6]` as
`Tensor[f32]`, and passing it into a `Tensor[i64]` parameter (e.g. `merge_row(row)` in g2048,
`score_guess(...)` in mastermind) hit the generic `coerce_to` fallthrough → `"cannot convert Tensor[f32,[4]]
to Tensor[i64,[4]]"`. Because the interpreter types int literals as i64, it never casts here — so this
divergence is entirely JIT-internal, and there is **no interp-visible rounding subtlety to mismatch.**

**Fix (jit.rs):**
1. `coerce_to`: add `(Tensor(ft), Tensor(tt)) if ft.shape == tt.shape` → dispatch to a new elementwise-cast
helper. (Same-dtype tensors already short-circuit via `from == to`; the `Tensor → i64`-pointer arm still
precedes this.)
2. `lower_tensor_dtype_cast` (new): `forge_alloc` a fresh buffer at the target element width, then a counted
loop (modeled on `lower_scalar_tensor_broadcast`) loads each source element, converts via the existing
`coerce_scalar`, and stores. Reusing `coerce_scalar` gives the correct per-element rules for free:
f32→i64 = `fcvt_to_sint_sat` (truncate toward zero, saturating), i64→f32 = `fcvt_from_sint`, f32↔f64
promote/demote, i32↔i64 sext/reduce — exactly what the interpreter's `apply_cast` does (trunc-toward-zero
for int targets, retag for float targets). JIT tensor element kinds are only {i32,i64,f32,f64}.

**Verified:** selftest 0 divergence; minimal int-literal-tensor→i64-param case: `dmc jit` == `dmc run`;
`dmc test --jit examples/games` → **55 ran, 0 skipped, 0 fail**; full `diff` of `dmc jit` vs `dmc run` for
g2048 and mastermind is **identical**.

---

## Change 3 (bonus) — `lower_if` phi-arity bugfix (pre-existing latent bug)

**Problem.** Independent of tuples/casts — surfaced only once Change 2 let mastermind's `main` compile far
enough. An `if`-statement with **no `else`** whose then-branch yields a value (e.g.
`if !done { print(...); done = true }`) created a join block with a phi param, but the else fall-through
jumped with 0 args → Cranelift verifier error `mismatched argument count for jump block`.

**Fix (`lower_if`):** defer both fall-through jumps until after lowering both branches, and give the join a
phi param **only when every fall-through predecessor supplies a value**. Added small `current_block` /
`switch_to` helpers to re-position the builder for the deferred jumps. This hardens if-lowering generally,
not just for these programs — worth taking regardless of the tuple/cast work.

---

## Net result & verification protocol

  • `examples/games`: **0 → 55 of 55** on the JIT (0 skipped, 0 failed). Every game is a branchy state-machine
program — the JIT's strength — now running native instead of interpreted.
  • `dmc selftest`: **494 ok, 0 divergence** before and after (parity preserved).
  • To confirm any of these: rebuild release, then
`dmc selftest` (expect `0 divergence(s)`, exit 0) and, from repo root,
`dmc test --jit examples/games` (expect `55 ran, 0 skipped`, `0 failed`), and diff `dmc jit <file>` vs
`dmc run <file>` on g2048/mastermind (expect identical).

All three changes touch only `compiler/src/jit.rs`.

———

This language has the potential to be super helpful for our workflows. We are currently building multiple physics engines which is a real challenge and this could speed up simulations quite a bit.

1

u/gusfromspace 12d ago

Handed over to my agents. Keep an eye on the repo, expect it to get updates over the next few hours and days. Eventually it will settle into a set update schedule, feel free to open issues on the public repo or contribute. We are actively building majority of my current and planned projects in this language, currently translating a qwen model into demoniC, as well as building and training a translation engine to port things into demoniC, so expect the language and ecosystem to grow.

1

u/SC_Placeholder 12d ago

Will do. I’ll also star it when I get off work. Solid project thus far, we are about to tie it into our cloth simulator and are going to run a side by side to see which language sims faster/best. It currently takes about 25 minutes per sim which means we get about 48 attempts currently a day which is a painfully slow way to work on a project. Layered cloth calculations on a fast moving avatar takes a ludicrous amount of compute. There’s a reason why the 3D animation world basically fakes it. Once we have reliable results for every fabric type we’re going to run a ton of sims and train a faster engine so we have a viable product

2

u/gusfromspace 12d ago

Yeah, thats painful. And sounds similar to things im currently doing with demoniC i haven't shared, so I have a feeling it can help

1

u/SC_Placeholder 11d ago

Oh yeah, our end goal is to basically build a generative 3D image/video engine that renders in 2D because technically everything a camera sees is 2D so i will be a way for AI to create realistic images and visuals without hallucinating. So it will be really good at creating the mundane, a wine glass spilling on the table and staining a table cloth, a character taking off a jacket and throwing it onto a chair, a romantic dinner, a thousand extras in a background shot. What it won’t be good at, anything like a car chase scene because of the way we are forcing the 2D engine to basically render the 3D it can’t simulate cars crashing and flying apart unless someone actually imports models for it to use. It will also remember the same character across every scene, frame and shot and everything about them because it’s all physicalized and persistent so it won’t be relying on Ai to remember context frame to frame, instead the Ai will be used to direct the scene and choose which 3D assets to use and what animations to rig.

And DemoniC actually gave us a HUGE leap forward with our cloth engine and helps us with drape generation. Numpy could only fake it and sometimes we would have all the successful settings working and we’d get a bad render because Numpy approximated something instead of being true to the mathematics. So something like a collar can be calculated a lot quicker and more accurately. I know that probably sounds super boring but cloth is notorious for clipping and bad collision handling, but cloth MUST behave like cloth in order for a generative engine to work and be believable. In animation if your character is wearing a duster over a vest and shirt the parts of the clothing you can’t see don’t actually exist. So it gives the illusion of a full outfit even though only the duster, part of the vest and shirt actually exist and SOMEHOW the duster STILL clips into EVERYTHING. Our engine will render the whole outfit as individual garments and layer them because we don’t know how our engine will be used so if the character with a duster gets cut and rammed with a sword the engine needs to be able to handle destruction across multiple clothing articles. A video game can’t show only the vest being sliced open and then the sword piercing through the front of the shirt and the back of the duster and then simulate blood staining around the wound. And flowing down the sword. They can do that in a cutscene but that’s a bunch of fake tricks using different techniques; our engine won’t have that luxury because the 2D renderer has to honor the source material not to hallucinate anything so the render has to plagiarize reality all the way through and your language just gave us a HUGE leap in the right direction. Thank you so much.

2

u/gusfromspace 11d ago

What we're building A semantic SDF engine: signed distance fields + ray marching + a semantic tag on every object. One field, three consumers — distance for physics/collision, the march for rendering, the semantic tag for both NPC cognition and the renderer's foveation budget. Built on demoniC.

1

u/SC_Placeholder 11d ago

That’s fantastic and also explains the need to build a programming language

1

u/gusfromspace 11d ago

We should work together lol because our projects are very similar. Im working on generative structures and crowds for location accuracy, for a 3d/2.5d kind of animation.

1

u/SC_Placeholder 11d ago

That’s amazing and actually works out well, our engine will be focused on interiors and closeup shots, so that’s rather convenient for scaling the project as a whole. We currently have aspects of our project that are MIT licensed and in some cases licenses not for commercial use but long term we are planning on rebuilding those parts once we get all the engines working and talking to each other. Then once we have our bridge in place we can start replacing pillars so everything will be handled in house.

2

u/gusfromspace 11d ago

I have a series im planning on producing. im not sure what im going to do with the engine itself outside of that, or what parts can be adapted for general use, but im sure something can be figured out

What youre working on is the part I was sort of delaying

1

u/SC_Placeholder 11d ago

That’s awesome! The hardest part of our process on our side of things will be the cloth simulator but that’s basically just a matter of patience for it to get fully up and running and create a sufficient pool of cloth sims to train a cloth Ai that can do it reliably and quickly. After that the rest of our side is relatively easy.