diff --git a/agents/honker/work/queue-194/DESIGN.md b/agents/honker/work/queue-194/DESIGN.md index a5f1975ca..874729505 100644 --- a/agents/honker/work/queue-194/DESIGN.md +++ b/agents/honker/work/queue-194/DESIGN.md @@ -114,7 +114,7 @@ directory, and clearing that is T1 item 7 (clear context). This row doesn't take | `organization-definition-refused` | I is END_PROTECTED | | `organization-instance-referenced` | I is `launch.by` or an arbiter. The message names the reference | | `organization-instance-kept` | I is in `launch.keep`. The human runs `veto unkeep` first. Delete never clears a veto silently | -| `organization-credentials-out-of-scope` | I holds credentials or a tracker bot. That stays a hand edit until row 195 | +| `organization-credentials-out-of-scope` | I holds credentials or a tracker bot. That stays a hand edit until the credentials row (T1 item 6, not yet filed) | | `instance-running` | the broker sees a claim for I. The human terminates first | | BusinessError | I is the last name in `launch.instances` (E1). The message says so | @@ -140,7 +140,7 @@ What stays: `veto.set` args: `{ revision, op: "keep" | "unkeep" | "nohire" | "hire", name }`. It goes through the organization writer, so it is logged with actor and diff in `changes.jsonl`. `keep` needs a declared, non-END_PROTECTED instance. `nohire` needs a definition in `rolesDir`. A no-op answers -`organization-no-change`. It is human-only and isn't in `TESTER_ORGANIZATION_VERBS` (Q3). +`organization-no-change`. It is human-only and isn't in `TESTER_ORGANIZATION_VERBS`. ## D2. Chief hire and fire @@ -163,12 +163,16 @@ Hire and fire need authority the chief doesn't have. That is Q1. The two options `roles/chief-of-staff.json` withinRole. The broker checks them with `#consumeAuthority`, as it does `role.end`. This is a role file change (AGENTS.md invariant 7) and widens what a chief can do. It is what Case 1 asks for ("hire/fire authority for agents as needed; unless user forbids per agent"). + Sage's bounded form (sage-1355): the role file also carries an allowlist of definitions the chief may + hire, for example `hireable: ["security-reviewer"]`, checked before `noHire`. Hires stay uncredentialed. + Every hire and fire writes `changes.jsonl` with actor the chief's instance and run. Row 191's switch + refuses both (D6). The allowlist key is part of the role file change. - O2. No role file change. The chief raises a gated `role.hire` or `role.fire` decision, and the human resolves it. This follows the brief's "verbs, not new role authority" literally, but Case 1's authority then sits with the human. The brief says this row adds verbs, not authority. Case 1 says the chief hires and fires. Both can't hold, -so the choice is Sage's and Mos's. The rest of this design works under either option. Only the broker's +so the choice is Mos's (Sage sent it with an O1 recommendation, sage-1355). The rest of this design works under either option. Only the broker's authority check and the role file differ. ### D2.2 The veto @@ -232,7 +236,22 @@ Every human verb above calls `#human(s)` and then one hook, `#mayHuman(s, verb, lands, the hook passes for the business's one `human`, which is the owner. The verbs are listed once, in an exported `LIFECYCLE_HUMAN_VERBS` (`instance.launch`, `instance.end`, `instance.regenerate`, `veto.set`, and `instances.set` ops `add`, `change`, `delete`), so row 193 maps each verb to the human roles that may -use it. Row 193 replaces the hook body and nothing else. The tester gets none of the new write verbs (Q3). +use it. Row 193 replaces the hook body and nothing else. + +### D4.1 The tester (Sage, sage-1355) + +`instance.launch` and `instance.end` are also tester verbs. Every other new write verb refuses +`tester-refused`. The tester's cap is bound to one business, and only when that business sets `bus.tester` +to true (`broker.mjs:542-546`). That stays Jason's switch. Two checks run on each tester call, before any +effect: + +1. The request's business is the cap's business. Any other refuses `tester-refused`. +2. `bus.tester` is still exactly true in the broker's live copy. After D3 a running bus can see the switch + turned off, and the cap must stop working then, not at the next restart. Off refuses `tester-off`. + +The request and done events record actor `tester`. The tester gets no regenerate, delete, create or veto. +Its Q173 tests of the Agents section then cover launch and terminate on a scratch business, and the rest +through fixtures. ## D5. One stack instance @@ -290,11 +309,12 @@ Every test uses scratch roots under `TMPDIR` and the existing fixtures (`busines | T5 | V4: the new run starts only after the old exit, with a new run dir and the same workspace. The assistant refuses `regenerate-thread` | same | | T6 | V5: each refusal in the V5 table, in order. A clean delete leaves the evidence bytes unchanged, renames the workspace, adds `retired`, and a create of the same name refuses | business `instance-settings.test.mjs` | | T7 | V6: each op, the no-op refusal, and a `changes.jsonl` entry with actor `human` | business | -| T8 | Chief hire: added and listed, then launched by the same chief session (D3 item 5). `noHire`, credentialed, END_PROTECTED, existing and retired each refuse | bus `chief-of-staff.test.mjs` | +| T8 | Chief hire: added and listed, then launched by the same chief session (D3 item 5). `noHire`, credentialed, END_PROTECTED, existing and retired each refuse. Under O1, a definition outside `hireable` refuses `definition-not-hireable` | bus `chief-of-staff.test.mjs` | | T9 | Chief fire: runs end, delisted, still in `roles`. Kept, `launch.by` and last-listed refuse | same | | T10 | Keep: chief `role.end`, fire and hire aimed at a kept instance refuse `instance-kept`. The human's V3 on it works | same | | T11 | Two scratch stack instances with the same business id: V2, V3 and V5 in A leave B's root and config byte-identical | cli `lifecycle.test.mjs` | -| T12 | Agent, reader and tester sessions refuse every human verb before any effect. The D4 hook is called with the verb | bus `instances-verb.test.mjs` | +| T12 | Agent and reader sessions refuse every human verb before any effect. The tester refuses every one except launch and terminate. The D4 hook is called with the verb | bus `instances-verb.test.mjs` | +| T12a | Tester launch and terminate work on the cap's business with `bus.tester` true, record actor `tester`, refuse `tester-refused` for a second business on the same bus, and refuse `tester-off` after a live write turns `bus.tester` off | bus `instances-verb.test.mjs` | | T13 | `organization.set` with `launch`, `retired`, `keep` or `noHire` keys refuses | bus | | T14 | Live reload: after each write the broker answers from the new document. A definition change on a running instance refuses `instance-running` | bus | | T15 | Kill switch (with row 191's fixture): launch and regenerate refuse `processing-halted`, hire and fire refuse, terminate works | bus and cli | @@ -326,6 +346,9 @@ sha256 checked after each one. | M16 | the halted check is dropped from `instance.launch` | T15 | | M17 | the Console route skips the Origin check | T16 | | M18 | `veto.set` joins `TESTER_ORGANIZATION_VERBS` | T12 | +| M19 | the tester's business scope check is dropped | T12a | +| M20 | the tester's live `bus.tester` check is dropped | T12a | +| M21 | under O1, hire skips the role file's `hireable` list | T8 | ## Scope and boundaries @@ -335,13 +358,14 @@ sha256 checked after each one. section), the tests, and the package READMEs. `docs/TOOLS.md` text goes to Sage. - Role file change: `roles/chief-of-staff.json` under O1 only. Business file schema: D2.3. Both are named for review. -- Not in the row: credentialed hires and deletes (row 195), clear context for the assistant (T1 item 7), +- Not in the row: credentialed hires and deletes (the credentials row), clear context for the assistant (T1 item 7), human roles (row 193), and any live activation or Console start. ## Risks - R1. Case 1's working roles (coder, reviewer, pm, cto) all declare credentials (E11). Neither the human - verb nor the chief can create or delete them until row 195 binds credentials. Until then this row covers + verb nor the chief can create or delete them until the credentials row (T1 item 6, not yet filed) binds + credentials. Until then this row covers uncredentialed roles only. That is the largest gap against Case 1, and it isn't this row's to close. - R2. The human proof is path-bound and same-uid (P19 333). Any same-uid process that runs the tree's `human-cli.mjs` can launch and delete. Row 190b's separate uid and row 193 narrow it. This row adds no @@ -355,9 +379,11 @@ sha256 checked after each one. ## Questions -- Q1, for Sage and Mos: chief hire and fire authority, O1 (role file change) or O2 (gated decisions)? - D2.1. I recommend O1. +- Q1, for Mos (sent by Sage, sage-1355): chief hire and fire authority, O1 (role file change) or O2 (gated + decisions)? D2.1. Sage recommends O1 bounded: uncredentialed roles only, an allowlist of role kinds in + the role file, every hire and fire logged, and the kill switch covering both. Both options stay in this + design until Mos rules. - Q2, for Webby: keep blocks the chief's `role.end` on that instance, not only fire and replace (D2.2). Is the wider rule right? -- Q3, for Sage: the tester gets no lifecycle write verbs. The Q173 tester could then test the Agents section - only through fixtures. Should launch and terminate be tester verbs on the tester's own scratch business? +- Q3, settled by Sage (sage-1355): launch and terminate are tester verbs scoped to the tester's own + business, behind `bus.tester`. D4.1.