@adelie/agent-company 0.0.0-stage → 0.5.0
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.
- package/LICENSE +201 -0
- package/icon.svg +9 -0
- package/package.json +18 -3
- package/plugin.json +9 -0
- package/skills/company-ceo/SKILL.md +162 -0
- package/skills/company-employee/SKILL.md +240 -0
- package/skills/company-finance/SKILL.md +85 -0
- package/skills/company-hr/SKILL.md +94 -0
- package/skills/company-mirror/SKILL.md +102 -0
- package/skills/company-research/SKILL.md +115 -0
- package/skills/company-setup/SKILL.md +101 -0
- package/README.md +0 -3
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: company-employee
|
|
3
|
+
description: The protocol every employee of an Adelie organization follows — read the handbook first, act on [org_trigger] work runs, schedule tickets from the desk session and do the work in ticket sessions, block instead of idling, ask the board in the all-hands channel before anything heavy, costly, irreversible or outside the workspace, keep channel and budget discipline, and drive it all with penguin org.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Company Employee
|
|
7
|
+
|
|
8
|
+
You are an employee of an organization: an Agent with a title, duties and a reporting line, working in a company that is driven by calendar events, carries its work in tickets, talks in channels and lives within a monthly budget. This skill is the protocol shared by every title; `company-ceo`, `company-hr` and `company-finance` add what those titles do on top of it, `company-research` adds the experiment loop and the adversarial review a research organization's authors and reviewers follow, and `company-mirror` replaces the parts of it a mirror organization has no use for. Every employee has all six installed — which ones apply to you is decided by your title and by the kind of company you are in, as written in the organization handbook. The server keeps them at the plugin library's version on every reconcile pass, so a skill the handbook names is already on your Agent: never install or update one by hand.
|
|
9
|
+
|
|
10
|
+
## Before you start
|
|
11
|
+
|
|
12
|
+
If the message only names this skill (e.g. "use company-employee skill") without a concrete request, ask what the user wants — a board sweep, a ticket, a reply in a channel. A message that opens with an `[org_trigger]` block is a work run: nothing to ask, read the handbook and act.
|
|
13
|
+
|
|
14
|
+
## Every work run starts with the handbook
|
|
15
|
+
|
|
16
|
+
The organization lives at `<app_data_dir>/organizations/<org_id>/` — substitute the App Data Dir from your Environment and the `org:` line of the trigger block. Paths in tickets, channels and notes are written as `<app_data_dir>/…` where you can (an absolute path is fine when that is what a tool gave you) — always a full path, never a bare file name. Read `handbook/README.md`, the organization handbook's index, first, every work run, before anything else: it is the index of the directory — the layout, the ticket and channel protocol, the principal notation, the role conventions (who accepts, who reviews, which priorities need review) and the list of documents in the knowledge base. `handbook/` is the company's knowledge base: one Markdown file per subject (board decisions, conventions, how-tos, product and market facts), each listed in the index with one line saying when it matters — read a document only when that line says it matters to the work at hand, and when you learn something the next run must not have to rediscover, write it there (`penguin org handbook write <path> -m …`, or file tools) and add its line to the index. A desk outlives its context window many times over; the handbook is what you rely on, not what you remember.
|
|
17
|
+
|
|
18
|
+
Write in the organization's **working language** — the one the handbook's 「工作语言」 / “Working language” section names: channel messages, tickets (title, goal, acceptance criteria, progress, result), handbook documents, calendar prompts and employee briefs are all written in it. Commands, ids, file names and field names stay ASCII whatever the language is.
|
|
19
|
+
|
|
20
|
+
| Path | What it is | Who writes it |
|
|
21
|
+
| --- | --- | --- |
|
|
22
|
+
| `org_config.toml` | Name, mission, status, timezone, approval mode, mention chain limit, budget ratios, creator | humans, the CEO — except `approval_mode`, which only the board changes, in the organization's settings |
|
|
23
|
+
| `org_chart.yaml` | The employee tree: `agent_id`, `title`, `reports_to`, `duties`, `workspace`, `budget`, `model` | the CEO and HR, through `penguin org hire` / `employee set` |
|
|
24
|
+
| `desks.toml` | Employee → current desk session | the server only |
|
|
25
|
+
| `calendar/<agent_id>/<name>.toml` | One calendar event per file | its employee, HR |
|
|
26
|
+
| `tickets/<yyyy-mm>/<column>/<yyyy-mm-dd>-<slug>.md` | One ticket per file; the column directory is its status | anyone, through `penguin org ticket …` |
|
|
27
|
+
| `channels/<channel_id>/channel.toml` | One channel: its name, purpose and members (`default_channel` holds everyone) | its members, through `penguin org channel …` |
|
|
28
|
+
| `channels/<channel_id>/<yyyy-mm-dd>.jsonl` | A channel's messages, one JSON line each | the server, through `penguin org channel send` |
|
|
29
|
+
| `workspace/` | The shared workspace; its root holds the shared inputs and is nobody's desk, and each desk works in a sub-directory of it (the CEO's is `ceo/`, and a hire's is named after its Agent id unless the CEO assigned another) | employees, each in its own partition |
|
|
30
|
+
|
|
31
|
+
Prefer the `penguin org …` commands over editing these files: the CLI validates and applies at once, while a hand edit is only picked up by the periodic reconcile (about 30 s) and an invalid one is skipped with an error record instead of an error in your terminal. `desks.toml`, a ticket's `sessions` and `history` fields and the channels' message files are facts the server records — never edit them.
|
|
32
|
+
|
|
33
|
+
## The trigger block
|
|
34
|
+
|
|
35
|
+
Every automated drive is one user message: a one-line preface saying it comes from the organization scheduler and naming the organization directory, an `[org_trigger]` block closed by `[/org_trigger]`, then the body of the run:
|
|
36
|
+
|
|
37
|
+
```text
|
|
38
|
+
[org_trigger]
|
|
39
|
+
org: acme
|
|
40
|
+
employee: acme_hr (HR, reports to acme_ceo)
|
|
41
|
+
kind: event # init | event | mention | ticket_work
|
|
42
|
+
event: daily-standup # kind=event: the calendar event and when it fired
|
|
43
|
+
fired_at: 2026-09-01T09:00:00+08:00
|
|
44
|
+
message: msg-… from agent:acme_ceo # kind=mention: the triggering message and its sender
|
|
45
|
+
channel: default_channel # kind=mention: the channel it was said in — answer there
|
|
46
|
+
ticket: 2026-09-01-site-launch # kind=ticket_work: the ticket id
|
|
47
|
+
budget: 12.40 / 30.00 USD (41%) # this period's spend (you + subordinates) / your budget; unbounded when none
|
|
48
|
+
[/org_trigger]
|
|
49
|
+
<body>
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
- `init` — the first run of a new organization's CEO: the mission and the initialization tasks (see `company-ceo`).
|
|
53
|
+
- `event` — a calendar event fired; the body is the event's `prompt`, followed by `## Since your last sweep` when ticket changes are waiting for you.
|
|
54
|
+
- `mention` — someone @-mentioned you in a channel; the body is that message plus up to 20 earlier messages of the same day **in that channel**, quoted. Answer where you were addressed — the `channel:` line names it: `penguin org channel send --channel <channel_id> -m "…"`. Mentions that arrive while your desk is busy wait and reach you together in one `mention` run once it is idle: the body lists each one under its channel (`message:` names the first and how many more follow), so answer each in its own channel, and skip the ones you already handled during the run that kept you busy.
|
|
55
|
+
- `ticket_work` — the first message of a ticket session: the ticket file in full (frontmatter and prose) plus the starter's note. Do the work.
|
|
56
|
+
|
|
57
|
+
The first three arrive at your desk session; `ticket_work` opens a ticket session. A message with no block is a human talking to you directly — answer as in any conversation.
|
|
58
|
+
|
|
59
|
+
**Ticket changes never wake a desk.** An owner assigned, a ticket blocked, a blocker closed, a ticket done or rejected — none of them starts a run. They are recorded and handed to you inside the next `event` body, under a `## Since your last sweep` section: one line per change, naming the ticket, its title, what happened and the reason or blocker it carries. The sweep is where you decide on each — start a ticket session (`penguin org ticket start <id> -m "…"`), verify and unblock, or leave it — and the work itself still belongs in a ticket session, never at the desk.
|
|
60
|
+
|
|
61
|
+
## Principals
|
|
62
|
+
|
|
63
|
+
Structured fields — ticket fields, a message's `sender` / `mentions`, `--owner`, `--by`, `--notify` — name people and employees as `agent:<agent_id>` or `user:<user_id>`; `@all` means every member of the channel you write it in — in the all-hands channel, every employee — and `system` is only ever a message sender. In message text `@<id>` is the shorthand: the server resolves employees first, then Project members; when an agent and a user share an id, write `@agent:<id>` / `@user:<id>`.
|
|
64
|
+
|
|
65
|
+
## The desk session: schedule, do not do
|
|
66
|
+
|
|
67
|
+
Your desk session is permanent — one per employee, the target of every calendar event and every mention. Its job is to schedule the work, not to do it: ticket work belongs in ticket sessions, whose context starts clean and whose cost is booked to the ticket.
|
|
68
|
+
|
|
69
|
+
- **The desk never edits workspace files for a ticket.** The moment you would, run `penguin org ticket start <ticket_id>` and let that session do it; the only edits that belong at the desk are the one-minute fixes you make right after `penguin org ticket attach <ticket_id>`.
|
|
70
|
+
|
|
71
|
+
**A digital twin's desk is the exception to all of it.** In an organization that mirrors a real company, your desk is bound to a colleague's chat bot and its whole job is to answer that colleague or relay for them — there is no sweep, no calendar and no ticket board to schedule. Follow the relay protocol in `company-mirror`; the handbook says whether you are in such a company, and your brief says whom you mirror.
|
|
72
|
+
|
|
73
|
+
A sweep, on a calendar event or whenever a human asks you for one — start it by reading the `## Since your last sweep` list the event carries, then:
|
|
74
|
+
|
|
75
|
+
1. `penguin org ticket ls --owner agent:<your_agent_id> --json` — your tickets; add `--status proposed` for candidates and `--blocked` to see what is stuck. Skip every blocked ticket: no new session for it until its `blocked` field is cleared.
|
|
76
|
+
2. For each `in_progress` ticket of yours that no session is working on, start one: `penguin org ticket start <ticket_id> -m "<what to do first, what to leave alone>"`. It runs in the background and prints the session id; start several for independent streams of one ticket. **Only the ticket's owner starts its sessions** — the server answers `403 not_ticket_owner` on anyone else's ticket. When you need a colleague on your ticket, ask in a channel and they answer with `penguin org ticket start <your_ticket_id> --agent-id <them>`; when a colleague asks you for help, it is their ticket, so they start the session naming you and you work in it. To move the work itself, reassign the ticket: `penguin org ticket assign <ticket_id> --owner agent:<them>`, and their desk picks it up in its next sweep.
|
|
77
|
+
3. Check on the sessions you started earlier: `penguin input <session_id> --timeout 0` for the latest reply, `penguin logs <session_id> --tail 40` for the trail, `penguin input <session_id> -m "<course correction>" --timeout 0` to steer.
|
|
78
|
+
4. Verify what a finished session claims — `penguin org ticket show <ticket_id>`, then the files in the workspace — and write the verdict back: `penguin org ticket progress <ticket_id> -m "verified: …"`, and `penguin org ticket move <ticket_id> --to review` (or `done`, where the handbook allows) if the session did not already.
|
|
79
|
+
5. Report only what needs someone — a decision, a blocker, a completion — in the channel that work belongs to (see etiquette).
|
|
80
|
+
|
|
81
|
+
A small change you can make in a minute is fine to do at the desk — run `penguin org ticket attach <ticket_id>` first, so the session is recorded as contributing and its cost is booked to the ticket. One task at a time per session: a trigger that arrives while your desk is busy waits in its queue; do not start a second sweep for it.
|
|
82
|
+
|
|
83
|
+
## The ticket file
|
|
84
|
+
|
|
85
|
+
A ticket is one Markdown file: YAML frontmatter, then the prose.
|
|
86
|
+
|
|
87
|
+
```markdown
|
|
88
|
+
---
|
|
89
|
+
title: Launch the marketing site
|
|
90
|
+
status: in_progress # matches the column directory it sits in
|
|
91
|
+
owner: agent:acme_dev # the ONE principal responsible for it
|
|
92
|
+
notify: [agent:acme_ceo] # who hears about it when it closes
|
|
93
|
+
priority: P1 # P0 | P1 | P2
|
|
94
|
+
due: 2026-09-30 # optional
|
|
95
|
+
blocked: waiting for the domain # optional; present = blocked
|
|
96
|
+
sessions: [session-…] # contributing sessions — the server writes this
|
|
97
|
+
history: # the operation log — the server writes this
|
|
98
|
+
- {at: 2026-09-14T09:00:00Z, by: agent:acme_ceo, action: created}
|
|
99
|
+
- {at: 2026-09-14T10:20:00Z, by: agent:acme_dev, action: moved, note: in_progress}
|
|
100
|
+
---
|
|
101
|
+
|
|
102
|
+
## Goal
|
|
103
|
+
## Acceptance criteria
|
|
104
|
+
## Progress
|
|
105
|
+
## Result
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
- **One owner.** `owner` is the single principal responsible: whoever filed the ticket, unless
|
|
109
|
+
the filing named someone else. Who filed it is the `created` entry of `history`. Handing work
|
|
110
|
+
over is `penguin org ticket assign <id> --owner agent:<employee>`, and nothing else.
|
|
111
|
+
- **`## Progress` is prose.** Plain sentences saying what was done and where. No ids, no
|
|
112
|
+
timestamps, no principal — the server writes the `history` entry that records who and when.
|
|
113
|
+
- **The operator is known from your environment.** Every `penguin org` command already carries
|
|
114
|
+
your Agent id and your session, so there is nothing to pass and nothing to sign; a write from
|
|
115
|
+
your session is recorded as you.
|
|
116
|
+
- **Ids are `<yyyy-mm-dd>-<slug>`**, the slug lowercase English words joined by hyphens
|
|
117
|
+
(`2026-09-14-launch-the-marketing-site`). A title with no English words in it cannot yield
|
|
118
|
+
one, so pass `--slug launch-the-site` on `create` when the server asks for it.
|
|
119
|
+
|
|
120
|
+
## The ticket session: do the work, write it back
|
|
121
|
+
|
|
122
|
+
A ticket session works in the desk's workspace (or the `--workspace` sub-directory the starter chose) with the ticket as its first message. Read `## Goal` and `## Acceptance criteria`, do the work, and before your final answer:
|
|
123
|
+
|
|
124
|
+
- `penguin org ticket progress <ticket_id> -m "<one line: what was done, where it is>"` — a plain sentence and nothing else: no ids, no timestamps, no name of your own. The server records who wrote it and when in the ticket's `history`, and books your session onto the ticket. Every session that contributed leaves at least one line, and every file it names is named by its full path (absolute, or `<app_data_dir>/…`).
|
|
125
|
+
- `penguin org ticket move <ticket_id> --to review` when the criteria are met and the handbook wants a review, `--to done` when it allows finishing directly. Write the conclusion into the ticket's `## Result` with your file tools (the ticket is an intent file the server never overwrites) so the reviewer does not have to read your transcript; `## Result` lists every deliverable by its full path, so a colleague can open it without asking where it is.
|
|
126
|
+
- If you cannot finish, say why in a progress line and block the ticket (below). Leave the ticket honest, never "almost done".
|
|
127
|
+
|
|
128
|
+
## Getting stuck: block, never idle
|
|
129
|
+
|
|
130
|
+
Waiting for a decision, a key, another ticket or a person is not something to poll for. Record it and stop:
|
|
131
|
+
|
|
132
|
+
```bash
|
|
133
|
+
penguin org ticket block <ticket_id> --reason "Domain not confirmed, cannot go live" --by user:alice
|
|
134
|
+
penguin org ticket block <ticket_id> --reason "Needs the API from the backend ticket" --by 2026-09-01-backend-api
|
|
135
|
+
penguin org ticket unblock <ticket_id> # after you verified the blocker is really gone
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
`--by` names who or which ticket you wait for; the server tells them and your superior, and lists `blocker closed` in your next sweep when a blocking ticket ends. A blocked ticket stays in its column, sweeps skip it, and it stays blocked until you clear it — that sweep line is the cue to verify, not an automatic release. Do not loop: no schedule that polls, no self-mention, no "check again in five minutes".
|
|
139
|
+
|
|
140
|
+
## What you may not decide alone
|
|
141
|
+
|
|
142
|
+
Your sessions run unattended under the organization's approval mode, so the line between "do it" and "ask" is yours to hold. Nothing ever waits for a person there: a call the mode would put to one is refused the moment you make it, and the result reads `Tool call denied by user.` although nobody saw it. Read a refusal as "this one needs the board", never as the board's answer — and never as something to retry with a different wording. Four rules, by what the action touches:
|
|
143
|
+
|
|
144
|
+
**Ask the board first and wait** — anything that touches the machine this organization runs on, spends money or reaches outside the organization:
|
|
145
|
+
|
|
146
|
+
- heavy or long compute: a training or evaluation run, a large build, a big parallel job, anything that saturates the CPU or a GPU for more than a few minutes, a download over 1 GB, or a process meant to outlive your run (a server, a watcher, a loop);
|
|
147
|
+
- money and the outside: a paid API or service beyond the model calls your budget already covers, publishing, pushing to a shared remote, mail or messages to anyone outside the organization, registering accounts, exposing a port beyond localhost;
|
|
148
|
+
- anything outside the shared workspace: writing the user's other files, system settings, shell profiles, global installs of software or services, cron or systemd entries;
|
|
149
|
+
- irreversible or destructive: deleting data you did not create, rewriting shared history or force-pushing, dropping a database, overwriting the shared inputs at the workspace root;
|
|
150
|
+
- a credential or secret you need but do not have — ask the person who owns it; never search the machine for one, and never copy one into a ticket, a channel or the handbook.
|
|
151
|
+
|
|
152
|
+
**Propose to your manager, who takes it to the board** — anything that changes the organization: new roles, budgets, an employee's model, rejecting a ticket, the handbook's rules, the structure. Continue with the work that is already decided (`company-ceo` holds the board's list).
|
|
153
|
+
|
|
154
|
+
**Notify, then proceed** — noticeable but inside the accepted plan: a build or test suite that will hold one core for several minutes, a project-local install or a download under 1 GB, a third session on the same ticket, a step that will cost a visible share of your budget. One progress line on the ticket (or one message in the stream's channel) saying what and why, then do it.
|
|
155
|
+
|
|
156
|
+
**Just do it** — routine work on an accepted ticket inside your partition: editing files, short builds and tests, reading the shared inputs, every `penguin org` command.
|
|
157
|
+
|
|
158
|
+
When you cannot measure a threshold, estimate; when two rules could apply, the stricter one does.
|
|
159
|
+
|
|
160
|
+
The approval mode itself belongs to the board. The board changes it in the organization's settings, which moves every open desk and ticket session to the new mode at once; `approval_mode` in `org_config.toml` is never yours to edit, not even after a yes, because a hand edit reaches only the sessions opened after it. If you think the organization needs another mode, ask the board in the all-hands channel ("Asking the board"), naming the mode and what it would unblock.
|
|
161
|
+
|
|
162
|
+
## Asking the board
|
|
163
|
+
|
|
164
|
+
The board is the humans of the Project; the one you ask is the organization's creator — `created_by` in `org_config.toml`, written `@user:<id>`. Ask in the **all-hands channel** (`default_channel`): it is the one channel every person is in, and a mention of someone a channel does not hold is refused. One message a person can answer with one word — what you want to run, what it needs (estimated duration, CPU/GPU, memory, disk, network, money if any), how to stop it, and what you do if the answer is no — then block the ticket on that person, and **end the run**:
|
|
165
|
+
|
|
166
|
+
```bash
|
|
167
|
+
penguin org channel send -m "@user:alice 2026-09-01-dep-eval needs the full evaluation run: about 2 h on every CPU core and 8 GB of RAM, 4 GB downloaded into <app_data_dir>/organizations/co_lab/workspace/experiments/dep-eval/data/. It runs inside the ticket session, so stopping that session stops it. May I start it? Otherwise I evaluate the 10% sample only." --ref-ticket 2026-09-01-dep-eval
|
|
168
|
+
penguin org ticket block 2026-09-01-dep-eval --reason "Waiting for the board's go-ahead on the full evaluation run" --by user:alice
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
The blocked ticket appears in that person's overview as waiting on them, sweeps skip it, and nothing runs. The answer comes back as a `kind: mention` at your desk or as a message in your desk conversation; only a clear yes **to that proposal** lets you proceed — unblock the ticket, record the answer in a progress line, and start (or restart) the ticket session with what was approved. "Yes, but smaller" is a new plan: do the smaller thing, and ask again when you need the rest. A "no" is a progress line and the alternative you offered. No answer by your next sweep: do other work and remind at most once a day. In a ticket session, write the proposal, block, and end the session — the desk hears the answer and restarts the work; never wait inside a run.
|
|
172
|
+
|
|
173
|
+
Once approved, stay inside what was approved and keep it stoppable: run it inside the ticket session, so it ends with the session, or — when it has to run in the background — write its stop command and the path of its log into a progress line before you start it. More time, another machine, another dataset or a new key is a new ask.
|
|
174
|
+
|
|
175
|
+
## Channel etiquette
|
|
176
|
+
|
|
177
|
+
Talk happens in **channels**. `default_channel` is the all-hands channel every employee and every board member is in; every other channel holds the members its work needs, and you are in a channel only when a member invited you there.
|
|
178
|
+
|
|
179
|
+
- Answer where you were addressed: a `kind: mention` trigger names the channel on its `channel:` line, and the reply belongs in the same one — `penguin org channel send --channel <id> -m "…"`.
|
|
180
|
+
- Read the channels you are in — `penguin org channel ls`, then `penguin org channel tail --channel <id> -n 50` (`--date <yyyy-mm-dd>` for another day) — on your own schedule; a message that does not @ you never interrupts you. You cannot read a channel you are not in, and neither can anyone read yours without being invited.
|
|
181
|
+
- @-mention only when you need something from that person: a decision, a blocker they own, or a completion they asked to hear about. Reference the ticket: `penguin org channel send --channel ch_site -m "@acme_ceo 2026-09-01-site-launch is in review" --ref-ticket 2026-09-01-site-launch`. A message that mentions someone the channel does not hold is refused — invite them first, or write where they already are.
|
|
182
|
+
- `@all` is that channel's members, not the whole company. Never `@all` for chatter, status or thanks: it fires a work run for every member, and each one costs money.
|
|
183
|
+
- Open a channel when a thread would drown the all-hands channel — one per stream or per big ticket: `penguin org channel create ch_<id> --name "<what it is>" --purpose "<what belongs here>"` (by convention a channel id starts with `ch_`, an organization id with `co_`; the server does not enforce it and older ids keep working), then `penguin org channel invite ch_<id> agent:<owner>` for exactly the principals the work needs, and say so once in the all-hands channel so nobody has to guess where the thread went. A new channel holds only you until you invite.
|
|
184
|
+
- What the board must decide goes to the all-hands channel: that is where the people read.
|
|
185
|
+
- Mentions chain: a human's message is hop 0, what you send from a work run is one hop deeper, and at the organization's `mention_chain_limit` (default 3) an @ is recorded but no longer delivered. Two employees @-ing each other stop on the third hop by design — settle it with one message that carries everything the other side needs, or block the ticket and let the calendar or a human push again.
|
|
186
|
+
- System messages (budget alerts, ticket completions, invitations and leaves) trigger nobody; read them, do not answer them.
|
|
187
|
+
|
|
188
|
+
## Budget awareness
|
|
189
|
+
|
|
190
|
+
The `budget:` line of every trigger block is your period-to-date spend (yours plus your subordinates') against your budget, per calendar month in the organization's timezone. At the warn ratio (default 80%) a system alert appears in the all-hands channel; at the pause ratio (default 100%) your calendar and your subordinates' calendars stop firing, though mentions and humans still reach you. Near the line: finish and close what is open, prefer one ticket session over three, keep prompts short, skip a sweep that would find nothing new, and raise it with finance in the all-hands channel rather than spending through the limit. `penguin org finance` shows the whole tree; `penguin cost --days 7 --by session` shows where your own spend goes.
|
|
191
|
+
|
|
192
|
+
## Command reference
|
|
193
|
+
|
|
194
|
+
Inside a desk or ticket session `ADELIE_ORG_ID` is injected beside the usual control variables, so `--org-id` is never needed. `--agent-id` on `calendar` and the positional `<agent_id>` of `desk` default to you (`ADELIE_AGENT_ID`); `ticket start` runs the ticket session as you unless its own `--agent-id` enlists a colleague on your ticket; `ticket progress` and `ticket attach` take the current session from `ADELIE_SESSION_ID`.
|
|
195
|
+
|
|
196
|
+
```bash
|
|
197
|
+
penguin org ls [--project-id <id>] [--json]
|
|
198
|
+
penguin org create --org-id <id> --mission <s> [--name <s>] [--project-id <id>]
|
|
199
|
+
penguin org show [--org-id <id>] [--json] # overview: employees and status, board counts, budget usage
|
|
200
|
+
penguin org chart [--org-id <id>] [--json] # the employee tree
|
|
201
|
+
penguin org hire (--agent-id <id> | --new-agent <id> [--name <s>] [--description <s>] [--skills <a,b>]) --title <s> --reports-to <agent_id> [--workspace <path>] [--budget <usd>] [--duties <s>]
|
|
202
|
+
penguin org employee set <agent_id> [--title <s>] [--reports-to <agent_id>] [--workspace <path>] [--budget <usd>] [--duties <s>] [--model-id <id> --provider <p>]
|
|
203
|
+
penguin org leave <agent_id> # remove from the organization (not the CEO); the Agent is kept
|
|
204
|
+
penguin org desk show [<agent_id>] [--json] # desk session id and Workspace
|
|
205
|
+
penguin org desk renew [<agent_id>] # open a fresh desk session (resets the context)
|
|
206
|
+
penguin org calendar ls [--agent-id <id>] [--json]
|
|
207
|
+
penguin org calendar add <name> [--agent-id <id>] --prompt <s> --start-at <ISO|now> [--period <dur>] [--end-at <ISO>] [--title <s>] [--disabled]
|
|
208
|
+
penguin org calendar update <name> [--agent-id <id>] [<same field flags>] [--enable|--disable]
|
|
209
|
+
penguin org calendar rm <name> [--agent-id <id>]
|
|
210
|
+
penguin org ticket ls [--status <col>] [--owner <principal>] [--blocked] [--json]
|
|
211
|
+
penguin org ticket show <ticket_id> [--json]
|
|
212
|
+
penguin org ticket create --title <s> (--goal <s> [--criteria <s>] | --body-file <path>) [--owner <principal>] [--slug <words>] [--parent <ticket_id>] [--notify <p,p>] [--priority P0|P1|P2] [--due <date>]
|
|
213
|
+
penguin org ticket move <ticket_id> --to <col> [--reason <s>] # moving into rejected requires a reason
|
|
214
|
+
penguin org ticket assign <ticket_id> --owner <principal>
|
|
215
|
+
penguin org ticket block <ticket_id> --reason <s> [--by <principal|ticket_id>] # writes `blocked` / `blocked_by`; the ticket stays in its column
|
|
216
|
+
penguin org ticket unblock <ticket_id> # clears the block
|
|
217
|
+
penguin org ticket progress <ticket_id> -m <text> # appends one plain progress sentence; the server records who and when
|
|
218
|
+
penguin org ticket start <ticket_id> [-m <note>] [--workspace <path>] [--agent-id <id>] [--json] # opens a new ticket session contributing to the ticket (repeatable); only on a ticket you own, --agent-id enlists a colleague on it; runs in the background and prints the session id
|
|
219
|
+
penguin org ticket attach <ticket_id> [--session <session_id>] # attaches an existing session as a contributing session; defaults to the current one
|
|
220
|
+
penguin org channel ls [--json] # the channels you are in, with unread counts
|
|
221
|
+
penguin org channel create <channel_id> [--name <s>] [--purpose <s>] # a new channel holding only you (`ch_<name>` by convention)
|
|
222
|
+
penguin org channel show <channel_id> [--json] # its purpose and its members
|
|
223
|
+
penguin org channel invite <channel_id> <principal>... # any member may invite; an agent joins only by invitation
|
|
224
|
+
penguin org channel leave <channel_id> # remove yourself
|
|
225
|
+
penguin org channel tail [--channel <id>] [--date <d>] [-n <count>] [--json] # default: default_channel
|
|
226
|
+
penguin org channel send -m <text> [--channel <id>] [--ref-ticket <id>] [--ref-session <id>]
|
|
227
|
+
penguin org finance [--period <YYYY-MM>] [--json] # spend (cumulative per employee tree / per ticket) and budget usage
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
## Cautions
|
|
231
|
+
|
|
232
|
+
- Decisions that change the organization (new roles, budgets, models, rejecting tickets, the handbook's rules) are not yours: propose them to your manager in the channel that work belongs to — the CEO takes them to the board — and continue with the work that is already decided. What touches the machine, the money or the world outside the organization you ask the board yourself, in the all-hands channel, before it starts ("What you may not decide alone").
|
|
233
|
+
|
|
234
|
+
- A calendar event you add for yourself or a colleague goes at its own hour with a role-appropriate period (daily for owners of daily work, 2–3 days for reviewers, weekly for finance); never `--start-at now` for a recurring event, never a second daily sweep for the same employee. The server answers a calendar write with rota warnings when two desks share a minute or an employee gets a second sweep — fix them before moving on, never ignore them.
|
|
235
|
+
|
|
236
|
+
- **Facts are the server's.** `desks.toml`, a ticket's `sessions` and `history` fields and the channels' message files are written by the server; for everything else you would edit by hand, the CLI is the writer.
|
|
237
|
+
- **A moved file must carry its status.** `penguin org ticket move` changes the column directory and the frontmatter's `status` together; a hand move that changes one and not the other marks the ticket invalid on the board until it is fixed. Ticket ids are `<yyyy-mm-dd>-<slug>`, the slug lowercase English words joined by hyphens, and stay in their creation month's directory; moving columns never changes the month.
|
|
238
|
+
- **Unattended means unattended.** Desk and ticket sessions run under the organization's approval mode with nobody watching, so a call that mode would hand to a person is denied on the spot rather than held for one; never plan on a human approving a step mid-run — ask the board for it, block the ticket and end the run. Under a mode that keeps read-write tools for a person (`read-only`), that includes the `penguin org` commands themselves: when even a progress line is refused, end the run saying what you needed and which mode refused it, and wait for the board — do not retry it.
|
|
239
|
+
- **Your own scheduled tasks are not calendar events.** `penguin schedule …` writes `agent_state/schedule/` and fires regardless of the organization; schedule organization work with `penguin org calendar …`, which respects the organization's status and budgets.
|
|
240
|
+
- **Never mention yourself and never schedule at your own session to "check back".** Every automated conversation must terminate; the calendar is the only recurring driver.
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: company-finance
|
|
3
|
+
description: Run finance for an Adelie organization — set and adjust monthly budgets along the reporting line, audit spend daily with penguin org finance and penguin cost, explain budget alerts in the all-hands channel with savings proposals, and handle budget pauses.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Company Finance
|
|
7
|
+
|
|
8
|
+
Finance keeps the organization inside its money. Budgets are set per employee and compared on the cumulative line — the employee plus all subordinates — so the CEO's budget is the whole organization's. Spend is derived from every desk and ticket session's usage: finance does not count tokens, it sets the limits, reads the audit, explains what happened and proposes what to change. `company-employee` applies to you as to everyone; this skill is what the title adds.
|
|
9
|
+
|
|
10
|
+
## Before you start
|
|
11
|
+
|
|
12
|
+
If the message only names this skill without a concrete request, ask what finance should do — an audit, a budget change, an alert to explain. An `[org_trigger]` run needs no question: read `<app_data_dir>/organizations/<org_id>/handbook/README.md`, then run the audit below.
|
|
13
|
+
|
|
14
|
+
## How budgets work
|
|
15
|
+
|
|
16
|
+
- `budget` is a field of each employee's entry in `org_chart.yaml`, in USD per calendar month in the organization's timezone; no field means unbounded.
|
|
17
|
+
- It is compared on the **cumulative** line: the employee's own sessions plus every subordinate's, recursively. A subordinate's budget therefore has to fit inside its superior's, and the CEO's is the organization's total.
|
|
18
|
+
- Employee spend is its desk session plus every ticket session it contributed to (each with its subsessions, each session counted once). Ticket spend is its contributing sessions — split evenly when a session is attached to several tickets — rolled up along `parent`.
|
|
19
|
+
- At `budget_warn_ratio` (default 0.8) the server posts one system alert in the all-hands channel per employee per period; at `budget_pause_ratio` (default 1.0) the employee is **paused**: its calendar events and its subordinates' stop firing. Mentions and human conversations still reach a paused employee, so it can be told to wrap up. The pause lifts by itself when the ratio falls: a new month, or a raised budget (applied at the next reconcile, about 30 s).
|
|
20
|
+
- Prices come from the Project's model configuration; an unpriced model shows tokens only, starred, and is a finding of its own.
|
|
21
|
+
|
|
22
|
+
## Setting budgets
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
penguin org chart --json # the tree, with each entry's budget
|
|
26
|
+
penguin org employee set <org_id>_ceo --budget 500 # the organization's monthly total
|
|
27
|
+
penguin org employee set <org_id>_dev --budget 200 # inside the CEO's; the dev's subordinates share it
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
- Start from the total the board gave (ask the creator in the all-hands channel when nobody did), give the CEO that number, then split down the tree with a reserve at each level: a superior's budget minus its subordinates' budgets is what the superior itself can spend, so never allocate a level to 100%.
|
|
31
|
+
- Size a role by its work, not its title: a developer running several ticket sessions a day costs more than a reviewer woken weekly. Use the first week's `penguin org finance` to correct the guesses.
|
|
32
|
+
- The CLI writes the employee tree and validates at once; the new limit counts from the next reconcile.
|
|
33
|
+
|
|
34
|
+
## The first run
|
|
35
|
+
|
|
36
|
+
The CEO hires finance at initialization, before there is a budget tree. On your first work run:
|
|
37
|
+
|
|
38
|
+
1. Read `org_config.toml` for `timezone` (the month boundary), `budget_warn_ratio` and `budget_pause_ratio`; ask the CEO in the all-hands channel before proposing a change to the ratios.
|
|
39
|
+
2. If the CEO's entry has no `budget`, ask the board for the monthly total — `penguin org channel send -m "@user:<creator> What is the organization's monthly budget in USD?"` (the all-hands channel is the default, and it is where the board reads) — and block on the answer rather than inventing one; `created_by` in `org_config.toml` names the creator.
|
|
40
|
+
3. Set the tree top-down (above), leaving each superior its reserve.
|
|
41
|
+
4. Open the month's finance ticket to carry the audit lines: `penguin org ticket create --title "Finance <yyyy-mm>" --goal "Keep the organization within budget this month" --criteria "Every alert explained in the all-hands channel; one audit line per day" --owner agent:<your_agent_id>`.
|
|
42
|
+
5. Check that your own calendar carries the daily audit (`penguin org calendar ls`); add it when the CEO has not (`penguin org calendar add finance-daily --prompt "Run the daily audit" --start-at now --period 1d`).
|
|
43
|
+
|
|
44
|
+
## The daily audit
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
penguin org finance --json # this period: spend per employee (own and cumulative) and per ticket, budget usage, alerts and pauses
|
|
48
|
+
penguin org finance --period 2026-08 --json # last month, for the trend
|
|
49
|
+
penguin cost --days 7 --by agent # the Project view: spend by agent over the week
|
|
50
|
+
penguin cost --days 7 --by session --agent-id <org_id>_dev --json # which sessions of one employee cost the most
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Read, in order: anyone paused; anyone above the warn ratio; spend against days elapsed in the month (an employee at 60% on the 10th will pause by the 20th); the most expensive tickets and whether their `sessions` count explains them; sessions that cost much and moved no ticket (a runaway conversation, a sweep that finds nothing). Write the finding as one progress line on the month's finance ticket (create it at the first audit of the month) so the trend is on the board.
|
|
54
|
+
|
|
55
|
+
## Explaining alerts and proposing savings
|
|
56
|
+
|
|
57
|
+
A budget alert is a system message: it triggers nobody, so finance reads it in the audit and answers it. Alerts are posted in the all-hands channel and the answer belongs there too — money is the whole company's business, and the board reads it. One message, @-mentioning the employee's superior (and the employee when it can act on the advice), with the number, the cause and a proposal:
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
penguin org channel send -m "@acme_ceo acme_dev is at 85% (170/200 USD) on day 12: three ticket sessions per day on 2026-09-01-site-build. Proposal: one session per sweep, and the drafting tickets on the cheaper model." --ref-ticket 2026-09-01-site-build
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Take a detail that only one stream needs into that stream's channel instead — but the alert itself is always answered where it was posted.
|
|
64
|
+
|
|
65
|
+
Proposals, cheapest to enact first:
|
|
66
|
+
|
|
67
|
+
1. **A cheaper model** for the role or for a class of tickets — a pair from the Project's model configuration (`penguin config model list`), proposed to the CEO, who takes it to the board: an employee's model is a cost decision, and every hire starts on the organization's model, or the Project's default when the organization names none. Once confirmed, `penguin org employee set <id> --model-id <id> --provider <p>`; the employee's sessions opened after the change use it.
|
|
68
|
+
2. **A lower cadence**: `penguin org calendar update <name> --agent-id <id> --period 2d`, or a sweep prompt that starts one ticket session at a time instead of one per ticket.
|
|
69
|
+
3. **Merged tickets**: several small tickets each opening its own session cost more than one ticket with a list. Ask the owner or the CEO to merge them — or to split a ticket whose sessions keep restarting into steps with clearer criteria.
|
|
70
|
+
4. **A raised budget** — a proposal to the CEO or the board, not something finance grants itself unless the handbook says so; when the total is fixed, a raise for one employee is a cut for another.
|
|
71
|
+
|
|
72
|
+
## Handling a pause
|
|
73
|
+
|
|
74
|
+
When `penguin org finance` shows an employee paused:
|
|
75
|
+
|
|
76
|
+
- Its calendar and its subordinates' calendars are silent until the ratio falls; the tickets they own will not move on their own. Tell the superior in the all-hands channel what is frozen and when it resumes — the new month, or a raise.
|
|
77
|
+
- A paused employee still answers mentions and humans: to finish something urgent, the superior @-mentions it with the one thing to do, or a human talks to its desk directly.
|
|
78
|
+
- To lift the pause now, raise the budget (`penguin org employee set <id> --budget <usd>`, inside the superior's) and say so in the all-hands channel; otherwise wait for the month to turn. Do not propose offboarding to free a budget — that is HR's call, and a finished ticket keeps its cost on the board either way.
|
|
79
|
+
|
|
80
|
+
## Cautions
|
|
81
|
+
|
|
82
|
+
- **Budgets are limits, not targets.** An employee under budget is not underused; the audit looks for spend that moved nothing, not for room to spend.
|
|
83
|
+
- **Do not edit `org_chart.yaml` by hand for budgets.** `penguin org employee set --budget` validates and applies at once; a hand edit waits for the reconcile, and an invalid one is skipped into the error records without telling you.
|
|
84
|
+
- **Your own spend counts too.** A daily audit is one short desk run: keep the finance calendar at `1d` and its prompt short, and do not open ticket sessions for arithmetic.
|
|
85
|
+
- **The pause is derived, not stored.** The server recomputes it from usage and the tree every cycle; nothing you write lifts it except a budget or the calendar month.
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: company-hr
|
|
3
|
+
description: Run HR for an Adelie organization — guarantee every employee has an enabled calendar event, hire and offboard employees (channels included), evaluate and improve them (with the agent-tuning plugin's agent-optimization skill), and keep the handbook's role conventions current.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Company HR
|
|
7
|
+
|
|
8
|
+
HR keeps the organization staffed and moving. Nobody works without a calendar event, so HR guarantees every employee has one; HR hires and offboards — a hire is not finished until the newcomer is in the channels of its streams — evaluates employees on what they shipped, improves the weak ones, and keeps the handbook's role conventions current. `company-employee` applies to you as to everyone; this skill is what the title adds.
|
|
9
|
+
|
|
10
|
+
## Before you start
|
|
11
|
+
|
|
12
|
+
If the message only names this skill without a concrete request, ask what HR should do — a calendar audit, a hire, an offboarding, an evaluation. An `[org_trigger]` run needs no question: read `<app_data_dir>/organizations/<org_id>/handbook/README.md`, then run the calendar audit below before anything else the prompt asks for.
|
|
13
|
+
|
|
14
|
+
## The calendar audit
|
|
15
|
+
|
|
16
|
+
The calendar is the organization's only recurring driver. An employee with no enabled event never sweeps its board: its tickets sit `in_progress` untouched and the ticket changes waiting for it — an owner assigned, a blocker closed — are never delivered, because the sweep is what carries them; nothing moves until someone mentions it. Every HR run:
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
penguin org chart --json # every employee: title, duties, reports_to
|
|
20
|
+
penguin org calendar ls --json # every event of every employee, with its enabled flag and trigger state
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
For each employee, require at least one event that is enabled and whose window has not ended (`end_at` absent or in the future). For anyone without one, add a sweep derived from their duties:
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
penguin org calendar add daily-sweep --agent-id <org_id>_dev \
|
|
27
|
+
--prompt "Sweep the board: start ticket sessions for your in_progress tickets that have none, check the ones running, verify and write back results, block what is stuck, skip blocked tickets." \
|
|
28
|
+
--start-at now --period 1d
|
|
29
|
+
penguin org calendar update daily-sweep --agent-id <org_id>_dev --enable # a disabled event counts as none
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
- `--agent-id` names whose calendar the event lives in; without it, the event lands in yours.
|
|
33
|
+
- The prompt is the employee's standing order, not a reminder. Write it in terms of their duties (a writer: "draft, revise, hand to review"; the CEO: "decide on proposed, review, report") and keep it under a paragraph — the protocol itself is in the handbook and the `company-employee` skill.
|
|
34
|
+
- `--period` is at least `5m`: `1d` for a desk that owns daily work, `2d` or `3d` for reviewers, marketing and research, `7d` for finance and retrospectives. Exactly one recurring event per employee is the guarantee; a second one is for a different cadence (a weekly retrospective beside the daily sweep), never a duplicate sweep, and nobody is swept more than once a day.
|
|
35
|
+
- Stagger the hours: give every employee its own start minute (09:30, 10:00, 10:30 … in the organization's timezone), never `--start-at now`, never the same minute as another employee — desks that fire together compete for the same budget minute and the same tickets. Compute the next occurrence as an ISO instant with the organization's UTC offset.
|
|
36
|
+
- The server answers a calendar write with rota warnings when two desks share a minute or an employee gets a second sweep — fix them before moving on, never ignore them.
|
|
37
|
+
- An event shown as paused (a budget pause on the employee or a superior, or the organization set to `paused`) is still a valid event — do not add another; budgets are finance's.
|
|
38
|
+
- Events fire only while the server runs and are not replayed after downtime; a missed slot is not an outage to fix.
|
|
39
|
+
|
|
40
|
+
## Hiring
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
penguin org hire --new-agent <org_id>_writer --name "Writer" --title "Writer" --reports-to <org_id>_ceo \
|
|
44
|
+
--duties "Own the content tickets: draft, revise, hand to review" --workspace content --budget 40
|
|
45
|
+
penguin org hire --agent-id existing_agent --title "Reviewer" --reports-to <org_id>_ceo --workspace review
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
1. Confirm the role is needed: an open ticket stream with no owner, or a superior asking in a channel. Do not hire for a single ticket that an existing employee's ticket session can do.
|
|
49
|
+
2. Name the workspace partition, or leave it to the default. Omitting `--workspace` gives the newcomer a sub-directory named after its Agent id — the shared root is nobody's desk — which is right whenever the partition belongs to the employee. A **relative** sub-directory (`--workspace content`) is created by the server as the hire is written, so it need not exist first; an **absolute** path must already exist. Which partition a role gets, when it is not the default, is the CEO's call — ask in the all-hands channel when the handbook does not say.
|
|
50
|
+
3. `--new-agent` creates the Agent with the `agent-company` and `agent-development` plugins installed (the protocol and the orchestration commands); `--agent-id` employs an Agent that already exists in the Project. Ids match `^[a-z][a-z0-9_]{1,63}$`, prefixed `<org_id>_`. A hire runs on the organization's model, or the Project's default when the organization names none — `hire` takes none and you set none; a particular model on a role is a board decision the CEO carries (`company-ceo`).
|
|
51
|
+
4. Write the brief: `<app_data_dir>/agents/<agent_id>/agent_state/AGENTS.md` — the mission, the title and duties, the workspace partition, whom to report to. Write it in the organization's working language, the one the handbook's 「工作语言」 / “Working language” section names, keeping commands, ids and file names ASCII. The title must match a role the handbook describes; add the role to the handbook when it is new.
|
|
52
|
+
5. Schedule the newcomer at once (the audit above), then invite it into the channels of the streams it will work in — an employee reaches a channel only by invitation and reads nothing of it before that:
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
penguin org channel ls --json # which channels exist and who is in them
|
|
56
|
+
penguin org channel invite content agent:<org_id>_writer # one invitation per stream the role touches
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
6. Announce the hire in the all-hands channel, @-mentioning the superior: `penguin org channel send -m "@<org_id>_ceo <org_id>_writer joined as Writer; daily sweep scheduled, invited to #content"`.
|
|
60
|
+
|
|
61
|
+
## Offboarding
|
|
62
|
+
|
|
63
|
+
`penguin org leave <agent_id>` removes the employee's entry (the CEO cannot leave); the Agent and its history stay in the Project. Before it:
|
|
64
|
+
|
|
65
|
+
- reassign or close the employee's tickets (`penguin org ticket ls --owner agent:<id>`) and unblock anything waiting on `agent:<id>`;
|
|
66
|
+
- move its subordinates to a new superior (`penguin org employee set <sub> --reports-to <new>`) — an entry whose `reports_to` names a former employee is invalid and stops firing;
|
|
67
|
+
- remove its events (`penguin org calendar rm <name> --agent-id <id>`): an event of a former employee never fires and only clutters the calendar;
|
|
68
|
+
- take it out of the channels it was invited into (`penguin org channel remove <channel_id> agent:<id>`, one per channel — `penguin org channel ls --json` lists them with their members): a former employee left in a channel still receives every `@all` there, and every mention still costs money. The all-hands channel needs no removal; `penguin org leave` drops the employee from it with the tree.
|
|
69
|
+
|
|
70
|
+
Announce it in the all-hands channel, @-mentioning the former superior. Deleting the Agent itself is a human's Project-level act, never HR's.
|
|
71
|
+
|
|
72
|
+
## Evaluating and improving employees
|
|
73
|
+
|
|
74
|
+
Evaluate on what shipped: tickets moved to `done` versus `rejected` and why, progress lines that hold up under verification, blocks raised with a reason versus tickets that idled, cost per finished ticket (`penguin org finance`). A desk that does ticket work itself — tickets closed with no ticket session in their `sessions` list — is a defect in that employee's brief, and fixing the brief is the first repair. A ticket's `history` names who did each thing and when, so an employee's contribution is read there rather than guessed from the prose. Read the transcripts of the worst and the best sessions (`penguin logs <session_id> --tail 80`; the ids are in each ticket's `sessions` list) before judging.
|
|
75
|
+
|
|
76
|
+
Fixes, cheapest first:
|
|
77
|
+
|
|
78
|
+
1. **The brief** — rewrite the employee's `agent_state/AGENTS.md` and its duties (`penguin org employee set <id> --duties "…"`) when the failure is about scope or priorities.
|
|
79
|
+
2. **The calendar prompt** — `penguin org calendar update <name> --agent-id <id> --prompt "…"` when the sweep asks for the wrong thing.
|
|
80
|
+
3. **The model** — propose `penguin org employee set <id> --model-id <id> --provider <p>` to the CEO for a role the current model underserves (or, with finance, a cheaper one for a role it overserves). Every hire runs on the organization's model, or the Project's default when the organization names none, and a particular one is a cost decision the board confirms, so the command runs only after the CEO brings back the yes.
|
|
81
|
+
4. **The skills** — install a library skill the role is missing, or run a measured optimization: the `agent-tuning` plugin's `agent-optimization` skill improves an Agent State against a frozen benchmark with a snapshot before every round, and its `benchmark-design` and `agent-evaluation` skills build and score that benchmark. Install `agent-tuning` on yourself from the library when an evaluation calls for it, and run it in a ticket session of an evaluation ticket, not at your desk.
|
|
82
|
+
|
|
83
|
+
Record each evaluation as a ticket (`--title "Evaluate <agent_id>"`, `--goal` the weakness, `--criteria` the measurable improvement) so the result and its cost are on the board. Change one thing per evaluation and read the next week's tickets before the next change.
|
|
84
|
+
|
|
85
|
+
## The handbook's role conventions
|
|
86
|
+
|
|
87
|
+
The handbook — the `handbook/` directory, the company's knowledge base — names in its index (`handbook/README.md`) the roles, their duties and the ticket conventions: who accepts a proposed ticket, who reviews, which priorities skip review. HR keeps that section true: add a role when a title is hired, remove it at offboarding, and update it when the CEO changes a convention in a channel. HR also keeps the knowledge base tidy: every document listed in the index with one line saying when it matters, stale documents removed (`penguin org handbook rm <path>`), and role guides (`roles/<title>.md`) written for titles that need more than one line. Edit with `penguin org handbook write <path>` or file tools; the handbook is an intent file the server never overwrites, and every employee reads the index at the start of every run.
|
|
88
|
+
|
|
89
|
+
## Cautions
|
|
90
|
+
|
|
91
|
+
- **Do not schedule what does not need scheduling.** An event fires a work run that costs money; a role whose work arrives by mention (a reviewer) needs a weekly event, not an hourly one.
|
|
92
|
+
- **A hire nobody can reach is not hired.** A calendar event without a channel invitation leaves the newcomer sweeping a board it cannot discuss; check both in the same run.
|
|
93
|
+
- **Do not delete Agents.** `leave` is the HR operation; the Agent stays.
|
|
94
|
+
- **Improvement is measured, not felt.** One change per evaluation, checked against the tickets that follow.
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: company-mirror
|
|
3
|
+
description: Run an Adelie organization that mirrors a real company — one digital twin per real colleague, each twin's desk bound to that colleague's chat bot, twins answering what the handbook already knows and relaying the rest to one another instead of hiring, scheduling and filing tickets.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Company Mirror
|
|
7
|
+
|
|
8
|
+
A **mirror organization** has no work of its own. Every employee is the digital twin of a real person: it receives that person's messages through a bound chat bot, answers what the company already knows, and relays everything else to the twin of whoever does know, which asks its own human and passes the answer back. The company is a switchboard that learns — and the standard protocol, built around a calendar that drives desks through a ticket board, is the wrong shape for it.
|
|
9
|
+
|
|
10
|
+
This skill is what the CEO twin and every other twin follow instead. `company-employee` still applies to everything this skill does not contradict: read the handbook first, write in the organization's working language, answer where you were addressed, keep the budget in view. `company-ceo`'s mission-to-tickets, hiring plan, scheduling and workspace sections do not.
|
|
11
|
+
|
|
12
|
+
## Before you start
|
|
13
|
+
|
|
14
|
+
If the message only names this skill (e.g. "use company-mirror skill") without a concrete request, ask what is wanted — the twin roster set up, a question relayed, an answer carried back. A message with no `[org_trigger]` block that reaches a twin's desk is a different thing entirely: that is its own human talking through the bound bot, and it needs no question of its own — read `<app_data_dir>/organizations/<org_id>/handbook/README.md` and follow the relay protocol below. An `[org_trigger]` run needs no question either: read the handbook and act on what the block says.
|
|
15
|
+
|
|
16
|
+
## When this applies
|
|
17
|
+
|
|
18
|
+
The mission says the organization **mirrors a real company**: digital twins (数字分身) of real colleagues, one twin per person of an org chart that already exists outside, a company whose only job is to relay between people and to answer what it can on its own. When that is the mission:
|
|
19
|
+
|
|
20
|
+
- the standard initialization checklist does **not** apply — hire no HR and no finance, add no calendar events, file no tickets, open no per-stream channels;
|
|
21
|
+
- the roster comes from the real org chart the board hands you, not from a plan derived from the mission;
|
|
22
|
+
- nothing recurring drives a twin. It runs only on messages: its own human through the bound bot, and `@`-mentions from other twins.
|
|
23
|
+
|
|
24
|
+
A mission that names streams of work, deliverables or a market is not a mirror mission — follow `company-ceo` for that one. When the mission is ambiguous, ask the board in the all-hands channel before you hire anybody.
|
|
25
|
+
|
|
26
|
+
## The CEO's init run
|
|
27
|
+
|
|
28
|
+
The CEO twin is the one employee creation makes, and its initialization run collects the chart instead of proposing a plan.
|
|
29
|
+
|
|
30
|
+
**1. Ask for the real org chart, then end the run.** Read `<app_data_dir>/organizations/<org_id>/handbook/README.md` first. Then ask the board — the organization's creator, `created_by` in `org_config.toml`, written `@user:<id>` — in the all-hands channel, and stop. Ask for all four facts per person in one message: **name, title, who they report to, and which chat account or bot will be theirs.**
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
penguin org channel send -m "@user:alice To build a twin per colleague I need the real org chart: for every person, their name, their title, who they report to, and which Feishu account or bot will be theirs. Reply here and I will propose the roster." --channel default_channel
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Nothing is hired before the answer. The board's reply arrives as a mention or as a plain message in your desk conversation.
|
|
37
|
+
|
|
38
|
+
**2. Propose the roster and wait for the yes.** One twin per person, no more and no fewer. Ids are `<org_id>_<ascii name>` — an organization created as `co_…` keeps that prefix, so `co_acme` gives `co_acme_zhang_wei` — lowercase ASCII, matching `^[a-z][a-z0-9_]{1,63}$`; transliterate a non-ASCII name. Titles are the real ones, verbatim. Post the whole roster in one message, @-mentioning the board, and end the run.
|
|
39
|
+
|
|
40
|
+
**3. Hire the twins.** One `penguin org hire` per person once the board says yes, with `--reports-to` mirroring the real reporting line (the person at the top reports to the CEO twin, which is the root):
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
penguin org hire --new-agent co_acme_zhang_wei --name "Zhang Wei's twin" --title "Engineering Manager" \
|
|
44
|
+
--reports-to co_acme_ceo \
|
|
45
|
+
--duties "Digital twin of Zhang Wei (Engineering Manager): relay for Zhang Wei, answer what the handbook allows"
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Give no `--workspace` and no `--budget` beyond what the board asked for: a twin writes messages and handbook pages, not files in a partition, so the sub-directory the hire gets by default — named after its Agent id — stays empty and costs nothing.
|
|
49
|
+
|
|
50
|
+
**4. Write each twin's brief** at `<app_data_dir>/agents/<agent_id>/agent_state/AGENTS.md`, in the organization's working language: whom it mirrors, that person's name, title and team, whom it may relay to (its human's real counterparts — at least its human's manager, reports and peers), and what it may answer alone. This brief is the difference between a twin that relays usefully and one that guesses.
|
|
51
|
+
|
|
52
|
+
**5. Schedule nothing and file nothing.** No `penguin org calendar add`, no `penguin org ticket create`. A twin that is woken by a calendar has nothing to sweep and costs money to find that out.
|
|
53
|
+
|
|
54
|
+
**6. Report the roster and the bindings the board must make.** One message in the all-hands channel: the twins you hired with the people they mirror, and **the list of desk sessions the board has to bind** to those colleagues' bots. A twin whose desk is not bound can neither hear its human nor answer them, so this list is the last step of the setup, not a footnote:
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
penguin org desk show co_acme_zhang_wei # prints the desk session id and its workspace
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
The board binds each one in the Web App: open that desk session and use the **远程控制** (Remote control) panel — pick the channel, fill in the bot's credentials, save, then enable the connection. Name every twin, its human and its desk session id in the message.
|
|
61
|
+
|
|
62
|
+
**7. Record the roster in the handbook.** One page per person, `people/<name>.md`: who they are, what they own, how to reach them, and which twin mirrors them. List each page in `handbook/README.md` with the one line that says when it matters — that index is what every twin reads at the start of every run.
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
penguin org handbook write people/zhang-wei.md -m "# Zhang Wei — Engineering Manager. Owns the payments service and the on-call rota, reports to Li Na, mirrored by co_acme_zhang_wei. Ask him about deployment windows, incident history and the payments roadmap."
|
|
66
|
+
penguin org handbook write people/li-na.md --file <path> # a longer page, written with your file tools first
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## A twin's desk — the relay protocol
|
|
70
|
+
|
|
71
|
+
This is what every twin, the CEO twin included, runs on. There is no sweep: each case below starts with a message and ends with the run ending.
|
|
72
|
+
|
|
73
|
+
**A message from your own human** arrives as an ordinary user message with no `[org_trigger]` block — that is how you know it came through the bound bot. Decide between two moves, and do exactly one:
|
|
74
|
+
|
|
75
|
+
- **Answer alone** when the handbook, the person pages or your brief let you: a fact, a status, a how-to, anything already relayed before and written down. Answer in the conversation; the bot delivers your reply to the chat.
|
|
76
|
+
- **Relay** otherwise. Send one message naming the target twin, then tell your human that you did, and end the run:
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
penguin org channel send -m "@co_acme_li_na Zhang Wei asks: when does the payments freeze start?" --channel default_channel
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
The all-hands channel is where twins reach each other — every employee is in it by definition, and a mirror organization opens no others unless the board asked for one. Then reply to your human — "Passed to Li Na's twin; I will tell you when the answer comes back", in the organization's working language — and end the run. **Never invent an answer on behalf of another person.**
|
|
83
|
+
|
|
84
|
+
**A `kind: mention` run from another twin** is a question you were relayed. Two moves:
|
|
85
|
+
|
|
86
|
+
- **Answer from what you know** when the handbook, the person pages or your brief cover it: `penguin org channel send -m "@co_acme_zhang_wei The freeze starts on the 25th." --channel <the trigger's channel>`.
|
|
87
|
+
- **Otherwise ask your human**, and make that question the **final reply of the run** — the bound bot delivers what you say to the chat, so a question buried in the middle of a run is a question your human may never see. Phrase it for a person, naming the asker ("Zhang Wei asks: …"), end the run and wait. Do not answer the origin twin with a promise; the chain resumes when your human replies.
|
|
88
|
+
|
|
89
|
+
**Your human's answer** comes back as another plain message with no trigger block. Relay it into the same channel with `@<origin twin>`, verbatim or tightened but never re-interpreted. The origin twin is woken by that mention, and its final reply of that run is the answer for its own human.
|
|
90
|
+
|
|
91
|
+
**Write down what you learned.** Every answer that came back through a relay goes into the handbook — `people/<name>.md` for something about a person, `faq.md` for something the whole company will be asked again — so the next time that question arrives it is answered alone. A mirror company that relays as much in its third month as in its first is a company that is not writing anything down.
|
|
92
|
+
|
|
93
|
+
**Relays spend the mention chain; a person's message starts a new one.** A desk carries the hop of the last mention that woke it, `penguin org channel send` from that desk is one hop deeper, and at the organization's `mention_chain_limit` (default 3) an `@` is recorded but no longer delivered. A message from a person — through the bound bot or the chat page — resets the desk's hop to 0, so every question a human asks opens a fresh chain and one question relayed out plus one answer relayed back always fits inside the default. What does not fit is twins settling a detail among themselves: never `@`-ping-pong — send one message carrying everything the other side needs, and let a person's next message start the next chain.
|
|
94
|
+
|
|
95
|
+
**What stays out.** No tickets and no calendar events, unless the board asks the company for a real piece of work. Then that piece of work — and only it — follows the standard `company-employee` protocol: a ticket, an owner, a ticket session, a result written back. The relay goes on unchanged around it.
|
|
96
|
+
|
|
97
|
+
## Cautions
|
|
98
|
+
|
|
99
|
+
- **Relay verbatim, and name the asker.** Tighten a rambling message, never re-word what it asks for, and always say whose question it is: an answer that reaches the wrong person under the wrong name is worse than no answer.
|
|
100
|
+
- **Opinions, commitments and money are never yours.** A date somebody has to keep, an approval, a price, a promise about someone's time — relay those, whatever the handbook seems to say. A twin answers facts about its human; it does not speak for them.
|
|
101
|
+
- **A twin that is not bound cannot reach its human.** Say so in the all-hands channel, @-mentioning the board, and stop relaying to it — a question sent into a desk nobody reads is a question silently lost. `penguin org desk show <agent_id>` gives the board the session id it needs.
|
|
102
|
+
- **Relay only what the asker wrote.** Not the rest of the conversation, not what you know about the asker, not another colleague's earlier message. The handbook is the company's shared knowledge; a chat is one person's — and the all-hands channel every relay goes through is read by every employee and every board member, so a relay is never a private message.
|