L
ling-miao
↓ 0 ダウンロードmiao: a Ling-native version control system — temples, souls, rites and talismans instead of repos, branches, commits and tags; adaptive whole/delta/chunk storage; SSH temple fairs for sharing; a LingStationX-themed GUI; ROYGBIV everywhere
キーワード vcs, version-control, git, miao, ling
lingfu install ling-miaoコード / ファイル (268)
ling/rites.ling
# ━━━ rites.ling — the ceremonies: divine, offer, rite, lineage, summon… ━━━
# fns prefixed rt_. These implement the miao commands on top of store.ling.
# ── path resolution (user arg -> repo-relative path) ──────────────────
fn rt_relpath(arg) {
bind p = ut_norm(arg)
if str_starts_with(p, "./") { bind p = str_slice(p, 2.0, 99999.0) }
bind pre = sx_prefix()
bind cand = p
if pre != "" { bind cand = pre + "/" + p }
if file_exists(sx_root() + "/" + cand) { return cand }
if file_exists(sx_root() + "/" + p) { return p }
return cand
}
# any ref: soul | talisman | rite | mother/soul (fetched tip)
fn rt_resolve(name) {
bind r = sx_resolve(name)
if r != "" { return r }
# mother tips: lines "mother|soul|rite", referenced as "mother/soul"
bind lines = ut_read_lines(sx_dir() + "/mtips")
bind i = 0.0
while i < len(lines) {
bind parts = split(list_get(lines, i), "|")
bind full = list_get(parts, 0.0) + "/" + list_get(parts, 1.0)
if full == name { return list_get(parts, 2.0) }
bind i = i + 1.0
}
return ""
}
# ── divine (status) ───────────────────────────────────────────────────
# returns [altar_paths, altar_states, restless_paths, restless_states, wandering]
fn rt_status_data() {
bind head = sx_rite_manifest(sx_head_rite())
bind hids = list_get(head, 0.0)
bind hpaths = list_get(head, 1.0)
bind a = sx_altar()
bind aids = list_get(a, 0.0)
bind apaths = list_get(a, 1.0)
bind work = sx_walk()
bind sp = list_new()
bind ss = list_new()
bind i = 0.0
while i < len(apaths) {
bind p = list_get(apaths, i)
bind id = list_get(aids, i)
bind hat = ut_index_of(hpaths, p)
if id == "-" {
bind sp = list_push(sp, p)
bind ss = list_push(ss, "gone")
} else if hat < 0.0 {
bind sp = list_push(sp, p)
bind ss = list_push(ss, "new")
} else if list_get(hids, hat) != id {
bind sp = list_push(sp, p)
bind ss = list_push(ss, "edit")
} else {
bind sp = list_push(sp, p)
bind ss = list_push(ss, "same")
}
bind i = i + 1.0
}
# restless: worktree differs from altar/head
bind rp = list_new()
bind rs = list_new()
bind wander = list_new()
bind i = 0.0
while i < len(work) {
bind p = list_get(work, i)
bind aat = ut_index_of(apaths, p)
bind hat = ut_index_of(hpaths, p)
bind expected = ""
if aat >= 0.0 {
bind expected = list_get(aids, aat)
} else if hat >= 0.0 {
bind expected = list_get(hids, hat)
}
if expected == "" {
bind wander = list_push(wander, p)
} else if expected == "-" {
# staged for removal but still present: wandering again
bind wander = list_push(wander, p)
} else {
bind actual = file_hash(sx_root() + "/" + p)
if actual != expected {
bind rp = list_push(rp, p)
bind rs = list_push(rs, "edit")
}
}
bind i = i + 1.0
}
# departed: tracked or staged, but missing from the worktree
bind i = 0.0
while i < len(hpaths) {
bind p = list_get(hpaths, i)
if ut_contains(work, p) == false {
bind aat = ut_index_of(apaths, p)
bind staged_gone = false
if aat >= 0.0 {
if list_get(aids, aat) == "-" { bind staged_gone = true }
}
if staged_gone == false {
bind rp = list_push(rp, p)
bind rs = list_push(rs, "gone")
}
}
bind i = i + 1.0
}
bind i = 0.0
while i < len(apaths) {
bind p = list_get(apaths, i)
if list_get(aids, i) != "-" {
if ut_contains(work, p) == false {
if ut_contains(hpaths, p) == false {
bind rp = list_push(rp, p)
bind rs = list_push(rs, "gone")
}
}
}
bind i = i + 1.0
}
return [sp, ss, rp, rs, wander]
}
fn rt_divine() {
bind h = sx_head()
bind tip = sx_head_rite()
bind where = ""
if list_get(h, 0.0) == "soul" {
bind where = cx_info("soul " + list_get(h, 1.0))
} else {
bind where = cx_warn("wandering rite " + ut_short(list_get(h, 1.0))) + cx_dim(" (detached)")
}
bind tipstr = cx_dim("newborn temple — no rites yet")
if tip != "" {
bind r = sx_rite_read(tip)
bind tipstr = cx_aura(tip) + " " + cx_dim(ut_first_line(list_get(r, 4.0)))
}
print(cx_rainbow("miao") + " " + where + cx_dim(" · ") + tipstr)
bind d = rt_status_data()
bind sp = list_get(d, 0.0)
bind ss = list_get(d, 1.0)
bind rp = list_get(d, 2.0)
bind rs = list_get(d, 3.0)
bind wander = list_get(d, 4.0)
bind shown = 0.0
if len(sp) > 0.0 {
print("")
print(cx_stage("on the altar") + cx_dim(" (sealed by the next rite — `miao withdraw <path>` to take back)"))
bind i = 0.0
while i < len(sp) {
bind s = list_get(ss, i)
bind tag = "offered "
if s == "new" { bind tag = "new " }
if s == "gone" { bind tag = "gone " }
if s == "edit" { bind tag = "renewed " }
print(" " + cx_stage(tag) + cx_stage(list_get(sp, i)))
bind i = i + 1.0
bind shown = shown + 1.0
}
}
if len(rp) > 0.0 {
print("")
print(cx_warn("restless spirits") + cx_dim(" (changed since enshrined — `miao offer <path>` to stage)"))
bind i = 0.0
while i < len(rp) {
bind tag = "changed "
if list_get(rs, i) == "gone" { bind tag = "departed" }
print(" " + cx_warn(tag) + " " + cx_warn(list_get(rp, i)))
bind i = i + 1.0
bind shown = shown + 1.0
}
}
if len(wander) > 0.0 {
print("")
print(cx_tal("wandering spirits") + cx_dim(" (untracked — `miao offer <path>` to enshrine)"))
bind i = 0.0
while i < len(wander) {
print(" " + cx_tal(" " + list_get(wander, i)))
bind i = i + 1.0
bind shown = shown + 1.0
}
}
if file_exists(sx_dir() + "/DISCORD") {
print("")
print(cx_err("⚠ discord in the temple — resolve the marked files, offer them, then seal with `miao rite`"))
} else if shown < 0.5 {
print(cx_good("the temple is serene — nothing to divine"))
}
return 0.0
}
# ── offer (stage) ─────────────────────────────────────────────────────
fn rt_offer_one(rel) {
bind abs = sx_root() + "/" + rel
bind head = sx_rite_manifest(sx_head_rite())
bind hids = list_get(head, 0.0)
bind hpaths = list_get(head, 1.0)
bind hat = ut_index_of(hpaths, rel)
if file_exists(abs) == false {
if hat >= 0.0 {
sx_altar_set(rel, "-")
print(" " + cx_err("⊖ released ") + rel)
return 1.0
}
print(" " + cx_err("no such spirit: " + rel))
return 0.0
}
bind a = sx_altar()
bind aat = ut_index_of(list_get(a, 1.0), rel)
bind prev = ""
if aat >= 0.0 {
bind prev = list_get(list_get(a, 0.0), aat)
if prev == "-" { bind prev = "" }
}
if prev == "" {
if hat >= 0.0 { bind prev = list_get(hids, hat) }
}
bind res = sx_spirit_put(abs, prev)
bind id = list_get(res, 0.0)
bind strat = list_get(res, 1.0)
if id == "" {
print(" " + cx_err("unreadable: " + rel))
return 0.0
}
if hat >= 0.0 {
if list_get(hids, hat) == id {
sx_altar_del(rel)
print(" " + cx_dim("∅ serene " + rel) + cx_dim(" (matches the enshrined spirit)"))
return 0.0
}
}
sx_altar_set(rel, id)
bind glyph = "○ whole "
if strat == "delta" { bind glyph = "◐ delta " }
if str_starts_with(strat, "chunks") { bind glyph = "◍ " + strat }
if strat == "kept" { bind glyph = "◉ kept " }
print(" " + cx_stage("⊕ offered ") + ut_pad(rel, 36.0) + cx_meta(" " + glyph))
return 1.0
}
fn rt_offer(args) {
if len(args) < 1.0 {
print(cx_err("what shall be offered? try: miao offer <path> or miao offer ."))
return 0.0
}
bind count = 0.0
bind i = 0.0
while i < len(args) {
bind argp = list_get(args, i)
if argp == "." || argp == "--all" || argp == "-A" {
# everything changed or wandering, plus departures
bind d = rt_status_data()
bind rp = list_get(d, 2.0)
bind wander = list_get(d, 4.0)
bind q = 0.0
while q < len(rp) {
bind count = count + rt_offer_one(list_get(rp, q))
bind q = q + 1.0
}
bind q = 0.0
while q < len(wander) {
bind count = count + rt_offer_one(list_get(wander, q))
bind q = q + 1.0
}
} else {
bind rel = rt_relpath(argp)
bind abs = sx_root() + "/" + rel
if is_dir(abs) {
bind files = sx_walk_dir(abs, rel, list_new())
bind q = 0.0
while q < len(files) {
bind count = count + rt_offer_one(list_get(files, q))
bind q = q + 1.0
}
} else {
bind count = count + rt_offer_one(rel)
}
}
bind i = i + 1.0
}
if count > 0.0 {
print(cx_stage("" + count + " offering(s) on the altar") + cx_dim(" — seal them with `miao rite -m \"...\"`"))
}
return 0.0
}
fn rt_withdraw(args) {
if len(args) < 1.0 {
print(cx_err("withdraw what? try: miao withdraw <path>"))
return 0.0
}
bind i = 0.0
while i < len(args) {
bind rel = rt_relpath(list_get(args, i))
bind a = sx_altar()
if ut_index_of(list_get(a, 1.0), rel) >= 0.0 {
sx_altar_del(rel)
print(" " + cx_warn("⊖ withdrawn ") + rel)
} else {
print(" " + cx_dim("not on the altar: " + rel))
}
bind i = i + 1.0
}
return 0.0
}
# ── rite (commit) ─────────────────────────────────────────────────────
fn rt_rite(msg) {
if msg == "" {
print(cx_err("a rite needs an inscription: miao rite -m \"message\""))
return 0.0
}
bind a = sx_altar()
bind discord = file_exists(sx_dir() + "/DISCORD")
if len(list_get(a, 0.0)) < 1.0 {
if discord == false {
print(cx_warn("the altar is bare — `miao offer <path>` first"))
return 0.0
}
}
bind parents = list_new()
bind head_rite = sx_head_rite()
if head_rite != "" { bind parents = list_push(parents, head_rite) }
if discord {
bind dl = ut_read_lines(sx_dir() + "/DISCORD")
bind first = list_get(dl, 0.0)
bind parts = split(first, "|")
if list_get(parts, 0.0) == "theirs" {
bind parents = list_push(parents, list_get(parts, 1.0))
}
}
bind ov = sx_overlay()
bind scroll = sx_scroll_put(list_get(ov, 0.0), list_get(ov, 1.0))
bind id = sx_rite_put(scroll, parents, sx_author(), msg)
bind h = sx_head()
if list_get(h, 0.0) == "soul" {
sx_set_tip(list_get(h, 1.0), id)
} else {
sx_set_head_rite(id)
}
sx_altar_write(list_new(), list_new())
if discord { remove_file(sx_dir() + "/DISCORD") }
sx_log("rite", id + "|" + ut_first_line(msg))
bind n = len(list_get(ov, 0.0))
print(cx_good("✦ rite sealed ") + cx_aura(id) + cx_dim(" " + n + " spirit(s) enshrined"))
print(cx_dim(" 「") + cx_info(ut_first_line(msg)) + cx_dim("」"))
if discord { print(cx_good(" harmony restored — the discord is resolved")) }
return 0.0
}
# ── lineage (log) ─────────────────────────────────────────────────────
fn rt_lineage(limit, all_flag) {
bind tips = list_new()
if all_flag {
bind souls = sx_souls()
bind i = 0.0
while i < len(souls) {
bind t = sx_tip(list_get(souls, i))
if t != "" {
if ut_contains(tips, t) == false { bind tips = list_push(tips, t) }
}
bind i = i + 1.0
}
} else {
bind t = sx_head_rite()
if t != "" { bind tips = list_push(tips, t) }
}
if len(tips) < 1.0 {
print(cx_dim("the genealogy is empty — no rites have been sealed"))
return 0.0
}
# gather rites breadth-first following all parents, then sort by time
bind seen = list_new()
bind queue = tips
bind qi = 0.0
while qi < len(queue) {
bind id = list_get(queue, qi)
if ut_contains(seen, id) == false {
bind seen = list_push(seen, id)
bind r = sx_rite_read(id)
bind ps = list_get(r, 1.0)
bind k = 0.0
while k < len(ps) {
bind queue = list_push(queue, list_get(ps, k))
bind k = k + 1.0
}
}
bind qi = qi + 1.0
}
# decorate: souls and talismans per rite
bind souls = sx_souls()
bind tals = sx_talismans()
# sort by time desc (selection on small n is fine; lineage is capped anyway)
bind times = list_new()
bind i = 0.0
while i < len(seen) {
bind r = sx_rite_read(list_get(seen, i))
bind times = list_push(times, list_get(r, 3.0))
bind i = i + 1.0
}
bind shown = 0.0
bind used = list_new()
bind i = 0.0
while i < len(seen) {
bind used = list_push(used, 0.0)
bind i = i + 1.0
}
while shown < limit && shown < len(seen) {
bind best = 0.0 - 1.0
bind k = 0.0
while k < len(seen) {
if list_get(used, k) < 0.5 {
if best < 0.0 {
bind best = k
} else if list_get(times, k) > list_get(times, best) {
bind best = k
}
}
bind k = k + 1.0
}
if best < 0.0 {
bind shown = limit
} else {
bind used = list_set(used, best, 1.0)
bind id = list_get(seen, best)
bind r = sx_rite_read(id)
bind deco = ""
bind s = 0.0
while s < len(souls) {
if sx_tip(list_get(souls, s)) == id { bind deco = deco + " " + cx_info("❮" + list_get(souls, s) + "❯") }
bind s = s + 1.0
}
bind s = 0.0
while s < len(tals) {
if sx_talisman_get(list_get(tals, s)) == id { bind deco = deco + " " + cx_tal("符" + list_get(tals, s)) }
bind s = s + 1.0
}
bind merge_mark = ""
if len(list_get(r, 1.0)) > 1.5 { bind merge_mark = cx_tal(" ☯") }
print(cx_aura(id) + " " + cx_meta(ut_fmt_time(list_get(r, 3.0))) + " " + cx_good(ut_pad(list_get(r, 2.0), 12.0)) + " " + ut_first_line(list_get(r, 4.0)) + merge_mark + deco)
bind shown = shown + 1.0
}
}
return 0.0
}
# ── yinyang (diff) ────────────────────────────────────────────────────
fn rt_spirit_text_or(id) {
if id == "" { return "" }
bind info = sx_spirit_info(id)
if list_get(info, 4.0) == "bin" { return "" }
return sx_mat_text(id)
}
fn rt_worktree_text(rel) {
bind r = file_read_hex(sx_root() + "/" + rel)
match r {
bad(e) => { return "" }
ok(v) => { bind r = r }
}
bind t = hex_text(r.unwrap())
match t {
bad(e) => { return "" }
ok(v) => { return t.unwrap() }
}
}
fn rt_is_bin_spirit(id) {
if id == "" { return false }
bind info = sx_spirit_info(id)
return list_get(info, 4.0) == "bin"
}
fn rt_yinyang(args) {
bind staged = false
bind refs = list_new()
bind path_filter = ""
bind i = 0.0
while i < len(args) {
bind a0 = list_get(args, i)
if a0 == "--altar" || a0 == "--staged" || a0 == "--cached" {
bind staged = true
} else if rt_resolve(a0) != "" {
bind refs = list_push(refs, rt_resolve(a0))
} else {
bind path_filter = rt_relpath(a0)
}
bind i = i + 1.0
}
if len(refs) >= 2.0 {
rt_yinyang_rites(list_get(refs, 0.0), list_get(refs, 1.0), path_filter)
return 0.0
}
if len(refs) == 1.0 {
# ref vs worktree
rt_yinyang_worktree(list_get(refs, 0.0), path_filter)
return 0.0
}
if staged {
# altar vs head
bind head = sx_rite_manifest(sx_head_rite())
bind hids = list_get(head, 0.0)
bind hpaths = list_get(head, 1.0)
bind a = sx_altar()
bind aids = list_get(a, 0.0)
bind apaths = list_get(a, 1.0)
bind i = 0.0
bind any = 0.0
while i < len(apaths) {
bind p = list_get(apaths, i)
bind okp = true
if path_filter != "" {
if p != path_filter { bind okp = false }
}
if okp {
bind nid = list_get(aids, i)
bind hat = ut_index_of(hpaths, p)
bind oid = ""
if hat >= 0.0 { bind oid = list_get(hids, hat) }
rt_render_pair(p, oid, nid, "")
bind any = any + 1.0
}
bind i = i + 1.0
}
if any < 0.5 { print(cx_dim("the altar casts no shadow — nothing staged")) }
return 0.0
}
# default: worktree vs altar+head overlay (unstaged changes)
rt_yinyang_worktree("", path_filter)
return 0.0
}
# diff a single file pair by spirit ids; wt_rel != "" means right side is the worktree file
fn rt_render_pair(p, old_id, new_id, wt_rel) {
bind old_bin = rt_is_bin_spirit(old_id)
bind new_bin = false
bind new_txt = ""
if wt_rel != "" {
bind new_txt = rt_worktree_text(wt_rel)
if new_txt == "" {
if file_exists(sx_root() + "/" + wt_rel) {
bind hr = file_read_hex(sx_root() + "/" + wt_rel)
if ut_is_bad(hr) == false {
bind new_bin = len(hr.unwrap()) > 0.0
}
}
}
} else {
bind new_bin = rt_is_bin_spirit(new_id)
if new_bin == false { bind new_txt = rt_spirit_text_or(new_id) }
}
if old_bin || new_bin {
print(cx_tal("☯ " + p) + " " + cx_warn("binary spirits differ"))
return 0.0
}
bind old_txt = rt_spirit_text_or(old_id)
bind label = p
if old_id == "" { bind label = p + cx_good(" (newly manifest)") }
if new_id == "-" {
print(cx_tal("☯ " + p) + " " + cx_err("released from the temple"))
return 0.0
}
print_file(dy_render(old_txt, new_txt, label))
return 0.0
}
fn rt_yinyang_worktree(refid, path_filter) {
bind base = refid
if base == "" {
# overlay = altar + head
bind ov = sx_overlay()
bind bids = list_get(ov, 0.0)
bind bpaths = list_get(ov, 1.0)
rt_yinyang_against(bids, bpaths, path_filter)
return 0.0
}
bind m = sx_rite_manifest(base)
rt_yinyang_against(list_get(m, 0.0), list_get(m, 1.0), path_filter)
return 0.0
}
fn rt_yinyang_against(bids, bpaths, path_filter) {
bind work = sx_walk()
bind any = 0.0
bind i = 0.0
while i < len(work) {
bind p = list_get(work, i)
bind okp = true
if path_filter != "" {
if p != path_filter {
if str_starts_with(p, path_filter + "/") == false { bind okp = false }
}
}
if okp {
bind at = ut_index_of(bpaths, p)
if at >= 0.0 {
bind oid = list_get(bids, at)
bind actual = file_hash(sx_root() + "/" + p)
if actual != oid {
rt_render_pair(p, oid, "", p)
bind any = any + 1.0
}
} else {
print(cx_tal("☯ " + p) + " " + cx_tal("wandering spirit (untracked)"))
bind any = any + 1.0
}
}
bind i = i + 1.0
}
# departures
bind i = 0.0
while i < len(bpaths) {
bind p = list_get(bpaths, i)
bind okp = true
if path_filter != "" {
if p != path_filter { bind okp = false }
}
if okp {
if file_exists(sx_root() + "/" + p) == false {
print(cx_tal("☯ " + p) + " " + cx_err("departed (deleted in the worktree)"))
bind any = any + 1.0
}
}
bind i = i + 1.0
}
if any < 0.5 { print(cx_good("yin and yang are balanced — no differences")) }
return 0.0
}
fn rt_yinyang_rites(a, b, path_filter) {
bind ma = sx_rite_manifest(a)
bind mb = sx_rite_manifest(b)
bind aids = list_get(ma, 0.0)
bind apaths = list_get(ma, 1.0)
bind bids = list_get(mb, 0.0)
bind bpaths = list_get(mb, 1.0)
bind any = 0.0
bind i = 0.0
while i < len(bpaths) {
bind p = list_get(bpaths, i)
bind okp = true
if path_filter != "" {
if p != path_filter { bind okp = false }
}
if okp {
bind at = ut_index_of(apaths, p)
bind oid = ""
if at >= 0.0 { bind oid = list_get(aids, at) }
if oid != list_get(bids, i) {
rt_render_pair(p, oid, list_get(bids, i), "")
bind any = any + 1.0
}
}
bind i = i + 1.0
}
bind i = 0.0
while i < len(apaths) {
bind p = list_get(apaths, i)
bind okp = true
if path_filter != "" {
if p != path_filter { bind okp = false }
}
if okp {
if ut_contains(bpaths, p) == false {
print(cx_tal("☯ " + p) + " " + cx_err("released between these rites"))
bind any = any + 1.0
}
}
bind i = i + 1.0
}
if any < 0.5 { print(cx_good("yin and yang are balanced — no differences")) }
return 0.0
}
# ── souls (branches) ──────────────────────────────────────────────────
fn rt_soul(args) {
bind h = sx_head()
bind cur = ""
if list_get(h, 0.0) == "soul" { bind cur = list_get(h, 1.0) }
if len(args) < 1.0 {
bind souls = sx_souls()
bind i = 0.0
while i < len(souls) {
bind s = list_get(souls, i)
bind tip = sx_tip(s)
bind line = ""
if s == cur {
bind line = cx_good("● " + ut_pad(s, 16.0))
} else {
bind line = cx_info("○ " + ut_pad(s, 16.0))
}
if tip != "" {
bind r = sx_rite_read(tip)
bind line = line + " " + cx_aura(tip) + " " + cx_dim(ut_first_line(list_get(r, 4.0)))
} else {
bind line = line + " " + cx_dim("(unborn)")
}
print(line)
bind i = i + 1.0
}
return 0.0
}
bind first = list_get(args, 0.0)
if first == "-d" || first == "--release" {
bind name = list_get(args, 1.0)
if name == cur {
print(cx_err("cannot release the living soul — summon another first"))
return 0.0
}
if file_exists(sx_dir() + "/souls/" + name) == false {
print(cx_err("no such soul: " + name))
return 0.0
}
remove_file(sx_dir() + "/souls/" + name)
print(cx_warn("soul released: " + name))
return 0.0
}
if file_exists(sx_dir() + "/souls/" + first) {
print(cx_err("that soul already dwells here: " + first))
return 0.0
}
bind at = sx_head_rite()
if len(args) > 1.5 { bind at = rt_resolve(list_get(args, 1.0)) }
sx_set_tip(first, at)
sx_log("soul", first + "|" + at)
print(cx_good("✦ new soul kindled: ") + cx_info(first) + cx_dim(ut_sel(at == "", " (unborn)", " at " + ut_short(at))))
print(cx_dim(" summon it with `miao summon " + first + "`"))
return 0.0
}
# ── summon (checkout / switch) ────────────────────────────────────────
fn rt_summon(args) {
if len(args) < 1.0 {
print(cx_err("summon which soul? try: miao summon <soul|rite|talisman>"))
return 0.0
}
bind target = list_get(args, 0.0)
bind force = false
bind i = 1.0
while i < len(args) {
if list_get(args, i) == "--force" || list_get(args, i) == "-f" { bind force = true }
bind i = i + 1.0
}
bind rite = rt_resolve(target)
bind is_soul = file_exists(sx_dir() + "/souls/" + target)
if rite == "" {
if is_soul == false {
print(cx_err("no soul, talisman or rite answers to: " + target))
return 0.0
}
}
if force == false {
bind d = rt_status_data()
# missing files are harmless to summon over; edits and offerings are not
bind rs = list_get(d, 3.0)
bind edits = 0.0
bind q = 0.0
while q < len(rs) {
if list_get(rs, q) == "edit" { bind edits = edits + 1.0 }
bind q = q + 1.0
}
bind dirty = len(list_get(d, 0.0)) + edits
if dirty > 0.5 {
print(cx_err("the temple is unsettled — offerings or restless spirits would be lost"))
print(cx_dim(" seal a rite first, or summon with --force to discard"))
return 0.0
}
}
bind cur_m = sx_rite_manifest(sx_head_rite())
bind new_m = sx_rite_manifest(rite)
bind cids = list_get(cur_m, 0.0)
bind cpaths = list_get(cur_m, 1.0)
bind nids = list_get(new_m, 0.0)
bind npaths = list_get(new_m, 1.0)
bind wrote = 0.0
bind i = 0.0
while i < len(npaths) {
bind p = list_get(npaths, i)
bind at = ut_index_of(cpaths, p)
bind need = true
if at >= 0.0 {
if list_get(cids, at) == list_get(nids, i) {
if file_exists(sx_root() + "/" + p) { bind need = false }
}
}
if need {
sx_checkout_spirit(list_get(nids, i), sx_root() + "/" + p)
bind wrote = wrote + 1.0
}
bind i = i + 1.0
}
bind gone = 0.0
bind i = 0.0
while i < len(cpaths) {
bind p = list_get(cpaths, i)
if ut_contains(npaths, p) == false {
remove_file(sx_root() + "/" + p)
bind gone = gone + 1.0
}
bind i = i + 1.0
}
sx_altar_write(list_new(), list_new())
if is_soul {
sx_set_head_soul(target)
print(cx_good("✦ soul summoned: ") + cx_info(target) + cx_dim(" (" + wrote + " renewed, " + gone + " released)"))
} else {
sx_set_head_rite(rite)
print(cx_warn("✦ wandering at rite ") + cx_aura(rite) + cx_dim(" (detached — kindle a soul with `miao soul <name>` to keep work)"))
}
sx_log("summon", target)
return 0.0
}
# ── harmonize (merge) ─────────────────────────────────────────────────
fn rt_ancestors(id) {
bind seen = list_new()
bind queue = list_new()
if id != "" { bind queue = list_push(queue, id) }
bind qi = 0.0
while qi < len(queue) {
bind cur = list_get(queue, qi)
if ut_contains(seen, cur) == false {
bind seen = list_push(seen, cur)
bind r = sx_rite_read(cur)
bind ps = list_get(r, 1.0)
bind k = 0.0
while k < len(ps) {
bind queue = list_push(queue, list_get(ps, k))
bind k = k + 1.0
}
}
bind qi = qi + 1.0
}
return seen
}
fn rt_merge_base(a, b) {
bind anc = rt_ancestors(a)
bind queue = list_new()
bind queue = list_push(queue, b)
bind seen = list_new()
bind qi = 0.0
while qi < len(queue) {
bind cur = list_get(queue, qi)
if ut_contains(anc, cur) { return cur }
if ut_contains(seen, cur) == false {
bind seen = list_push(seen, cur)
bind r = sx_rite_read(cur)
bind ps = list_get(r, 1.0)
bind k = 0.0
while k < len(ps) {
bind queue = list_push(queue, list_get(ps, k))
bind k = k + 1.0
}
}
bind qi = qi + 1.0
}
return ""
}
fn rt_harmonize(args) {
if len(args) < 1.0 {
print(cx_err("harmonize with whom? try: miao harmonize <soul>"))
return 0.0
}
bind name = list_get(args, 0.0)
bind theirs = rt_resolve(name)
if theirs == "" {
print(cx_err("no soul, talisman or rite answers to: " + name))
return 0.0
}
bind h = sx_head()
if list_get(h, 0.0) != "soul" {
print(cx_err("cannot harmonize while wandering detached — summon a soul first"))
return 0.0
}
bind cur_soul = list_get(h, 1.0)
bind ours = sx_head_rite()
if theirs == ours {
print(cx_good("already in perfect harmony"))
return 0.0
}
bind d = rt_status_data()
bind dirty = len(list_get(d, 0.0)) + len(list_get(d, 2.0))
if dirty > 0.5 {
print(cx_err("the temple is unsettled — seal or restore before harmonizing"))
return 0.0
}
bind base = rt_merge_base(ours, theirs)
if base == theirs {
print(cx_good("the temple already holds everything from " + name))
return 0.0
}
if base == ours || ours == "" {
# fast-forward
rt_summon_to_rite(theirs)
sx_set_tip(cur_soul, theirs)
sx_set_head_soul(cur_soul)
print(cx_good("✦ fast-forward — ") + cx_info(cur_soul) + cx_good(" now flows at ") + cx_aura(theirs))
sx_log("harmonize-ff", name)
return 0.0
}
# true three-way merge
bind mb = sx_rite_manifest(base)
bind mo = sx_rite_manifest(ours)
bind mt = sx_rite_manifest(theirs)
bind union = list_new()
bind src = [list_get(mb, 1.0), list_get(mo, 1.0), list_get(mt, 1.0)]
bind s = 0.0
while s < 3.0 {
bind ps = list_get(src, s)
bind i = 0.0
while i < len(ps) {
bind p = list_get(ps, i)
if ut_contains(union, p) == false { bind union = list_push(union, p) }
bind i = i + 1.0
}
bind s = s + 1.0
}
bind union = ut_sort(union)
bind discord_paths = list_new()
bind merged = 0.0
bind i = 0.0
while i < len(union) {
bind p = list_get(union, i)
bind ob = rt_m_id(mb, p)
bind oo = rt_m_id(mo, p)
bind ot = rt_m_id(mt, p)
if oo == ot {
# same on both sides: nothing to do
bind i = i
} else if ot == ob {
# only ours changed: keep ours
bind i = i
} else if oo == ob {
# only theirs changed: take theirs
if ot == "" {
if file_exists(sx_root() + "/" + p) { remove_file(sx_root() + "/" + p) }
sx_altar_set(p, "-")
} else {
sx_checkout_spirit(ot, sx_root() + "/" + p)
sx_altar_set(p, ot)
}
bind merged = merged + 1.0
} else {
# both sides changed
bind can_text = true
if oo == "" || ot == "" { bind can_text = false }
if can_text {
if rt_is_bin_spirit(oo) { bind can_text = false }
}
if can_text {
if rt_is_bin_spirit(ot) { bind can_text = false }
}
if can_text {
bind tb = ""
if ob != "" { bind tb = rt_spirit_text_or(ob) }
bind to2 = rt_spirit_text_or(oo)
bind tt = rt_spirit_text_or(ot)
bind mres = dy_merge3(tb, to2, tt, cur_soul, name)
bind mtext = list_get(mres, 0.0)
bind ncf = list_get(mres, 1.0)
write_file(sx_root() + "/" + p, mtext)
if ncf > 0.5 {
bind discord_paths = list_push(discord_paths, p)
print(" " + cx_err("☯ discord " + p) + cx_dim(" (" + ncf + " clash(es) marked in the file)"))
} else {
bind res = sx_spirit_put(sx_root() + "/" + p, oo)
sx_altar_set(p, list_get(res, 0.0))
print(" " + cx_good("☯ harmonized " + p))
bind merged = merged + 1.0
}
} else {
# binary clash or add/delete clash: keep ours, flag discord
bind discord_paths = list_push(discord_paths, p)
print(" " + cx_err("☯ discord " + p) + cx_dim(" (kept our spirit; offer the resolution)"))
}
}
bind i = i + 1.0
}
if len(discord_paths) > 0.0 {
bind t = "theirs|" + theirs + "|" + name + "\n"
bind i = 0.0
while i < len(discord_paths) {
bind t = t + "path|" + list_get(discord_paths, i) + "\n"
bind i = i + 1.0
}
write_file(sx_dir() + "/DISCORD", t)
print(cx_err("" + len(discord_paths) + " spirit(s) in discord") + cx_dim(" — resolve, `miao offer` each, then seal with `miao rite -m \"...\"`"))
} else {
# record the second parent so the lineage knows this is a union
write_file(sx_dir() + "/DISCORD", "theirs|" + theirs + "|" + name + "\n")
rt_rite("Harmonize " + name + " into " + cur_soul)
}
return 0.0
}
fn rt_m_id(m, p) {
bind at = ut_index_of(list_get(m, 1.0), p)
if at < 0.0 { return "" }
return list_get(list_get(m, 0.0), at)
}
# checkout helper used by fast-forward (no SOUL bookkeeping)
fn rt_summon_to_rite(rite) {
bind cur_m = sx_rite_manifest(sx_head_rite())
bind new_m = sx_rite_manifest(rite)
bind cpaths = list_get(cur_m, 1.0)
bind cids = list_get(cur_m, 0.0)
bind npaths = list_get(new_m, 1.0)
bind nids = list_get(new_m, 0.0)
bind i = 0.0
while i < len(npaths) {
bind p = list_get(npaths, i)
bind at = ut_index_of(cpaths, p)
bind need = true
if at >= 0.0 {
if list_get(cids, at) == list_get(nids, i) {
if file_exists(sx_root() + "/" + p) { bind need = false }
}
}
if need { sx_checkout_spirit(list_get(nids, i), sx_root() + "/" + p) }
bind i = i + 1.0
}
bind i = 0.0
while i < len(cpaths) {
bind p = list_get(cpaths, i)
if ut_contains(npaths, p) == false {
if file_exists(sx_root() + "/" + p) { remove_file(sx_root() + "/" + p) }
}
bind i = i + 1.0
}
return 0.0
}
# ── talismans (tags) ──────────────────────────────────────────────────
fn rt_talisman(args) {
if len(args) < 1.0 {
bind ts = sx_talismans()
if len(ts) < 1.0 {
print(cx_dim("no talismans hang in the temple"))
return 0.0
}
bind i = 0.0
while i < len(ts) {
bind name = list_get(ts, i)
bind id = sx_talisman_get(name)
bind r = sx_rite_read(id)
print(cx_tal("符 " + ut_pad(name, 16.0)) + " " + cx_aura(id) + " " + cx_dim(ut_first_line(list_get(r, 4.0))))
bind i = i + 1.0
}
return 0.0
}
bind name = list_get(args, 0.0)
bind at = sx_head_rite()
if len(args) > 1.5 { bind at = rt_resolve(list_get(args, 1.0)) }
if at == "" {
print(cx_err("nothing to fix the talisman to"))
return 0.0
}
sx_talisman_set(name, at)
print(cx_tal("符 talisman hung: " + name) + cx_dim(" at ") + cx_aura(at))
return 0.0
}
# ── manifest (show) ───────────────────────────────────────────────────
fn rt_manifest(args) {
if len(args) < 1.0 {
bind args = ["@"]
}
bind what = list_get(args, 0.0)
if what == "@" { bind what = "" }
bind rite = rt_resolve(what)
if rite == "" {
# maybe a path: show the enshrined content
bind rel = rt_relpath(what)
bind head = sx_rite_manifest(sx_head_rite())
bind at = ut_index_of(list_get(head, 1.0), rel)
if at >= 0.0 {
bind id = list_get(list_get(head, 0.0), at)
if rt_is_bin_spirit(id) {
print(cx_warn("a binary spirit — " + rel))
} else {
print_file(sx_mat_text(id))
}
return 0.0
}
print(cx_err("nothing answers to: " + what))
return 0.0
}
bind r = sx_rite_read(rite)
bind m = sx_rite_manifest(rite)
bind ids = list_get(m, 0.0)
bind paths = list_get(m, 1.0)
print(cx_rainbow("✦ rite ") + cx_aura(rite) + cx_dim(" (" + rite + ")"))
print(cx_meta(" sealed ") + cx_info(ut_fmt_time(list_get(r, 3.0))))
print(cx_meta(" keeper ") + cx_good(list_get(r, 2.0)))
bind ps = list_get(r, 1.0)
bind i = 0.0
while i < len(ps) {
print(cx_meta(" parent ") + cx_aura(list_get(ps, i)))
bind i = i + 1.0
}
print(cx_meta(" scripture") + cx_dim(" 「") + list_get(r, 4.0) + cx_dim("」"))
print("")
bind logical = 0.0
bind i = 0.0
while i < len(paths) {
bind info = sx_spirit_info(list_get(ids, i))
bind strat = list_get(info, 0.0)
bind size = list_get(info, 3.0)
bind logical = logical + size
bind glyph = cx_good("○ whole ")
if strat == "delta" { bind glyph = cx_info("◐ delta ") }
if strat == "chunks" { bind glyph = cx_tal("◍ chunks") }
print(" " + glyph + " " + ut_pad(list_get(paths, i), 40.0) + cx_dim(" " + size + " B"))
bind i = i + 1.0
}
print(cx_dim(" " + len(paths) + " spirit(s), " + floor(logical / 1024.0) + " KiB enshrined"))
return 0.0
}
# ── restore ───────────────────────────────────────────────────────────
fn rt_restore(args) {
if len(args) < 1.0 {
print(cx_err("restore what? try: miao restore <path>"))
return 0.0
}
bind i = 0.0
while i < len(args) {
bind rel = rt_relpath(list_get(args, i))
bind a = sx_altar()
bind at = ut_index_of(list_get(a, 1.0), rel)
bind id = ""
if at >= 0.0 { bind id = list_get(list_get(a, 0.0), at) }
if id == "" || id == "-" {
bind head = sx_rite_manifest(sx_head_rite())
bind hat = ut_index_of(list_get(head, 1.0), rel)
if hat >= 0.0 { bind id = list_get(list_get(head, 0.0), hat) }
}
if id == "" || id == "-" {
print(" " + cx_err("nothing enshrined at: " + rel))
} else {
sx_checkout_spirit(id, sx_root() + "/" + rel)
print(" " + cx_good("↺ returned ") + rel)
}
bind i = i + 1.0
}
return 0.0
}