@cmgmyr/hive 1.7.0 → 1.9.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.
@@ -47,7 +47,7 @@ The user may want more than one profile - a simple one and an orchestration one,
47
47
 
48
48
  ## Start small; editing is how a profile grows
49
49
 
50
- A first profile carries only what this interview actually surfaced. A new simple profile is `posture.md` plus a short `runbook.md` written from the confirmed answers - not a copy of anything thicker. A new orchestration profile fills in the shipped orchestration template's placeholders from those same answers; it does not add sections nobody asked for. Depth comes from running this skill again later to edit, not from a bigger first pass. Do not add a mandatory extra `.md` file, a review tool, or a tracking artifact that nobody's answer called for.
50
+ A first profile carries only what this interview actually surfaced. A new simple profile is `posture.md` plus a short `runbook.md` written from the confirmed answers - not a copy of anything thicker. A new orchestration profile starts from the shipped orchestration files as they are. That base already says the lead assigns todo ids, supervises and accepts, and a worker never completes its own todo. The runbook spells out lanes, the brief, scope, worktrees, shared resources, checks, review, permissions, waiting, the context checkpoint, handback and record, closing a lane and cold boot, and the posture sets the model tiers, so do not interview for any of them. The interview only fills its optional vars from confirmed answers and edits a rule the user wants changed; it does not add sections nobody asked for. Depth comes from running this skill again later to edit, not from a bigger first pass. Do not add a mandatory extra `.md` file, a review tool, or a tracking artifact that nobody's answer called for.
51
51
 
52
52
  ## Converge, then confirm once
53
53
 
@@ -82,7 +82,11 @@ An edit changes only the rule that was discussed and any dependent instruction t
82
82
 
83
83
  ## Route project facts into `hive.yml` `vars`, not prose
84
84
 
85
- A command, a repository name, a ticket prefix: these belong in `hive.yml` `vars` and get referenced from the profile as `{{var}}`, not hard-coded into the generated `posture.md`/`runbook.md`/`worker.md` text. This is what lets one profile serve several projects. `references/interview.md` lists the `hive.yml` keys and var names this skill knows how to write, and which existing shipped vars (`check`, `repo`, `install`, `ticket_prefix`, `start_command`) to reuse before introducing a new one.
85
+ A command, a repository name, a ticket prefix: these belong in `hive.yml` `vars` and get referenced from the profile as `{{var}}`, not hard-coded into the generated `posture.md`/`runbook.md`/`worker.md` text. This is what lets one profile serve several projects. `references/interview.md` lists the `hive.yml` keys and var names this skill knows how to write. The shipped orchestration profile renders these optional vars: `check`, `install`, `repo`, `ticket_prefix`, `start_command`, `test_command`, `suite_command`, `verify_command`, `review_command` and `worker_model`. Offer one only when the interview confirmed its value, and leave the rest unset: an unset var drops its section, and nothing makes the user fill every one.
86
+
87
+ ## Worked examples, only on request
88
+
89
+ `references/examples/README.md` indexes two worked examples: one orchestration profile rendered for a personal repo and a work repo, and an annotated skeleton of the three files. Open one only when the user asks to see an example or wants to adapt one. They are not part of discovery and add no interview question.
86
90
 
87
91
  ## Offer a recipe only on its own signal
88
92
 
@@ -90,7 +94,7 @@ A command, a repository name, a ticket prefix: these belong in `hive.yml` `vars`
90
94
 
91
95
  ## Validate before you tell them it's done
92
96
 
93
- After writing, run `hive doctor` and read each file you touched with "Read a rendered file in bounded sections" above, from the project the profile is meant to serve. Read it to the last line: a change near the end of a large file is easy to miss. A profile with no readable `runbook.md` fails `hive doctor` outright; `posture.md` and `worker.md` do not, but check them anyway. Tell the user to restart any running hive session so it picks up the change, and invite one small follow-up edit once they've tried it - that is the expected way a profile keeps improving.
97
+ After writing, run `hive doctor` and read each file you touched with "Read a rendered file in bounded sections" above, from the project the profile is meant to serve. Read it to the last line: a change near the end of a large file is easy to miss. Read worker text with `hive profile read worker.md`, never `hive posture`: `hive posture` prints the lead's file only. `worker.md` keeps its identity placeholders (`{{agent_name}}` and the like) in that read because they fill at spawn, so do not treat them as a defect. A profile with no readable `runbook.md` fails `hive doctor` outright; `posture.md` and `worker.md` do not, but check them anyway. Tell the user to restart any running hive session so it picks up the change, and invite one small follow-up edit once they've tried it - that is the expected way a profile keeps improving.
94
98
 
95
99
  ## After a profile edit lands, ask once about notifying leads
96
100
 
@@ -100,6 +104,10 @@ For each matching project, call `agent_list` with `{project_id: <project id>}`.
100
104
 
101
105
  On no, send nothing. On yes, call `wake_set` once per qualifying lead with `delay_seconds: 1`, `project_id: <that project's integer id>`, and `deliver_to: <lead's integer agent_id>`. Do not pass an actor id such as `lead:663` as `deliver_to`. Each wake body names the changed files and commit range, then tells the lead to re-read with `hive posture`, `hive runbook`, and `hive profile read <file>`, or restart through `hive lead` to reload the posture. Do not send a wake before the human says yes.
102
106
 
107
+ ## Without the Claude plugin
108
+
109
+ The plugin only delivers this skill and the `/hive:profile` trigger. A stock Codex user, or anyone without the plugin, follows the same steps by hand: open this file and `references/interview.md` (they ship in the npm package: for a global install the directory is `$(npm root -g)/@cmgmyr/hive/claude-plugin/skills/profile/`, and in a checkout it is `claude-plugin/skills/profile/`), then run the interview in any session. Every command here is a plain `hive` CLI call (`hive profile list`, `path`, `read`, `fork`, `hive doctor`, `hive posture`, `hive runbook`), and the profiles are ordinary markdown. Three parts are Claude-only or harness-specific: the `/hive:profile` trigger, a subagent for reading transcripts (do it inline in a harness with none, in small batches), and Claude Code's transcript location (Codex's rollout path is named above). The notify-leads step uses hive's own MCP tools, so it works wherever hive is registered.
110
+
103
111
  ## What this skill does not do
104
112
 
105
- It does not dispatch project work, change which agent application or model a project uses beyond what was explicitly asked, install a third-party tool, or commit or publish anything. It edits `hive.yml`'s `profile`, `agents`, `vars`, `context_checkpoint_percent`, and `lead_turn_budget` keys only on an explicit ask, and only to values the user gave or confirmed.
113
+ It does not dispatch project work, change which agent application or model a project uses beyond what was explicitly asked, install a third-party tool, or commit or publish anything. It does not choose a model name for the user: `worker_model` is written only to a value they gave. It edits `hive.yml`'s `profile`, `agents`, `vars`, `context_checkpoint_percent`, and `lead_turn_budget` keys only on an explicit ask, and only to values the user gave or confirmed.
@@ -0,0 +1,26 @@
1
+ # Worked examples
2
+
3
+ Open one of these only when the user asks to see an example or wants to adapt one. Do not open them during discovery, and do not add an interview question to reach them. The interview in `../interview.md` stays the way a profile gets built.
4
+
5
+ | File | What it shows | Open it when |
6
+ |---|---|---|
7
+ | [two-projects.md](two-projects.md) | One orchestration profile and two `hive.yml` files, a personal repo and a work repo. Every "rendered" block is real output from the shipped profile. | The user asks how one profile differs per project, or what `vars` do. |
8
+ | [skeleton.md](skeleton.md) | The three profile files cut down to their seams: who dispatches, where review lands, what a brief carries, which facts belong in `vars`. | The user wants a different method and needs the places where it would diverge. |
9
+
10
+ ## What they are not
11
+
12
+ - They are illustrations to read and adapt. hive never forks, runs or injects them. `posture.md`, `runbook.md` and `worker.md` are the three files hive loads on its own. Any other `.md` in a profile directory renders its `{{vars}}` only when read with `hive profile read <file>.md`.
13
+ - The projects in them are invented. Nothing is copied from a real setup.
14
+ - A rendered block is checked by `test/profile-examples.test.mjs`, which renders the shipped orchestration profile with the example's `hive.yml` and fails when a block no longer matches. If the shipped profile changes, regenerate the block from the real output; do not edit it by hand.
15
+
16
+ ## Every example assumes
17
+
18
+ - hive is installed and the project is a git repository registered with `hive init`.
19
+ - One stock harness (Claude Code or Codex) and nothing else: no extra skills, plugins, CI, tracker tooling or scripts.
20
+ - Commands such as `npm test` are placeholders for the user's own. A var left unset drops its section; nothing is required.
21
+
22
+ If the user has none of this, use the simple profile instead.
23
+
24
+ ## Trust
25
+
26
+ `hive.yml` `vars` land in the lead's posture and every worker's brief with no approval step. Read a cloned repo's `hive.yml` the way you would read its `CLAUDE.md`.
@@ -0,0 +1,127 @@
1
+ # Annotated skeleton
2
+
3
+ This example assumes what `README.md` lists: hive, git and one stock harness. It is a skeleton, not the shipped text. Each section keeps its heading and one line saying what it holds; the real wording is in `profiles/orchestration/`. Use it to see where a different method would diverge. hive loads exactly three files on its own; any other `.md` in a profile directory renders its `{{vars}}` when read with `hive profile read <file>.md`.
4
+
5
+ Template syntax: `{{var}}` fills from `hive.yml` `vars`. `<!--if:var-->` ... `<!--end-->` keeps a section only when the var is set. Edit the raw template (`hive profile path <name> <file>`), and read what an agent sees with `hive profile read <file>`.
6
+
7
+ ## posture.md
8
+
9
+ Rendered into every lead's system prompt. Keep it the smallest file.
10
+
11
+ ```markdown
12
+ You are the lead of a hive crew. <one sentence: you hold the plan, workers do the work, you accept.>
13
+
14
+ - Name the lane before acting. <the lane kinds, one line on why each ends differently>
15
+ - Ambiguity is a question, not a guess.
16
+ - Dispatch by assigning todo ids. <why: nobody self-dispatches>
17
+ - Give a worker a brief it can follow cold. <the brief's fields, see THE BRIEF below>
18
+ - Keep every lane isolated. <worktree per writer, lease per shared runtime>
19
+ - Read the real diff and run the change before you accept it.
20
+ - Only you complete a todo, and only after you accept it.
21
+ - Outward-facing actions need authority already given.
22
+ - Run yourself on the strongest model tier, workers on a cheaper one.
23
+ <!--if:worker_model-->
24
+ - Default worker model: {{worker_model}}.
25
+ <!--end-->
26
+ - When asked how work runs here, run `hive runbook`.
27
+ ```
28
+
29
+ SEAMS: who dispatches (the lead, by todo id) and who accepts (the lead) are fixed here. A method where a human steers each worker changes those two lines and the matching lines in `worker.md`.
30
+
31
+ ## runbook.md
32
+
33
+ Read on demand, not loaded into every prompt. Order is the method.
34
+
35
+ ```markdown
36
+ RUNBOOK: how work runs here. Live state belongs in todos, not in this file.
37
+
38
+ THE ONE RULE
39
+ <the single invariant, stated with the failure it prevents>
40
+
41
+ LANES
42
+ <one bullet per lane: what it ends with>
43
+ <!--if:ticket_prefix-->
44
+ - Ticket ({{ticket_prefix}}-NNN): <link, do not copy>
45
+ <!--end-->
46
+
47
+ HOW A LANE RUNS
48
+ 1. <read the request, name the lane and who accepts>
49
+ 2. <write the brief>
50
+ 3. <prepare the worktree and shared runtime>
51
+ 4. <spawn with agent_spawn: cwd, name, model> <!--if:worker_model-->Worker model: {{worker_model}}.<!--end-->
52
+ 5. <read comments, diff, agent_output; run it yourself; triage findings>
53
+ 6. <reconcile with base, rerun affected checks>
54
+ 7. <accept, close out, record the next action>
55
+
56
+ THE BRIEF
57
+ <fields in order: goal, decisions made, files owned, input limits, base and worktree, checks and done-means, reviewer and acceptor, publish authority, open questions>
58
+
59
+ SCOPE | WORKTREES | SHARED RESOURCES | CHECKS | REVIEW | PERMISSIONS | WAITING
60
+ <each a short block: the rule, then the failure it prevents>
61
+ <!--if:install-->
62
+ - A fresh worktree has no dependencies installed: {{install}}
63
+ <!--end-->
64
+
65
+ CHECKS (inside it)
66
+ <!--if:check-->
67
+ - Gate command: {{check}}
68
+ <!--end-->
69
+ <!--if:test_command-->
70
+ - Scoped checks: {{test_command}}
71
+ <!--end-->
72
+ <!--if:suite_command-->
73
+ - Full suite: {{suite_command}}
74
+ <!--end-->
75
+
76
+ REVIEW (inside it)
77
+ <when a fresh-context reviewer runs; keep findings raw; record fix, accept or defer>
78
+ <!--if:review_command-->
79
+ - This project's review command: {{review_command}}
80
+ <!--end-->
81
+
82
+ CONTEXT CHECKPOINT | HANDBACK AND RECORD | CLOSING A LANE | COLD BOOT
83
+ <each a short block>
84
+ ```
85
+
86
+ SEAMS: review lands in REVIEW and in step 5; a method that reviews before the worker commits moves it to step 4. The brief's fields are where a method says what a worker must be told. Any project-specific command goes in a `vars` entry and a gated line, never in prose, so one profile serves several repos.
87
+
88
+ ## worker.md
89
+
90
+ Rendered into every worker's first prompt. Identity placeholders (`{{agent_name}}`, `{{actor_id}}`, `{{project_name}}`, `{{project_path}}`, `{{cwd}}`, `{{primary_root}}`) fill at spawn, not from `hive.yml`.
91
+
92
+ ```markdown
93
+ [HIVE CONTEXT]
94
+ You are agent "{{agent_name}}" (actor id: {{actor_id}}) in project "{{project_name}}" ({{project_path}}).
95
+ Your working directory is {{cwd}}.
96
+ <the hive tools the worker may use: whoami, pad_read, todo_get, todo_comment, lease_acquire>
97
+ [END HIVE CONTEXT]
98
+
99
+ SCOPE | YOUR FILES AND YOUR STORE | CHECKS
100
+ <each a short block, as in the runbook>
101
+ <!--if:install-->
102
+ <install line>
103
+ <!--end-->
104
+
105
+ BEFORE YOU REPORT DONE, in this order.
106
+ 1. <status in the worktree>
107
+ 2. <rebuild>
108
+ 3. <rerun scoped checks>
109
+ <!--if:check-->
110
+ Also run this project's gates: {{check}}
111
+ <!--end-->
112
+ 4. <commit; do not push; publish only where the brief grants it>
113
+ 5. <post reader findings raw, report on the todo, wait for the lead>
114
+
115
+ WAIT FOR EVERYTHING YOU START | IF YOU HIT YOUR CONTEXT CHECKPOINT
116
+ <each a short block>
117
+ ```
118
+
119
+ SEAMS: the worker never completes its own todo and never publishes unless the brief grants it. The gate is an unnumbered line under the scoped-checks step, so the numbering is the same with `check` set or unset.
120
+
121
+ ## Which facts go in vars
122
+
123
+ | Put in `vars` | Leave in prose |
124
+ |---|---|
125
+ | a command (`install`, `test_command`, `suite_command`, `check`, `verify_command`, `review_command`) | how and why a rule exists |
126
+ | a name (`repo`, `ticket_prefix`, `worker_model`) | the order of steps |
127
+ | anything that differs between two repos | anything true for every repo |
@@ -0,0 +1,105 @@
1
+ # One profile, two projects
2
+
3
+ This example assumes what `README.md` lists: hive, git and one stock harness. The projects are invented.
4
+
5
+ Both projects use the shipped orchestration profile unchanged. Only `hive.yml` `vars` differ, so the same three template files read differently in each repo. An unset var drops its section; a set one fills a placeholder or opens a section.
6
+
7
+ ## Project A: a personal repo
8
+
9
+ Install and a scoped test command. No tracker, no suite, no review command.
10
+
11
+ ```yaml hive.yml personal
12
+ profile: orchestration
13
+ vars:
14
+ install: npm install
15
+ test_command: npm test -- test/<file>.test.js
16
+ ```
17
+
18
+ What the lead's runbook says (`hive runbook`):
19
+
20
+ ```text rendered personal runbook
21
+ - Use absolute paths in edits and `git -C <worktree>`. A relative path after a `cd` resolves against the wrong tree.
22
+ - A fresh worktree has no dependencies installed: npm install
23
+ ```
24
+
25
+ ```text rendered personal runbook
26
+ CHECKS
27
+ Run the named checks. A green summary or a stale build is not a working result.
28
+ - Scoped checks: npm test -- test/<file>.test.js
29
+ ```
30
+
31
+ What a worker sees (`hive profile read worker.md`). With no `check` var set, the scoped-checks step has no gate line under it:
32
+
33
+ ```text rendered personal worker
34
+ 2. Rebuild before any screenshot, browser check, or measurement.
35
+ 3. Run the scoped checks again after your last edit, and the full suite once if the brief asks for it.
36
+ 4. Commit; do not push. Research lanes record findings on the todo and need no commit. Publish only where the brief grants it; otherwise ask the lead.
37
+ ```
38
+
39
+ ## Project B: a work repo
40
+
41
+ A ticket prefix, a gate, a full suite, a review command and a worker model.
42
+
43
+ ```yaml hive.yml work
44
+ profile: orchestration
45
+ vars:
46
+ ticket_prefix: PAY
47
+ check: make lint test
48
+ suite_command: make ci
49
+ review_command: /review
50
+ worker_model: the gateway's mid-size tier
51
+ ```
52
+
53
+ The lead's posture gains one line:
54
+
55
+ ```text rendered work posture
56
+ - Default worker model: the gateway's mid-size tier.
57
+ ```
58
+
59
+ The runbook gains a ticket lane, a worker model, a gate, a suite and a review command:
60
+
61
+ ```text rendered work runbook
62
+ - Ticket (PAY-NNN): link the ticket from the todo. Do not copy its body, or the two drift apart. Name who updates the ticket and which states they set.
63
+ ```
64
+
65
+ ```text rendered work runbook
66
+ Worker model: the gateway's mid-size tier.
67
+ ```
68
+
69
+ ```text rendered work runbook
70
+ - Gate command for this project: make lint test
71
+ - Full suite: make ci. Run it once before handback and again after a rebase.
72
+ ```
73
+
74
+ ```text rendered work runbook
75
+ - This project's review command: /review
76
+ ```
77
+
78
+ The worker's report-done list gets a gate line under the scoped-checks step, and the numbering does not change:
79
+
80
+ ```text rendered work worker
81
+ 3. Run the scoped checks again after your last edit, and the full suite once if the brief asks for it.
82
+ Also run this project's gates and fix what they find: make lint test
83
+ 4. Commit; do not push. Research lanes record findings on the todo and need no commit. Publish only where the brief grants it; otherwise ask the lead.
84
+ ```
85
+
86
+ ## What to change for your project
87
+
88
+ 1. List what your project actually has: an install step, a scoped test command, a full suite, a gate, a review command, a ticket prefix, a remote.
89
+ 2. Write only those into `hive.yml` `vars`. Use the names in the examples; the shipped profile renders `check`, `install`, `repo`, `ticket_prefix`, `start_command`, `test_command`, `suite_command`, `verify_command`, `review_command` and `worker_model`.
90
+ 3. Do not set a var you cannot fill. Leave it out.
91
+ 4. Set `worker_model` only to a model the user named.
92
+ 5. Read the result: `hive runbook`, `hive posture`, and `hive profile read worker.md`.
93
+ 6. Run `hive doctor` and restart any running lead so it reloads.
94
+
95
+ To change a rule itself, fork first: `hive profile fork orchestration`, then edit the files under `hive profile path orchestration`.
96
+
97
+ ## Paste-ready prompt
98
+
99
+ ```text
100
+ I use hive with the shipped orchestration profile. Here is my project: <one line on what it is>.
101
+ Commands I actually run: install = <cmd or none>, scoped tests = <cmd or none>, full suite = <cmd or none>, lint/gate = <cmd or none>, review = <cmd or none>.
102
+ Ticket prefix: <PREFIX or none>. Remote: <owner/name or none>.
103
+ Write a hive.yml for this repo with `profile: orchestration` and a `vars:` block holding only the commands above that are not "none". Do not invent commands.
104
+ Then run `hive runbook`, `hive posture` and `hive profile read worker.md` and tell me which sections appeared and which dropped. Do not edit the profile files.
105
+ ```
@@ -14,6 +14,13 @@ For an edit, open with "What should change, and what should stay?" and read the
14
14
 
15
15
  **Simple** fits one active agent, sequential tasks, the user directly controlling the work, or a case where coordinating several sessions would cost more than it saves. **Orchestration** fits someone who already delegates, needs independent work to run in parallel, or names a concrete coordination problem they are trying to solve. Treat both as signals to weigh, never as a rule to apply mechanically.
16
16
 
17
+ **What the orchestration base already settles.** The shipped orchestration files are written outright, with no mode var to switch on. The lead assigns todo ids, supervises and accepts; workers never self-dispatch and never complete their own todo; a brief names goal, decisions, files, base, checks and done-means; scope stops go to the lead; each lane has its own worktree and a lease on any shared runtime; the lead reads the real diff and runs the change; a fresh-context review runs by risk or on request, never on every change; pushes, PRs and posts need standing authority; a handback and a record live on the todo; the lead runs on the strongest model tier and workers on a cheaper one. A follow-up question on any of these is wasted unless the user's answer pushes against it, and then it is an edit to that rule, not a new section.
18
+
19
+ **Three synthetic walk-throughs, each inside the budget** (illustrations, not real interviews). Each converges in at most six discovery questions plus three follow-ups, and none needs a question beyond the map below.
20
+ - A solo user with personal repos, one stock harness and no tracker, CI or suite: no preference for delegation, so recommend simple. Dimensions asked: 12 (what done means), 15 (which command, or a stated manual check). No var beyond `check`, if they name one.
21
+ - A user in work repos with a hosted tracker, CI and required human PR review: recommend orchestration only if they say they delegate. Dimensions asked: 14 (tracker), 13 and 09 (who pushes and posts; human PR review stays required), 15. Vars: `ticket_prefix`, `start_command` if they run one, `repo`, `check`. Do not mirror the ticket body into todos, and do not add a model var for a gateway-routed setup.
22
+ - Two harnesses on a shared project with one suite and one dev database: recommend orchestration, since they name a coordination problem. Dimensions asked: 16, 15, 24. Vars: `suite_command`, `test_command`; `install` only if they name a setup step. The shipped SHARED RESOURCES rule covers the resource; the shared-test-resource recipe is offered only if they want a named coordinator.
23
+
17
24
  Summarise your recommendation with one reason tied to what the user said, and offer the other route without framing it as an upgrade or a downgrade. No stated preference means recommend simple, as the smaller thing to start from, while noting delegation is available later through an edit. If different kinds of project the user described need conflicting policies, offer separate profiles for them; do not offer several profiles just because both bases exist. Share discovery once, then confirm each profile's own differences and its selection separately.
18
25
 
19
26
  ## 3. Optional follow-up map
@@ -46,7 +53,7 @@ Every row below is optional. A row with no answer signal in what the user alread
46
53
  | 22 | Runtime verification | Green checks have missed a real failure before. | What real action demonstrates the change actually works? | The outcome the user described, exercised with a realistic input. | hive.yml vars, runbook.md |
47
54
  | 23 | Visual evidence | The project has a visible interface. | Which visible states do you need to see before accepting a change? | Only the states relevant to this project. | hive.yml vars, runbook.md |
48
55
  | 24 | Agent applications | More than one agent application is already in use. | Which applications are available, and which can use your tools? | Keep whatever is already working for the user. | top-level hive.yml `agents` |
49
- | 25 | Model selection | The user has a model preference. | Do you want a default model, or to choose one per task? | Keep current settings; propose no model ranking of your own. | posture.md, runbook.md |
56
+ | 25 | Model selection | The user has a model preference. | Do you want a default model, or to choose one per task? | Keep current settings; propose no model ranking of your own. | hive.yml vars (`worker_model`), posture.md, runbook.md |
50
57
  | 26 | Model identifiers | The user's setup routes models by a custom name. | Does your installed application expect an alias, or an exact identifier? | Use an identifier the user has verified works. | top-level hive.yml `lead`, runbook.md |
51
58
  | 27 | Reasoning effort | The user has an effort preference. | Should tasks inherit the default effort, or use a level you choose? | Inherit current settings. | top-level hive.yml `lead`, runbook.md |
52
59
  | 28 | Escalation | A session repeatedly gets stuck. | When do you want a fresh session, or a different model? | Return a blocked choice to the user. | runbook.md, worker.md |
@@ -119,14 +126,29 @@ When selecting one project's `profile:` key in `hive.yml`, treat each project's
119
126
 
120
127
  - `profile: <name>` selects the profile; write it to the project's own `hive.yml` for "this project", or to `~/.hive/hive.yml` only on an explicit ask for "every project" (see Scope, above).
121
128
  - `agents: [<harness>, ...]` selects which agent applications this project allows; write it only when the user names more than the default.
122
- - `vars:` holds project facts referenced as `{{var}}` from the profile's own text - reuse shipped names before inventing one: `check` (the before-you-report-done gate), `repo`, `install`, `ticket_prefix`, `start_command`. This lane's own additions, each a plain string substituted into prose and never executed by hive itself, are: `test_command` (scoped tests), `suite_command` (the full suite), `verify_command` (a real, observable outcome check), and `review_command` (an existing review the user already runs). Write one only when a generated template actually references it - an unreferenced var is dead weight, not a feature.
129
+ - `vars:` holds project facts referenced as `{{var}}` from the profile's own text - reuse the shipped names before inventing one. Each is a plain string substituted into prose and never executed by hive itself, and each is optional: an unset var drops its section from the render. The shipped orchestration profile renders exactly these ten, and this skill offers each only on a confirmed signal:
130
+
131
+ | Var | Holds | Signal (dimension) |
132
+ |---|---|---|
133
+ | `check` | the before-you-report-done gate | the user names one command that proves readiness (15) |
134
+ | `test_command` | scoped checks for one change | they name a smaller command (15) |
135
+ | `suite_command` | the full suite | they name one, often alongside a shared resource (15, 16) |
136
+ | `verify_command` | a real, observable outcome check | green checks have missed a failure before (22) |
137
+ | `review_command` | a review the user already runs | they run an installed review tool (18, 19) |
138
+ | `worker_model` | the cheaper model tier workers spawn on | they name a model they want workers on (25) |
139
+ | `install` | dependency setup for a fresh worktree | the user names a setup step a fresh checkout needs |
140
+ | `repo` | the project's remote | a remote is in use (09) |
141
+ | `ticket_prefix` | a ticket id prefix, linked from the todo | a tracker is in use (14) |
142
+ | `start_command` | how ticket work starts; rendered only under `ticket_prefix` | they have a start routine for tickets (14, 40) |
143
+
144
+ `worker_model` is a value the user gave or confirmed, never a name you pick. Write a var only when a template actually references it; an unreferenced var is dead weight, not a feature. On a simple profile, only `check` is meaningful unless the user's own runbook references another.
123
145
  - `context_checkpoint_percent` (an integer from 1 to 100) and `lead_turn_budget` (a `{warn, stop}` pair, `stop` greater than `warn`) are optional and written only when the user asks for them.
124
146
 
125
147
  Never write a `hive.yml` key this skill does not know, and never invent a model name, an effort flag, a reserved identity var, or an `agents_*` / `harness_*` var - those are hive's own, computed at spawn time, and a project-defined one is stripped before it ever reaches a template.
126
148
 
127
149
  ## 5. Recipes
128
150
 
129
- `recipes/index.md` links a small library of optional patterns, each tied to one or more dimensions above: verification (15, 17, 22), a shared test resource (16, 15), a review decision (18-21), session continuity (33, 40, 35), and a worker context checkpoint (30, 28, orchestration only). Read the matching recipe when its dimension's signal shows up in discovery; it is never a required stop on the way to a first profile.
151
+ `recipes/index.md` links a small library of optional patterns, each tied to one or more dimensions above: verification (15, 17, 22), a shared test resource (16, 15), a review decision (18-21), session continuity (33, 40, 35), and a worker context checkpoint (30, 28, orchestration only). Read the matching recipe when its dimension's signal shows up in discovery; it is never a required stop on the way to a first profile. On the shipped orchestration base, several recipes are mostly a var away because the base already renders the section (checks, review, shared resources, checkpoint); each recipe says what to set and when a block is still worth adding. Recipes keep their five-recipe count; the orchestration changes add no recipe.
130
152
 
131
153
  ## Known traps
132
154
 
@@ -10,3 +10,4 @@ A recipe is an optional pattern a profile can adopt: a short, named block of tex
10
10
  | [session-continuity.md](session-continuity.md) | A reopened session repeats decisions or loses the next action. | A small finish/start habit that carries the next action across sessions. | Both |
11
11
  | [worker-context-checkpoint.md](worker-context-checkpoint.md) | Delegated work runs long enough that a worker loses useful context. | A checkpoint threshold and a designated recipient who decides whether to continue. | Orchestration only |
12
12
 
13
+ Worked examples, not recipes: [../examples/README.md](../examples/README.md). Open one only when the user asks to see or adapt one.
@@ -14,6 +14,8 @@ Where useful review already happens today, and who should decide whether a findi
14
14
 
15
15
  ## Add
16
16
 
17
+ The shipped orchestration runbook already has a REVIEW section: the lead reads the real diff, runs a fresh-context reviewer by risk or on request, keeps findings as written, and renders `review_command` when it is set. On that base, set `review_command` if the user runs a real tool, and add the block below only to name a decision owner other than the lead.
18
+
17
19
  A runbook block naming the reviewer, the timing, and the decision owner:
18
20
 
19
21
  ```markdown
@@ -14,6 +14,8 @@ The name of the actual shared resource (a database, a port, a device) and who or
14
14
 
15
15
  ## Add
16
16
 
17
+ The shipped orchestration runbook already has a SHARED RESOURCES section (name the runtime, take a lease, one full check at a time, the lead gives out the slot). That section is unconditional prose and renders no var; `suite_command` renders under CHECKS. On that base, set `suite_command` and add the block below only to name a coordinator other than the lead.
18
+
17
19
  A runbook rule naming the resource and the coordination habit:
18
20
 
19
21
  ```markdown
@@ -28,7 +28,7 @@ Report a failing result as failing. A clean status line is not evidence by
28
28
  itself.
29
29
  ```
30
30
 
31
- For orchestration, add the same obligation to `worker.md`'s completion section rather than only the lead's runbook, since it is the worker who reports done.
31
+ On the shipped orchestration base, the runbook's CHECKS section already renders `check`, `test_command` and `verify_command` when they are set, and `worker.md` already asks for the named checks before a handback. So there, set the vars and add this block only if the user's own runbook lacks a completion step. For a forked or hand-written orchestration profile, add the same obligation to `worker.md`'s completion section rather than only the lead's runbook, since it is the worker who reports done.
32
32
 
33
33
  ```yaml
34
34
  vars:
@@ -38,7 +38,7 @@ vars:
38
38
 
39
39
  ## Verify
40
40
 
41
- Run `hive runbook` (and `hive posture` for the worker copy, on orchestration) and confirm both commands render. Then exercise it for real: pick a harmless, already-working change and confirm the block actually gets run and its result gets reported, not just written down.
41
+ Run `hive runbook` and confirm both commands render. On orchestration, also run `hive profile read worker.md` and confirm the worker text carries the check obligation. Never use `hive posture` for the worker copy: it prints the lead's file only. Then exercise it for real: pick a harmless, already-working change and confirm the block actually gets run and its result gets reported, not just written down.
42
42
 
43
43
  ## Remove
44
44
 
@@ -14,6 +14,8 @@ A context-fill threshold (a percentage), and who should receive a checkpoint and
14
14
 
15
15
  ## Add
16
16
 
17
+ The shipped orchestration runbook and `worker.md` already carry a context-checkpoint section, active wherever `context_checkpoint_percent` is set. On that base, writing the key is the whole recipe; add the blocks below only to name a recipient other than the lead. A forked profile without that section needs them.
18
+
17
19
  `context_checkpoint_percent` at the top level of `hive.yml`:
18
20
 
19
21
  ```yaml
@@ -1 +1 @@
1
- {"version":"1.7.0","sha":"2000149","dirty":false,"build_id":"c539d81be530294a451590d781bd6922cd7155087a70b8fc64dedc35cf94f3e2"}
1
+ {"version":"1.9.0","sha":"b0be61b","dirty":false,"build_id":"b0c86484d75006efe978e316cdbccb3c9b4e09604634cfff5f7a61c8b8d825b0"}
@@ -0,0 +1,44 @@
1
+ import { createConnection } from "node:net";
2
+ export const CROSS_SESSION_CLOSE = "</cross-session-message>";
3
+ export const SOCKET_WAKE_FOOTER = "Automated hive wake. Do not reply to this sender.";
4
+ const SOCKET_WRITE_BOUND_MS = 1000;
5
+ export function senderAddress(socketPath) {
6
+ const encoded = socketPath.replace(/[^A-Za-z0-9/._-]/gu, (c) => [...Buffer.from(c)].map((b) => `%${b.toString(16).toUpperCase().padStart(2, "0")}`).join(""));
7
+ return `uds:${encoded}`;
8
+ }
9
+ function claudeWakeFrame(senderAddress, text) {
10
+ const content = `<cross-session-message from="${senderAddress}" from-name="hive">\n${text}\n${CROSS_SESSION_CLOSE}`;
11
+ return JSON.stringify({ type: "user", from: senderAddress, message: { role: "user", content } }) + "\n";
12
+ }
13
+ // True only for a completed local write. The socket sends no ack, so true never means the lead read it.
14
+ export function postClaudeWake(options) {
15
+ return new Promise((resolve) => {
16
+ let settled = false;
17
+ const finish = (ok) => {
18
+ if (settled)
19
+ return;
20
+ settled = true;
21
+ clearTimeout(timer);
22
+ if (ok)
23
+ socket.end();
24
+ else
25
+ socket.destroy();
26
+ resolve(ok);
27
+ };
28
+ const socket = createConnection(options.socketPath);
29
+ const timer = setTimeout(() => finish(false), SOCKET_WRITE_BOUND_MS);
30
+ socket.on("error", () => finish(false));
31
+ socket.on("connect", () => {
32
+ let allowed = false;
33
+ try {
34
+ allowed = options.beforeWrite();
35
+ }
36
+ catch {
37
+ allowed = false;
38
+ }
39
+ if (!allowed)
40
+ return finish(false);
41
+ socket.write(claudeWakeFrame(options.senderAddress, options.text), (err) => finish(!err));
42
+ });
43
+ });
44
+ }
package/dist/cli.js CHANGED
@@ -20,16 +20,16 @@ import { isLowHeadroom, orphanLoginShellDetails, ptyHeadroom } from "./ptys.js";
20
20
  import { addProject, agentProjectPin, assertQueenCrossProjectWrite, captureQueenWriteIdentity, currentActor, effectiveProjectId, findProjectForCwd, findProjectForDir, getProjectByPath, gitPrimaryRoot, getProject, listProjects, QUEEN_PROFILE, queenHomeDir, registeredAncestor, takeRegistrationNotice, } from "./context.js";
21
21
  import { confirmQueenWrite, listQueenAudit } from "./queenAudit.js";
22
22
  import { formatRowCounts, projectRowCounts, removeProject } from "./projectRemove.js";
23
- import { ensureHooksFile } from "./hooks.js";
23
+ import { ensureHooksFile, ensureLeadHooksFile } from "./hooks.js";
24
24
  import { errorMessage, registrationNoticeText, withTrailingNewline } from "./result.js";
25
- import { ACTIVE_TIMER_WHERE, dashboardFileContained, describeStall, HELD_REASON_CONVERSATION, HELD_REASON_LEAD_PANE_DEAD, HELD_REASON_UNCLASSIFIABLE_PANE_PREFIX, isLeadRowClosedHold, isUnclassifiablePaneHold, HELD_REASON_UNSUBMITTED_INPUT_PREFIX, isUnsubmittedInputHold, janitor, resolveDashboardFile, generateQueenDashboardNow, transcriptStaleness, wasHeldForPaneIdentity, } from "./scheduler.js";
25
+ import { ACTIVE_TIMER_WHERE, socketAwaitingWhere, dashboardFileContained, describeStall, HELD_REASON_CONVERSATION, HELD_REASON_LEAD_PANE_DEAD, HELD_REASON_UNCLASSIFIABLE_PANE_PREFIX, isLeadRowClosedHold, isUnclassifiablePaneHold, HELD_REASON_UNSUBMITTED_INPUT_PREFIX, isUnsubmittedInputHold, janitor, resolveDashboardFile, generateQueenDashboardNow, transcriptStaleness, wasHeldForPaneIdentity, } from "./scheduler.js";
26
26
  import { readTurnCount } from "./turnCount.js";
27
27
  import { collectPortfolio, leadText } from "./portfolio.js";
28
28
  import { STALL_BOUND_SECONDS } from "./backgroundTasks.js";
29
29
  import { probeSessionInterpreter, reexecTarget, sessionStartVerdict, } from "./sessionProbe.js";
30
30
  import { backupHealth, backupNow, backupsDir, formatBytes, listSnapshots, previewRestore, restoreSnapshot, totalSizeBytes, } from "./backup.js";
31
31
  import { describeTeardownWindow, readTeardowns, teardownLogPath, } from "./teardown.js";
32
- import { asNameClash, buildEnvFlags, closeAgentRow, isReservedAgentName, launchAgent, LEAD_KIND, LEAD_NAME, mintLeadActorId, upsertActor, withWindowClaim, } from "./spawn.js";
32
+ import { asNameClash, buildEnvFlags, closeAgentRow, isReservedAgentName, launchAgent, LEAD_KIND, LEAD_NAME, mintLeadActorId, relayoutAfterPaneLeft, upsertActor, withWindowClaim, } from "./spawn.js";
33
33
  import { adoptableWindow, applyLayout, claimInitialWindow, configureHiveWindow, controlModeFor, createWindow, DEFAULT_LAYOUT, describePaneChoice, ensureSession, findProjectWindow, foreignSocket, isViewSessionName, listOwnedWindows, liveTargets, observationFailed, observeRowOwnership, ORPHAN_MIN_AGE_MS, orphanScratchServers, orphansWorthWarningAbout, paneIsAloneInWindow, paneVisibility, panePidForRecord, PROCESSES_LAYOUT, processesPaneTitle, processesWindowName, projectWindows, RAW_ATTACH_TMUX_CONFIG, renderAttachCommand, resolveAttachTarget, resolveInTmuxTarget, rowLive, rowOwnership, SESSION_PREFIX, appendGlobalHook, globalHooks, replaceGlobalHooks, sessionName, setPaneTitle, shellQuote, shownPaneTitle, makeProcessesWindow, tmux, TMUX_DOC, tmuxSaysNothingThere, tmuxTimeoutOverride, tmuxSocketPath, untrustedTmuxServer, waitForPaneEstablished, windowLayout, } from "./tmux.js";
34
34
  import { describeVisibility, processCounts } from "./dashboard.js";
35
35
  import { runningCommandRow, runningCommandRows, snapshotProcesses, stopAllProcesses, stopLine, stopProcess, STOP_REASONS, } from "./processes.js";
@@ -400,7 +400,7 @@ async function cmdLead(argv) {
400
400
  for (const w of warnings)
401
401
  console.log(`! ${w}`);
402
402
  const session = sessionName();
403
- const hooksPath = ensureHooksFile();
403
+ const hooksPath = ensureLeadHooksFile(project.id, config?.quiet_messaging === true);
404
404
  let leadCommand = "claude";
405
405
  if (!config) {
406
406
  console.log("No hive.yml here; starting a plain claude lead. Add a hive.yml to define project commands and a custom lead (run hive --help for the format).");
@@ -546,7 +546,9 @@ async function cmdLead(argv) {
546
546
  createdPane = true;
547
547
  }
548
548
  else {
549
- leadPane = tmux("split-window", ...(detach ? ["-d"] : []), "-P", "-F", "#{pane_id}", "-t", foundWindow, "-c", project.path, ...envFlags, launchCommand);
549
+ const firstPane = tmux("list-panes", "-t", foundWindow, "-F", "#{pane_id}").split("\n")[0];
550
+ leadPane = tmux("split-window", "-b", ...(detach ? ["-d"] : []), "-P", "-F", "#{pane_id}", "-t", firstPane || foundWindow, "-c", project.path, ...envFlags, launchCommand);
551
+ relayoutAfterPaneLeft(foundWindow);
550
552
  leadWindow = foundWindow;
551
553
  createdPane = true;
552
554
  }
@@ -601,7 +603,7 @@ async function cmdLead(argv) {
601
603
  if (updated === 0)
602
604
  return false;
603
605
  db.prepare(`UPDATE wakes SET deliver_pane = ?, held_at = NULL, held_reason = NULL
604
- WHERE ${ACTIVE_TIMER_WHERE} AND deliver_actor = ?
606
+ WHERE ((${ACTIVE_TIMER_WHERE}) OR (${socketAwaitingWhere()})) AND deliver_actor = ?
605
607
  AND (? = 1 OR held_reason IS NULL OR held_reason NOT LIKE ?)`).run(leadPane, leadActorId, createdPane ? 1 : 0, `${HELD_REASON_UNCLASSIFIABLE_PANE_PREFIX}%`);
606
608
  confirmQueenWrite("hive lead", project.id, { detach }, {
607
609
  agent_id: leadAgentId,
@@ -743,6 +745,8 @@ const HIVE_YML_TEMPLATE = `# hive project config. Read by \`hive lead\` from the
743
745
 
744
746
  # dashboard: true # write .hive/dashboard.html (default: false)
745
747
 
748
+ # quiet_messaging: true # wakes reach a claude lead as one row (default: false; restart the lead)
749
+
746
750
  # vars: # substituted into the profile runbook
747
751
  # repo: owner/name # {{repo}}
748
752
  # ticket_prefix: DEVX # sections needing it drop when it is unset
@@ -750,8 +754,13 @@ const HIVE_YML_TEMPLATE = `# hive project config. Read by \`hive lead\` from the
750
754
  # start_command: /jira-start
751
755
  # check: npm run lint && npx tsc --noEmit # what a worker runs before
752
756
  # reporting done; gates only,
753
- # no suite (test_all is that)
757
+ # no suite (suite_command is that)
754
758
  # check: ./vendor/bin/pint --test && ./vendor/bin/phpstan # a PHP stack's
759
+ # test_command: npm test -- test/foo.test.mjs # scoped check for one change
760
+ # suite_command: npm test # full suite; one run at a time, lead's slot
761
+ # verify_command: npm run build && node dist/cli.js --version # exercises the real outcome
762
+ # review_command: /review # a fresh-context reviewer, if your harness has one
763
+ # worker_model: sonnet # the cheaper tier workers spawn on
755
764
  # ci: weekly # absent: CI runs on push/PR. weekly: CI runs
756
765
  # on schedule + dispatch only, and the local
757
766
  # full suite gates the merge