honker: row 256 design draft 2 (webby-0122): T4 uses the last-listed refusal (R1), endProtected keeps its name with comments rewritten (Q1), bus test in creative.test.mjs (Q2), M1 killed by T2 only and the chief's human-required pinned (N1), M4 for the actor threading (N2)

This commit is contained in:
jason.woltje committed 2026-10-22 03:51:41 -05:00
1 parent c3e0bd9db6
commit 8c50481d2f
1 file changed
+28 -12
+28 -12
View File
@@ -1,7 +1,8 @@
# Row 256 (#1761) design: the human deletes a creative instance # Row 256 (#1761) design: the human deletes a creative instance
Brief: docs/plans/2026-10-21_creative-delete-human.md (REQ-COS-3). Base be2b008cc (row 194 landed as Brief: docs/plans/2026-10-21_creative-delete-human.md (REQ-COS-3). Base be2b008cc (row 194 landed as
fd6dd327c). Builder Honker, reviewer Webby. Draft 1, 2026-10-22. fd6dd327c). Builder Honker, reviewer Webby. Draft 2, 2026-10-22: Webby's d1 review (webby-0122, notes
171480e6e) R1, Q1, Q2 and N1-N2 applied; the changes are listed at the end.
## What changes ## What changes
@@ -122,14 +123,14 @@ closing line says the fire half is closed by ruling, not by code.
| business/tests/instance-settings.test.mjs | T1: the human deletes a creative instance (bean); the file loses the entry. | | business/tests/instance-settings.test.mjs | T1: the human deletes a creative instance (bean); the file loses the entry. |
| | T2: the same delete by a role actor (`chief-of-staff.chief`), by "tester" and by no actor refuses `organization-creative-human-only`, and the file is unchanged. | | | T2: the same delete by a role actor (`chief-of-staff.chief`), by "tester" and by no actor refuses `organization-creative-human-only`, and the file is unchanged. |
| | T3: the human's delete of the chief of staff refuses `organization-definition-refused`. | | | T3: the human's delete of the chief of staff refuses `organization-definition-refused`. |
| | T4: a creative instance in launch.keep refuses `organization-instance-kept` for the human, so it reaches the later checks. | | | T4 (R1): with bean the only name in launch.instances, the human's delete of bean gets the last-listed BusinessError from deletedDocument (:64-66), not the creative code, so it passes protectedRefusal and reaches the later checks. A creative instance can't be in launch.keep, launch.by or the arbiters (business.mjs:208, :181-183, :251-255), so those aren't used. |
| | T5: read(business, human) shows `endProtected: false` for bean; read(business, "tester") and read(business) show `true`; the chief of staff shows `true` for both. | | | T5: read(business, human) shows `endProtected: false` for bean; read(business, "tester") and read(business) with no actor show `true`; the chief of staff shows `true` for every actor. |
| | The existing :283-292 test is updated where it pinned the old refusal. | | | The existing :283-292 test is updated where it pinned the old refusal. |
| business/tests/lifecycle-settings.test.mjs | checkDelete with the human passes for a creative instance and with another actor refuses. | | business/tests/lifecycle-settings.test.mjs | checkDelete with the human passes for a creative instance and with another actor refuses. |
| | The fire of a creative instance by the human still refuses (fire unchanged). | | | The fire of a creative instance by the human still refuses (fire unchanged). |
| bus/tests/creative.test.mjs (or instances-verb.test.mjs, wherever the creative fixture lives) | T6: the human's `instances.set op delete` on bean records a lifecycle.delete request. | | bus/tests/creative.test.mjs (Q2: its runtime() is a real startBroker with the business writer) | T6: the human's `instances.set op delete` on bean records a lifecycle.delete request. |
| | Taking it and running the launcher pass commits the delete (the r.by path). | | | Taking it and running the launcher pass commits the delete (the r.by path). |
| | The chief's tool and the tester are refused, with the tester refused `tester-refused` at the verb. | | | The chief is refused `human-required` (broker.mjs:2585) and the tester `tester-refused` (:2595), both at the verb. |
| | The human's `instances` read has `endProtected: false` for bean; the tester's has `true`. | | | The human's `instances` read has `endProtected: false` for bean; the tester's has `true`. |
| webui/tests/agents-browser.test.mjs | T7: the human page with bean at `endProtected: false` offers Delete for bean. | | webui/tests/agents-browser.test.mjs | T7: the human page with bean at `endProtected: false` offers Delete for bean. |
| | T8: the tester page with the same listing offers no Delete. | | | T8: the tester page with the same listing offers no Delete. |
@@ -139,15 +140,19 @@ closing line says the fire half is closed by ruling, not by code.
- The server side of "never on the tester listener" is T5/T6. - The server side of "never on the tester listener" is T5/T6.
- No test touches live paths: fixtures under mktemp in /mnt/storage/scratch, as today. - No test touches live paths: fixtures under mktemp in /mnt/storage/scratch, as today.
## Mutants (both must be killed) ## Mutants (all must be killed)
- M1: protectedRefusal's creative branch returns `null` for every actor, so a non-human deletes a - M1: protectedRefusal's creative branch returns `null` for every actor, so a non-human deletes a
creative instance. Killed by T2 and T6. creative instance. Killed by T2 only (N1): through the bus no non-human actor reaches the delete,
since the chief and the tester are refused at the verb.
- M2: protectedRefusal checks the human before the creative check, so - M2: protectedRefusal checks the human before the creative check, so
`actor === document.human ? null : ...` for every END_PROTECTED definition. The human then `actor === document.human ? null : ...` for every END_PROTECTED definition. The human then
deletes the chief of staff. Killed by T3. deletes the chief of staff. Killed by T3.
- M3: read() keeps the old `END_PROTECTED.includes`, so the listing isn't the per-viewer predicate. - M3: read() keeps the old `END_PROTECTED.includes`, so the listing isn't the per-viewer predicate.
Killed by T5. Killed by T5.
- M4 (N2): the actor isn't threaded: runtime.mjs:283 calls `checkDelete(id, args.instance)`
without it. Killed by T6, the human's real-writer delete. A second variant, set op delete not
passing the actor to planDelete, is killed by T1 and by T6's launcher pass.
## Boundaries kept ## Boundaries kept
@@ -161,10 +166,21 @@ closing line says the fire half is closed by ruling, not by code.
- Touched test files, each whole. - Touched test files, each whole.
- The business, bus, cli and webui suites. - The business, bus, cli and webui suites.
- Every scripts/test-*.sh. - Every scripts/test-*.sh.
- The three mutants above, each on a green base, restored and blob-checked (the runb8 shape). - The four mutants above (M4 in both variants), each on a green base, restored and blob-checked (the runb8 shape).
## Open for Webby ## Comments rewritten (Q1)
1. Keep `endProtected` with a per-viewer value, or rename it. - `endProtected` keeps its name: agents.js:46 is its only reader, and it means "don't offer Delete".
2. Whether the bus test belongs in creative.test.mjs (the existing creative-human-only fixture) or - instance-settings.mjs:28-31 loses "no one deletes one yet". It says the human deletes a creative
instances-verb.test.mjs. instance and any other actor is refused, and that the listing's endProtected is protectedRefusal
for the reader.
- agents.js:45 says the same, naming row 256.
## Changes from draft 1 (webby-0122)
- R1: T4 uses the last-listed refusal instead of launch.keep, which the validator refuses for a
creative instance.
- Q1: keep the name; comments rewritten; T5 pins read(business) with no actor as true.
- Q2: the bus test goes in creative.test.mjs.
- N1: M1 is killed by T2 only; T6 pins the chief's `human-required`.
- N2: M4 added for the threading.