diff --git a/good-fences/docs/lend-the-mower.md b/good-fences/docs/lend-the-mower.md index d7ebe75..aa02cb8 100644 --- a/good-fences/docs/lend-the-mower.md +++ b/good-fences/docs/lend-the-mower.md @@ -38,10 +38,10 @@ sequenceDiagram MF-->>F: mower F-->>P: govern(mower, 2) P-->>F: governed - F-->>N: chat({ role, content, things: { mower }, about: { mower } }) - N-->>L: complete([{ role, content, about: { mower } }]) + F-->>N: chat({ role, content, things: { mower: governed }, about: { mower: { ts } } }) + N-->>L: complete([{ role, content, about: { mower: { ts } } }]) L-->>N: code - N-->>TL: load(code, { mower }) + N-->>TL: load(code, { mower: governed }) TL-->>N: tenant N-->>T: run() T-->>G: start() diff --git a/good-fences/test/lend-the-mower.test.ts b/good-fences/test/lend-the-mower.test.ts index 406afe5..806155d 100644 --- a/good-fences/test/lend-the-mower.test.ts +++ b/good-fences/test/lend-the-mower.test.ts @@ -31,14 +31,23 @@ const tipsyTenant = `(env) => { return 'mowed 20 cells'; }`; -/** `{ a, b: { c } }`: keys, and the keys of object-valued members */ -const shape = (record: Readonly>) => +/** diagram-local names, bound by the reply arrows that introduce them */ +const local = new WeakMap(); +const bind = (name: string) => (result: unknown) => { + local.set(result as object, name); + return name; +}; + +/** `{ a, b: { c: governed } }`: keys, nested objects by their keys, and + * objects with a diagram-local name by that name */ +const shape = (record: object): string => `{ ${Object.entries(record) - .map(([key, value]) => - value !== null && typeof value === 'object' && !Array.isArray(value) - ? `${key}: { ${Object.keys(value).join(', ')} }` - : key, - ) + .map(([key, value]) => { + if (value === null || typeof value !== 'object') return key; + const name = local.get(value); + if (name) return `${key}: ${name}`; + return Array.isArray(value) ? key : `${key}: ${shape(value)}`; + }) .join(', ')} }`; const quoted = (result: unknown) => `'${String(result)}'`; @@ -50,19 +59,22 @@ const viz = harden({ return `lend({ webkey: '${webkey}', limit: ${limit}, say })`; }, }, - mower: { result: () => 'mower' }, - govern: { args: args => `mower, ${String(args[1])}`, result: () => 'governed' }, + mower: { result: bind('mower') }, + govern: { + args: args => `${local.get(args[0] as object)}, ${String(args[1])}`, + result: bind('governed'), + }, chat: { - label: args => `chat(${shape(args[0] as Record)})`, + label: args => `chat(${shape(args[0] as object)})`, result: quoted, }, complete: { label: args => - `complete([${(args[0] as Record[]).map(shape).join(', ')}])`, + `complete([${(args[0] as object[]).map(shape).join(', ')}])`, result: () => 'code', }, load: { - args: args => `code, { ${Object.keys(args[1] as object).join(', ')} }`, + args: args => `code, ${shape(args[1] as object)}`, result: () => 'tenant', }, run: { result: quoted },