Orgchain v1.8: belts cross holdings, and a graduate becomes its own holding

From the operator's notes on trying v1.6.1. An award's recipient may sit in
any holding, so a registry like well-known can certify an agent it doesn't
hold (say, after the agent pays it). A graduated org already held its own
root; now it is a holding of its own too: it and its subtree re-root under
it, it joins the Holdings list with its own tree and timeline, mines its
share and can be funded, and its parent's tree keeps a row for it that opens
it. Events that touch two holdings (a belt across them, a graduation) show in
both timelines, and the holding that acted gets the last-act credit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01H4upF5LVwmPDDqrhdUfnXh
This commit is contained in:
teahubxyzandClaude Opus 5.5 committed 2026-10-15 00:44:59 -07:00
1 parent 69a97544da
commit 7d981341ff
11 files changed
+122 -37

No files matched your search

+21 -2
View File
@@ -31,7 +31,7 @@ test('every rule rejects with a reason, and rejected events change nothing', ()
[ev('found', null, { name: 'acme' }), /already named acme/], [ev('birth', 'f'.repeat(64) + 'i0', { name: 'x' }), /not in this lineage/],
[ev('birth', bot.id, { name: 'x' }), /agents do not give birth/], [ev('birth', root.id, { name: 'ops' }), /already has an active ops/],
[ev('award', bot.id, { to: ops.id, skill: 'launch', belt: 'green' }), /agents do not award/],
[ev('award', root.id, { to: other.id, skill: 'launch', belt: 'green' }), /another node in this holding/],
[ev('award', root.id, { to: 'f'.repeat(64) + 'i0', skill: 'launch', belt: 'green' }), /another node in this lineage/],
[ev('award', root.id, { to: root.id, skill: 'launch', belt: 'green' }), /another node/],
[ev('award', root.id, { to: bot.id, skill: 'launch', belt: 'gold' }), /belt/], [ev('decide', root.id, { title: ' ' }), /title/],
[ev('graduate', ops.id, { of: bot.id }), /only its parent/], [ev('graduate', root.id, { of: bot.id }), /only orgs graduate/],
@@ -59,7 +59,26 @@ test('graduation flips the edge; closing cascades through derived children only'
assert.equal(summary(s.log.find(e => e.id === close.id), s), 'close lab and 2 derived');
assert.match(s.log.find(e => e.id === after.id).why, /parent is closed/);
assert.equal(s.nodes.get(grad.id).decisions[0].title, 'Carry on');
assert.deepEqual(census(s, root.id), { orgs: 3, agents: 1, belts: 1, decisions: 1, closed: 3 });
// A graduate is a holding of its own: its parent's tree keeps a row for it, and its own tree starts at it.
assert.deepEqual(s.roots.map(r => r.id), [root.id, grad.id]);
assert.equal(s.nodes.get(grad.id).root, grad.id);
assert.deepEqual(s.log.find(e => e.id === up.id).roots, [root.id, grad.id]);
assert.deepEqual(s.log.find(e => e.id === still.id).roots, [grad.id]);
assert.deepEqual(rows(s, root.id).filter(r => r.away).map(r => r.node.name), ['grad']);
assert.deepEqual(draw(s, grad.id), ['● grad']);
assert.equal(trail(s, grad.id), 'grad');
assert.deepEqual(census(s, root.id), { orgs: 2, agents: 1, belts: 1, decisions: 0, closed: 3 });
assert.deepEqual(census(s, grad.id), { orgs: 0, agents: 0, belts: 0, decisions: 1, closed: 0 });
});
test('a belt can cross holdings: the event shows in both, and the issuer acted', () => {
const wk = ev('found', null, { name: 'well-known' }), other = ev('found', null, { name: 'acme' }), bot = ev('birth', other.id, { name: 'bot', kind: 'agent' });
const award = ev('award', wk.id, { to: bot.id, skill: 'listen', belt: 'white' }, 2);
const s = reduce([wk, other, bot, award]), entry = s.log.at(-1);
assert.equal(entry.ok, true);
assert.deepEqual([entry.root, entry.roots], [wk.id, [wk.id, other.id]]);
assert.deepEqual(s.nodes.get(bot.id).badges.map(b => [b.skill, b.belt, b.by]), [['listen', 'white', wk.id]]);
assert.equal(summary(entry, s), 'award listen · white → bot, from well-known');
});
test('upTo shows a past beat; pending adds cued events', () => {