@nanocollective/roster 0.1.0-alpha.2 → 0.1.0-alpha.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (68) hide show
  1. package/dist/cli.js +848 -164
  2. package/docs/README.md +10 -5
  3. package/docs/agents.md +320 -9
  4. package/docs/commands.md +5 -6
  5. package/docs/concepts.md +27 -9
  6. package/docs/cost.md +3 -2
  7. package/docs/doctor-codes.md +13 -4
  8. package/docs/export.md +2 -1
  9. package/docs/extending.md +11 -2
  10. package/docs/getting-started.md +89 -84
  11. package/docs/images/brain.jpg +0 -0
  12. package/docs/images/org.jpg +0 -0
  13. package/docs/images/prompt.jpg +0 -0
  14. package/docs/images/setup-org.jpg +0 -0
  15. package/docs/images/setup-plan.jpg +0 -0
  16. package/docs/images/staff.jpg +0 -0
  17. package/docs/manual-steps.md +36 -13
  18. package/docs/memory.md +9 -6
  19. package/docs/org-yaml.md +37 -9
  20. package/docs/portal.md +197 -31
  21. package/docs/prompts.md +50 -11
  22. package/docs/security.md +19 -7
  23. package/docs/session-workflow.md +8 -10
  24. package/docs/staff-yaml.md +3 -5
  25. package/docs/troubleshooting.md +17 -14
  26. package/docs/writing-a-charter.md +18 -17
  27. package/package.json +1 -1
  28. package/templates/brain/.github/workflows/%%STAFF%%-daily.yaml +1 -0
  29. package/templates/brain/.github/workflows/%%STAFF%%-mention.yaml +10 -4
  30. package/templates/brain/staff.yaml +0 -1
  31. package/templates/ops/.github/workflows/session.yaml +9 -26
  32. package/templates/ops/agents.mjs +121 -6
  33. package/templates/ops/compose.mjs +61 -4
  34. package/templates/ops/org/operating.md +0 -6
  35. package/templates/ops/prompts/_identity.md +8 -1
  36. package/templates/ops/prompts/mention.md +16 -2
  37. package/templates/portal/css/base.css +122 -8
  38. package/templates/portal/css/brain.css +8 -1
  39. package/templates/portal/css/diff.css +6 -2
  40. package/templates/portal/css/health.css +21 -2
  41. package/templates/portal/css/inbox.css +93 -5
  42. package/templates/portal/css/layout.css +26 -4
  43. package/templates/portal/css/markdown.css +23 -3
  44. package/templates/portal/css/setup.css +11 -6
  45. package/templates/portal/index.html +7 -1
  46. package/templates/portal/js/api.js +33 -0
  47. package/templates/portal/js/app.js +33 -7
  48. package/templates/portal/js/dialog.js +47 -4
  49. package/templates/portal/js/dom.js +25 -0
  50. package/templates/portal/js/icons.js +8 -1
  51. package/templates/portal/js/lightbox.js +273 -0
  52. package/templates/portal/js/md.js +23 -6
  53. package/templates/portal/js/mention.js +264 -0
  54. package/templates/portal/js/refresh.js +136 -6
  55. package/templates/portal/js/state.js +47 -5
  56. package/templates/portal/js/views/checklist.js +20 -7
  57. package/templates/portal/js/views/docs.js +94 -4
  58. package/templates/portal/js/views/files.js +58 -14
  59. package/templates/portal/js/views/health.js +163 -35
  60. package/templates/portal/js/views/inbox.js +882 -96
  61. package/templates/portal/js/views/memory.js +16 -1
  62. package/templates/portal/js/views/org.js +142 -62
  63. package/templates/portal/js/views/prompt.js +50 -63
  64. package/templates/portal/js/views/setup.js +37 -13
  65. package/templates/portal/js/views/staff.js +62 -2
  66. package/templates/portal/js/yaml.js +134 -0
  67. package/templates/brain/.github/workflows/%%STAFF%%-pr-mention.yaml +0 -50
  68. package/templates/ops/prompts/pr-mention.md +0 -57
package/docs/extending.md CHANGED
@@ -12,6 +12,11 @@ Four seams, in the order you are likely to reach for them.
12
12
 
13
13
  Edit `org/*.md` in the ops repo. It reaches every staff member on their next run.
14
14
 
15
+ The [Org screen](portal.md#org) is exactly this seam: every one of these files listed off disk
16
+ with a line saying what it is for, an Edit button, and a save that commits and pushes. The list
17
+ comes off disk rather than being written into the page, so a file you add yourself is editable
18
+ there too.
19
+
15
20
  | File | For |
16
21
  |---|---|
17
22
  | `business.md` | what the business is. The one everything else is downstream of. |
@@ -34,7 +39,6 @@ _identity.md who you are posting as, and where
34
39
  _paths.md where things are in the runner checkout
35
40
  daily.md the scheduled session
36
41
  mention.md a focused task from a comment
37
- pr-mention.md a review comment forwarded from the product repo
38
42
  ```
39
43
 
40
44
  The syntax is small on purpose: `{{ path.to.value }}`, `{{> partial.md }}`,
@@ -54,7 +58,12 @@ A staff member can override a fragment for themselves. `{{>? staff:prompts/work.
54
58
  `daily.md` renders `prompts/work.md` from their own brain repo if it exists, and nothing if it
55
59
  does not. That is how one role gets a different working ritual without changing anybody else's.
56
60
 
57
- See what you actually built:
61
+ See what you actually built on the [Prompt screen](portal.md#prompt), which walks the includes
62
+ rather than listing them from memory, so a fragment you just added shows up on it, marked with
63
+ the repo it came from. An optional fragment a role does not have is shown as absent rather than
64
+ hidden. The layers are editable there too, subject to the writable list on that page.
65
+
66
+ From a terminal:
58
67
 
59
68
  ```bash
60
69
  roster prompt cto --kind daily
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  title: "Getting started"
3
- description: "Stand up an org and a first staff member, in seven steps."
3
+ description: "Stand up an org and a first staff member, from the portal."
4
4
  sidebar_order: 1
5
5
  ---
6
6
 
@@ -10,125 +10,130 @@ sidebar_order: 1
10
10
  npx @nanocollective/roster
11
11
  ```
12
12
 
13
- Run that in an empty directory. It opens a portal in your browser and walks the whole setup:
14
- it checks `gh`, lists the organisations you can see, and asks which one.
13
+ Run that in an empty directory. There is nothing else to install and nothing to configure
14
+ first: the page that opens is the setup screen, and it is the whole of setup.
15
15
 
16
- **Two answers, and it works out which you need.** An organisation that does not run roster yet
17
- gets one stood up. One that already does gets checked out here instead, ops repo and every
18
- staff repo side by side, which is the shape the CI runner uses. That is how a second person on
19
- a team joins an org somebody else set up.
16
+ You need two things before you start. `gh` [authenticated](https://cli.github.com), and a
17
+ credential for whichever [coding agent](agents.md) you want to run. A GitHub organisation too,
18
+ if you do not already have one: GitHub has no API for creating one, so that part happens on
19
+ github.com.
20
20
 
21
- From there the page carries the rest: the Actions setting that has to be clicked, the repos
22
- your staff work in, hiring, each GitHub App, and a prompt you paste into your own AI to write
23
- `org/business.md` and the charters.
21
+ Everything below is also a command, and the commands are in [the CLI
22
+ reference](commands.md). They do the same work on the same files. This page is the portal
23
+ because that is the shorter road, not because the terminal is second class.
24
24
 
25
- You need `gh` authenticated, and a credential for whichever [coding agent](agents.md) you want
26
- to run.
25
+ ## 1. Say which organisation
27
26
 
28
- ---
27
+ ![The setup screen, asking which organisation and who runs it](images/setup-org.jpg)
29
28
 
30
- The rest of this page is the same setup from a terminal. Everything the portal does, these do;
31
- nothing writes without `--apply`.
29
+ **It works out which of two things this is, and you do not have to know.** An organisation
30
+ that does not run roster yet gets one stood up. One that already does gets *checked out* here
31
+ instead, ops repo and every staff repo side by side, which is the shape the CI runner uses.
32
+ That second case is how somebody joins an org a colleague set up, and offering both is how an
33
+ org ends up with two `roster-ops` repos.
32
34
 
33
- ## 1. Stand up the org
35
+ The rest of the card is three answers: what the business is called, which GitHub login the
36
+ agents answer to, and which coding agent runs a session. The agent is the one that is awkward
37
+ to change later, because it decides which credential the repos need.
34
38
 
35
- ```bash
36
- roster init --org acme --name "Acme Robotics"
37
- ```
39
+ ## 2. Read the plan before anything exists
38
40
 
39
- That prints the plan. Read it, then:
41
+ ![The plan: sixteen files and one private repo, listed before anything is written](images/setup-plan.jpg)
40
42
 
41
- ```bash
42
- roster init --org acme --name "Acme Robotics" --apply
43
- ```
43
+ Nothing has been created yet. **Show me the plan** lists every file and every repo it would
44
+ make, and *Create it* is a separate button. This is the pattern everywhere in roster: the plan
45
+ first, then the apply, and the same `initFiles` behind both the browser and the terminal so
46
+ they cannot disagree about what a new tenant contains.
44
47
 
45
- You now have `acme/roster-ops`: the org layer, the runner machinery, and a recorded merge base
46
- so later upgrades are merges rather than copies.
48
+ After it applies you have `acme/roster-ops`: the org layer, the runner machinery, and a
49
+ recorded merge base so later [upgrades](upgrading.md) are merges rather than copies.
47
50
 
48
- Then do the one thing that cannot wait: **Settings -> Actions -> General on `roster-ops`, set
49
- access to "accessible from repositories in the organisation".** Skip it and every workflow
50
- later fails with "workflow not found", which reads like a typo and is not one.
51
+ ## 3. The Actions setting
51
52
 
52
- ## 2. Say what the business is
53
+ The page asks for this next and deep-links to the exact settings page, because it is the one
54
+ step whose failure is unrecognisable.
53
55
 
54
- Open `roster-ops/org/business.md`. It ships as questions. Answer them, or:
56
+ **Settings → Actions → General on `roster-ops`, set access to "accessible from repositories in
57
+ the organisation".** Skip it and every workflow later fails with "workflow not found", which
58
+ reads like a typo and is not one.
55
59
 
56
- ```bash
57
- roster brief discover # paste into whatever agent you use
58
- ```
60
+ It is on [manual steps](manual-steps.md) with the others roster cannot do for you, and
61
+ [Health](#7-health-then-one-run-by-hand) keeps asking until it is done.
59
62
 
60
- Or, in Claude Code, `cd roster-ops && claude` then `/discover`. Both print the same brief:
61
- `roster init` generates the slash command from it.
63
+ ## 4. Say what the business is
62
64
 
63
- Do this before hiring anyone. It is composed into the top of every prompt, and an agent that
64
- cannot answer these questions writes plausible work about a business that does not exist.
65
+ `org/business.md` ships as questions, and it is composed into the top of every prompt. An agent
66
+ that cannot answer them writes plausible work about a business that does not exist, so this
67
+ comes before hiring anybody.
65
68
 
66
- ## 3. Hire someone
69
+ roster holds no model credential and cannot write it for you. What the portal does instead is
70
+ both halves of the round trip: **Copy the prompt** puts a self-contained brief on your
71
+ clipboard, and **paste the answer back** turns the reply into a file, with a diff and a button
72
+ rather than a silent save. See [the portal](portal.md#copy-a-prompt-paste-the-answer-back).
67
73
 
68
- ```bash
69
- roster hire cto --name "Chief Technology Officer" --dir technology
70
- ```
71
-
72
- Read the plan. It lists every file, every label, the peer wiring in both directions, and the
73
- things it cannot do for you. Then `--apply`.
74
+ ## 5. Hire someone
74
75
 
75
- For the first hire in a new org there is nobody to copy an identity from, so name them:
76
+ ![The Staff screen, with a card per staff member and Hire someone underneath](images/staff.jpg)
76
77
 
77
- ```bash
78
- roster hire cto --name "Chief Technology Officer" --dir technology \
79
- --app acme-cto --public-app acme-robot --apply
80
- ```
78
+ **Staff → Hire someone.** Only the handle is required; everything else is copied from whoever
79
+ is already here. You get the plan first: every file, every label, the schedule it chose and
80
+ why, the peer wiring in both directions, and the steps it cannot do for you.
81
81
 
82
- Later hires infer both from whoever is already there.
82
+ For the first hire in a new org there is nobody to copy an identity from, so the App names are
83
+ asked for rather than guessed at. Later hires infer both.
83
84
 
84
- ## 4. Give them an identity
85
+ ## 6. Give them an identity, and install it
85
86
 
86
- ```bash
87
- roster app cto
88
- ```
87
+ **GitHub App**, on the same card. There is no API that creates a GitHub App, so this runs the
88
+ manifest flow: a manifest is posted to a settings page, you confirm, and GitHub hands back a
89
+ one-time code. The private key is held in memory and written straight to a repository secret
90
+ without ever touching disk.
89
91
 
90
- A browser opens, GitHub asks you to confirm, and the App's id and private key go straight into
91
- the repository's secrets. The key never touches disk.
92
+ **What it cannot do is install the App.** That is a grant of access to specific repositories
93
+ and GitHub asks a human to choose them, which is correct. Grant it every tracker the staff
94
+ member writes to, not only their own. This is the step that most often looks done and is not.
92
95
 
93
- Then **install it**, using the URL that command prints, granting it every tracker the staff
94
- member writes to. This is the step that most often looks done and is not. See
95
- [manual steps](manual-steps.md#3-install-the-app-and-grant-it-the-right-repositories).
96
+ Then **Write the charter**, which is the same copy-a-prompt loop as `business.md`, aimed at
97
+ `CHARTER.md`. `hire` deliberately does not generate one: a generated charter produces exactly
98
+ the generic agent this whole arrangement exists to avoid. It is the file that decides
99
+ everything else, so it is worth the time. [Writing a charter](writing-a-charter.md).
96
100
 
97
- ## 5. Write the charter
101
+ ## 7. Health, then one run by hand
98
102
 
99
- ```bash
100
- roster brief charter cto # paste into whatever agent you use
101
- ```
103
+ **Health** is `roster doctor` on the page, every finding carrying the sentence that fixes it,
104
+ split into what an agent can do and what only a person can. Work through it until the ids are
105
+ gone.
102
106
 
103
- Or, in Claude Code, `cd technology && claude` then `/charter`. Same brief either way.
107
+ Then trigger the daily workflow once from the Actions tab and read the log.
104
108
 
105
- This is the file that decides everything else. [Writing a charter](writing-a-charter.md).
109
+ **A workflow that has never run has proved nothing.** Not that the App is installed, not that
110
+ the grant took, not that the secrets are right. `doctor` says `unproven` rather than `fine` for
111
+ exactly this reason.
106
112
 
107
- ## 6. Check, then run one by hand
113
+ ## 8. Now look at what you built
108
114
 
109
- ```bash
110
- roster doctor cto
111
- ```
115
+ ![A staff member's brain: memory sections, the facts in them, and the files](images/brain.jpg)
112
116
 
113
- Fix what it says. Then trigger the daily workflow once from the Actions tab and read the log.
117
+ **Brain** is that staff member's memory and files together, because they were always the same
118
+ thing. **Prompt** is the text they are actually sent, composed by your own `compose.mjs`, with
119
+ every layer it was made of and which repo each came from.
114
120
 
115
- **A workflow that has never run has proved nothing.** Not that the App is installed, not that
116
- the grant took, not that the secrets are right. `doctor` says `unproven` rather than `fine` for
117
- exactly this reason.
121
+ ![The Prompt screen: the composed text, and the layers behind it](images/prompt.jpg)
118
122
 
119
- ## 7. Look at it
123
+ Those two answer the question people ask hardest in the first week, which is *why did it do
124
+ that*. The answer is always in one of those files.
120
125
 
121
- ```bash
122
- roster portal
123
- ```
126
+ ![The Org screen, with org.yaml and every layer every staff member inherits](images/org.jpg)
124
127
 
125
- Everything open across the org, every staff member's memory, what changed since yesterday, and
126
- whether anything is unhealthy. Reads the repositories on disk, so keep them checked out
127
- alongside each other.
128
+ **Org** is the layer everybody inherits. Change `org/voice.md` once and it reaches every staff
129
+ member on their next run, without regenerating anything.
128
130
 
129
131
  ## Where things go from here
130
132
 
131
- - A second staff member: `roster hire`, then `roster app`. Peer wiring happens both ways.
132
- - A change to how everyone writes: edit `org/voice.md` once. It reaches everybody on their next
133
- run.
134
- - A framework update: `roster upgrade`. See [upgrading](upgrading.md).
133
+ - **A second staff member**: Staff Hire someone, then the App. Peer wiring happens both ways.
134
+ - **Answering your agents**: [the Inbox](portal.md#inbox) is everything open across the org, and
135
+ the reply goes out as you. Work they finished sits in [Pending work](portal.md#pending-work);
136
+ asking for a change to it is [one button](portal.md#asking-for-a-change).
137
+ - **A framework update**: `roster upgrade`, or the same from the portal. See
138
+ [upgrading](upgrading.md).
139
+ - **The whole portal**, screen by screen: [the portal](portal.md).
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
@@ -14,7 +14,9 @@ that deep-links item 1, runs items 2 and 3 for you as far as GitHub allows, and
14
14
  for items 5 and 6. This page is still the *why*: it is what to read when one of them bites, and
15
15
  what to check when the page says something is not done.
16
16
 
17
- `roster doctor` checks most of these. Run it after each one.
17
+ The portal's **Health** screen checks most of these, per staff member and for the org, with
18
+ every finding carrying the sentence that fixes it. `roster doctor` prints the same from a
19
+ terminal. Look after each step.
18
20
 
19
21
  ---
20
22
 
@@ -31,7 +33,7 @@ it and tells you, but setting it is one click and it is yours.
31
33
  a path, or a missing file, or a bad branch reference. You will check all three. It is none of
32
34
  them, it is this.
33
35
 
34
- **Check:** `roster doctor` reports `roster-ops is callable from the whole org`.
36
+ **Check:** Health, or `roster doctor`, reports `roster-ops is callable from the whole org`.
35
37
 
36
38
  ---
37
39
 
@@ -79,7 +81,8 @@ chain (App created, installed, granted, secrets right, workflow reachable) is a
79
81
  finished. `roster doctor` reads a window of recent runs for exactly this reason, and reports a
80
82
  workflow that has never run as **unproven** rather than as fine.
81
83
 
82
- **Check:** `roster doctor <handle>`, then trigger one run and look again.
84
+ **Check:** that staff member's Health screen, or `roster doctor <handle>`. Then trigger one run
85
+ and look again.
83
86
 
84
87
  ---
85
88
 
@@ -95,17 +98,20 @@ credential: `CLAUDE_CODE_OAUTH_TOKEN`, `CODEX_API_KEY`, and so on. See
95
98
  That check exists so it fails there rather than forty lines later inside the agent, after the
96
99
  checkouts have already happened.
97
100
 
98
- **Check:** `roster doctor` lists the secrets each caller references and whether they exist.
101
+ **Check:** Health, or `roster doctor`, lists the secrets each caller references and whether
102
+ they exist.
99
103
 
100
104
  ---
101
105
 
102
106
  ## 5. Write `org/business.md`
103
107
 
104
- **Do:** answer the questions `roster init` leaves in it. The setup screen has a **Copy the
105
- prompt** button that carries every file it refers to, and a box to paste the answer back into;
106
- `roster brief discover` prints the same brief for a terminal.
108
+ **Do:** the setup screen does both halves of this. **Copy the prompt** puts a brief on your
109
+ clipboard with every file it refers to inlined, so a chat window with no filesystem is as useful
110
+ as an agent standing in the repo; the box beneath it takes the reply, shows you a diff, and
111
+ saves only when you press the button. `roster brief discover` prints the same brief for a
112
+ terminal, and you can always just answer the questions in the file by hand.
107
113
 
108
- `roster doctor` reports `business.stub` while it is still the questions.
114
+ Health reports `business.stub` while it is still the questions.
109
115
 
110
116
  **Why not automated:** an agent that does not know the business writes work that is plausible
111
117
  and generic. That is worse than no work, because it takes longer to notice. This file is
@@ -118,9 +124,11 @@ a business that does not exist.
118
124
 
119
125
  ## 6. Write each staff member's `CHARTER.md`
120
126
 
121
- **Do:** **Write the charter** on that staff member's card in the portal, or
122
- `roster brief charter <handle>` and paste it into your agent. Or write it by hand;
123
- [writing a charter](writing-a-charter.md) has the shape.
127
+ **Do:** **Write the charter** on that staff member's card, which is the same copy-a-prompt,
128
+ paste-the-answer-back round trip as item 5, aimed at `CHARTER.md`. The brief it copies carries
129
+ the org layer, `business.md` and **the peers' charters**, because without those the model writes
130
+ a second copy of whoever it was shown. `roster brief charter <handle>` prints the same brief, and
131
+ [writing a charter](writing-a-charter.md) has the shape if you would rather write it yourself.
124
132
 
125
133
  **Why not automated:** same reason, one level down. The charter is what makes a staff member
126
134
  different from the others.
@@ -133,7 +141,11 @@ whatever the shared layer implies.
133
141
 
134
142
  ## 7. Commit and push what roster wrote into other repos
135
143
 
136
- **Do:** `roster hire` and `roster upgrade` write into brain repos on disk. Review, commit, push.
144
+ **Do:** hiring writes a whole brain repo and pushes it, so this is mostly about `roster
145
+ upgrade`, which writes into repos on disk and leaves them for you. Review, commit, push.
146
+
147
+ Hiring from the Staff screen still edits the *other* staff members' manifests on disk to wire the
148
+ peers both ways, and those are yours to commit.
137
149
 
138
150
  **Why not automated:** roster does not commit on your behalf into repositories it did not
139
151
  create in that command. And **App tokens cannot push a change under `.github/workflows/` in any
@@ -149,7 +161,18 @@ as still pending next time, which is the intended behaviour.
149
161
 
150
162
  For a new organisation:
151
163
 
152
- In the portal, this order is the screen you are looking at. From a terminal:
164
+ In the portal it is the screen you are looking at, in this order:
165
+
166
+ ```
167
+ the setup screen 1 is deep-linked from it, and 5 is on it
168
+ Staff -> Hire someone then 7
169
+ GitHub App, on the new staff card 2, then 3
170
+ Write the charter, on the same card 6
171
+ 4 is yours: a secret on the brain repo
172
+ Health until the ids are gone
173
+ ```
174
+
175
+ From a terminal:
153
176
 
154
177
  ```
155
178
  roster init --org <org> --apply # 1 applies here
package/docs/memory.md CHANGED
@@ -59,13 +59,16 @@ will disagree with itself within a month.
59
59
 
60
60
  ## Checking it
61
61
 
62
+ **Health**, per staff member, has a **Memory problems** section. Each finding has a button that
63
+ opens an issue in that staff member's own repository asking them to fix it, which is usually the
64
+ right move: they wrote it, and an issue on their tracker is a thing that wakes them.
65
+
66
+ It catches: a missing `So:`, a duplicate slug, a note nothing links to, a link to a note that
67
+ does not exist, an over-long line, a `[measured]` fact with no `n`, and an "updated:" chain.
68
+
69
+ The same checks, for a terminal or for CI:
70
+
62
71
  ```bash
63
72
  roster lint # everyone
64
73
  roster lint cto # one staff member
65
74
  ```
66
-
67
- Lint catches: a missing `So:`, a duplicate slug, a note nothing links to, a link to a note that
68
- does not exist, an over-long line, a `[measured]` fact with no `n`, and an "updated:" chain.
69
-
70
- The portal's **Health** screen shows the same findings and will open an issue in the staff
71
- member's own repository asking them to fix it, which is usually the right move: they wrote it.
package/docs/org-yaml.md CHANGED
@@ -31,11 +31,12 @@ experiment_private: true
31
31
 
32
32
  agent:
33
33
  id: claude-code-action
34
+ permissions: full
34
35
 
35
36
  defaults:
36
37
  model: claude-opus-5
37
- timeout_minutes: 60
38
- allowed_tools: [Bash, Read, Write, Edit, Glob, Grep, WebFetch, WebSearch]
38
+ timeout_minutes: 90
39
+ mention_timeout_minutes: 90
39
40
 
40
41
  staff:
41
42
  - { handle: cto, dir: technology, name: Chief Technology Officer, schedule: "0 7 * * 1-5" }
@@ -58,17 +59,37 @@ repos:
58
59
  | `ops_dir` | no | Directory name of the ops repo in the runner checkout. Defaults to `roster-ops`. |
59
60
  | `experiment_private` | no | Whether the fact that this org is agent-run is itself private. Read by the guardrails fragment. |
60
61
 
61
- ### `human`
62
+ ### `human` and `humans`
62
63
 
63
- Who the staff answer to. There is exactly one.
64
+ Who the staff answer to. One person is a `human` map; more than one is a `humans` list:
65
+
66
+ ```yaml
67
+ humans:
68
+ - { name: Will, github: will-lamerton, marker: will, role: founder }
69
+ - { name: Sam, github: sam-x, marker: sam, role: operations }
70
+ ```
64
71
 
65
72
  | Field | Required | Means |
66
73
  |---|---|---|
67
- | `github` | yes | Login. **The mention callers gate on this**, so without it nothing can wake an agent. |
74
+ | `github` | yes | Login. **The mention callers gate on these**, so without one nothing can wake an agent. |
68
75
  | `name` | no | What to call them in prose. Defaults to the login. |
69
- | `marker` | no | Provenance tag on a fact they ruled on, as in `[will]`. Also used as a label. |
76
+ | `marker` | no | Provenance tag on a fact they ruled on, as in `[will]`. Also used as a label. Defaults to the first part of the name, lowercased. |
70
77
  | `role` | no | Prose only. |
71
78
 
79
+ Both keys are read, and the singular is not deprecated: an org with one human should keep
80
+ writing `human`. When both are present, anyone in `human` who is not already in the list is
81
+ appended rather than dropped.
82
+
83
+ **The first entry is the primary.** Prompts are prose addressed to somebody ("*Will* is not
84
+ here"), and a list of two cannot go in that sentence, so the first one goes there, their
85
+ `marker` is what `%%HUMAN_MARKER%%` renders, and the rest are named by
86
+ `{{humans_extra}}` in the identity fragment. Everything that *gates* on identity reads all of
87
+ them: the mention caller's `if:` is `contains(fromJSON('["will-lamerton","sam-x"]'), …)`.
88
+
89
+ Adding a human changes every generated caller workflow, so it takes a `roster upgrade` to reach
90
+ the brain repos. Until that lands, the new person can open issues and read everything, and
91
+ mentioning a staff member does nothing.
92
+
72
93
  ### `agent`
73
94
 
74
95
  Which coding agent runs a session. Either a string, or a map. See
@@ -81,10 +102,16 @@ Which coding agent runs a session. Either a string, or a map. See
81
102
  | `run` | if `id` is unknown | Shell command that runs it, reading `$AGENT_PROMPT_FILE`. |
82
103
  | `token_env` | if `id` is unknown | Environment variable its credential goes in. |
83
104
  | `model` | no | Default model for this agent. A staff member's own `model` wins. |
105
+ | `permissions` | no | `full`, `workspace` or `read-only`. Defaults to `full`. One word, translated into each agent's own vocabulary: a tool list for Claude, a sandbox and an approval policy for Codex, a development mode for nanocoder. A staff member can set their own, and be trusted less than the org. |
106
+ | `options` | no | A map, in that agent's own vocabulary, spelled onto its command line untranslated. The escape hatch for anything roster does not model. |
84
107
 
85
108
  Any field given overrides the preset's, so a preset that is right except for one flag needs
86
109
  one line.
87
110
 
111
+ An agent that needs a config file of its own gets one written when `roster init` chooses it,
112
+ with the parts only a person can supply left as `FILL IN` blanks. `roster doctor` fails while
113
+ any of them are still there.
114
+
88
115
  ### `defaults`
89
116
 
90
117
  Fallbacks for staff members who do not set their own.
@@ -92,8 +119,9 @@ Fallbacks for staff members who do not set their own.
92
119
  | Field | Means |
93
120
  |---|---|
94
121
  | `model` | Model id passed to the agent. |
95
- | `timeout_minutes` | Ceiling on a daily session. |
96
- | `allowed_tools` | Tool permission string. Meaningful to agents that take one, ignored by those that do not. |
122
+ | `timeout_minutes` | Ceiling on a daily session. `90` if unset. |
123
+ | `mention_timeout_minutes` | Ceiling on a mention run. Falls back to `timeout_minutes`, then `90`. |
124
+ | `allowed_tools` | Claude's own spelling of a permission level, kept because it predates `agent.permissions` and still wins for the agents that take a tool list. Nothing translates it for the others: a list written for one agent is not a permission level for another. Prefer [`agent.permissions`](agents.md#permissions), which every agent understands. |
97
125
 
98
126
  ### `staff`
99
127
 
@@ -127,7 +155,7 @@ Every repository the org owns, and what it is for.
127
155
 
128
156
  | Reader | Uses |
129
157
  |---|---|
130
- | `compose.mjs` | `org`, `name`, `human`, `ops_dir`, `staff` |
158
+ | `compose.mjs` | `org`, `name`, `human`, `humans`, `ops_dir`, `staff` |
131
159
  | `runner-plan.mjs` | `org`, `staff`, and each manifest's `works_in` and `peers` |
132
160
  | `agents.mjs` | `agent`, `staff` |
133
161
  | `roster hire` | all of it, plus every existing manifest |