cyberfleet 0.2.0 → 0.3.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.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cyberfleet",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "Fleet & crew personas over cyberlegion — Pod (ship's bridge), Operator (command center), Crimp (crew recruitment), and Mechanic (automaton building).",
5
5
  "author": {
6
6
  "name": "unional"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cyberfleet",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "Fleet & crew personas over cyberlegion — Pod (ship's bridge), Operator (command center), Crimp (crew recruitment), and Mechanic (automaton building).",
5
5
  "author": {
6
6
  "name": "unional"
@@ -34,6 +34,7 @@ while capacity K and ready:
34
34
  on mission-done(m): # m reports through its existing HANDOFF relay
35
35
  merge per merge-backstop-governance # Operation order + speculative-CI gate + bisect-on-red
36
36
  cyberlegion unit close <id> # tear down the pod that ran it (spawn's inverse)
37
+ mail every other open pod: trunk moved # rebase, adapt, re-verify, report (merge-backstop §5)
37
38
  mission-graph append (retire + discovered edges/nodes) # SINGLE WRITER
38
39
  # next `ready` reflects it -> re-derive on the next tick
39
40
  ```
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cyberfleet",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "Harness-agnostic, MCP-free inter-agent sessions and messaging over the filesystem",
5
5
  "keywords": [
6
6
  "agent",
@@ -40,7 +40,7 @@
40
40
  },
41
41
  "devDependencies": {
42
42
  "@types/node": "^24.10.1",
43
- "tsdown": "^0.22.0",
43
+ "tsdown": "^0.23.0",
44
44
  "tsx": "^4.22.3",
45
45
  "typescript": "^6.0.0",
46
46
  "vitest": "^4.1.7"
package/plugin.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json",
3
3
  "name": "cyberfleet",
4
- "version": "0.2.0",
4
+ "version": "0.3.0",
5
5
  "description": "Fleet & crew personas over cyberlegion — Pod (ship's bridge), Operator (command center), Crimp (crew recruitment), and Mechanic (automaton building).",
6
6
  "author": {
7
7
  "name": "unional"
@@ -23,6 +23,9 @@ project Captains when they land.
23
23
  inference from engagement or from work looking finished, no self-grant.
24
24
  - **Form and scope** — a relayed Council decision carries the verbatim words, where they were said, the
25
25
  relaying unit, and the action and target it covers; it is valid for nothing else.
26
+ - **Standing merge delegations** — summoning the headless loop for a tick, or ordering an in-session
27
+ Operator to dispatch pods, delegates merging exactly that work: clean pull requests only, merged by
28
+ the Operator itself, never passed to a pod, and never any other ratification-class action.
26
29
  - **No stall** — a missing decision means: do the rest, raise a decision-request, report both.
27
30
  - **Thread** — one thread per work item carries the brief, the reports, and the decisions with their
28
31
  relayer named.
@@ -116,15 +116,44 @@ The positive set. An Operator, a Captain, or a parent agent may command:
116
116
  - tear down a unit it dispatched, and sweep exited units — in both cases only where no unmerged work is
117
117
  being discarded (that is ratification-class, above);
118
118
  - and for the headless lifecycle loop, claim and retire on the mission graph as the single writer.
119
+ - and for an Operator the Council ordered in-session to dispatch pods, merge those pods' clean pull
120
+ requests under §7 — the Operator itself, never by commanding a pod to merge.
119
121
 
120
122
  Anything outside the set is declined and raised as a decision-request, not commanded.
121
123
 
122
- ## 7. The headless lifecycle loop
123
-
124
- The Council **summoning the loop for a tick** is what permits the loop to retire that tick's missions.
125
- The merge still lands only on green speculative CI on the merged result — `merge-backstop-governance`
126
- owns that order and land-or-hold discipline, and this governance does not touch it. The delegation
127
- covers the tick's missions and no other class of action: a release still needs its own decision.
124
+ ## 7. Standing merge delegations — the loop's tick, and the Operator's dispatch order
125
+
126
+ Two acts of the Council delegate merges without a decision per merge. Each covers **merging the work
127
+ it dispatched, and nothing else**.
128
+
129
+ **The headless lifecycle loop.** The Council **summoning the loop for a tick** is what permits the loop
130
+ to retire that tick's missions. The merge still lands only on green speculative CI on the merged
131
+ result — `merge-backstop-governance` owns that order and land-or-hold discipline, and this governance
132
+ does not touch it. The delegation covers the tick's missions and no other class of action: a release
133
+ still needs its own decision.
134
+
135
+ **The in-session Operator.** The Council ordering an Operator, **on a turn in the Operator's own
136
+ session**, to dispatch pods is what permits that Operator to merge **the pull requests of the pods it
137
+ spawned for that order**. It merges one only when it is **clean** — all four hold:
138
+
139
+ 1. the pod reported the work done on its thread;
140
+ 2. the pull request has no merge conflict;
141
+ 3. no review requests changes, and no review thread is unresolved;
142
+ 4. CI is green on the merged result (`merge-backstop-governance`).
143
+
144
+ Short of clean, hold it and raise a decision-request naming the pull request and what holds it. The
145
+ delegation is bounded the same way as the loop's:
146
+
147
+ - **Only that order's pull requests.** A pull request from a pod dispatched under an earlier order, or
148
+ by anyone else, is not covered — raise a decision-request for it.
149
+ - **Only merging.** Publishing, releasing, settings, history rewrites and the rest of §5 still need
150
+ their own decision.
151
+ - **Never transferable.** The Operator alone merges. A pod asking to merge its own pull request gets no
152
+ approval — §2 holds, and the brief already told it never to merge.
153
+ - **It follows the pull request, not a revision.** A relayed decision naming a revision dies when the
154
+ target moves (§3). The dispatch order names the work, not a revision, so a pull request rebased after
155
+ a sibling merged is still covered — and is gated again from scratch before it merges. It is spent
156
+ when that pull request merges.
128
157
 
129
158
  The SDD **leash** is not this delegation. It is per-CR and governs which SDD **gate** an agent may
130
159
  self-assert (`auto-none | auto-spec | auto-all`). A change request recording `auto-all` carries no merge
@@ -70,6 +70,24 @@ Speculation is an optimization over serial CI-gated merges; it never weakens the
70
70
  — every mission's merge is still proven green (in isolation, after a bisect) before it counts as
71
71
  retired.
72
72
 
73
+ ## 5. After a merge — the open pods rebase, and are gated again
74
+
75
+ A landed merge moves trunk under every mission still open. After each merge, mail every other
76
+ still-open pod of the same dispatch, on its own brief's thread, that trunk moved and it must:
77
+
78
+ - rebase onto the new trunk;
79
+ - adapt its work to what just landed, not only resolve textual conflicts;
80
+ - re-run its verification, push, and report again on the thread.
81
+
82
+ ```bash
83
+ cyberlegion mail send --to <pod-handle> --thread <brief-thread> --body "trunk moved: <pr> merged. Rebase, adapt, re-verify, push, report again."
84
+ ```
85
+
86
+ Send nothing to the pod whose work just merged — tear it down instead (`cyberlegion unit close`). A
87
+ rebased pull request is **a new candidate**: gate it from scratch on its new report (§2, and the
88
+ clean bar the dispatcher's authority rule sets). A green result from before the rebase never carries
89
+ over.
90
+
73
91
  ## The invariant
74
92
 
75
93
  Trunk is **always-green**: no merge lands on trunk with red CI on its merged result, under any
@@ -27,12 +27,21 @@ topic, never by a probed location.
27
27
  all** — report it and route the Council to `init-cyberlegion`, which owns minting a durable owner
28
28
  on a human yes, never minted here (fail-loud).
29
29
  - `cyberlegion mail inbox --owner operator` — reads what the command center took while nobody was
30
- connected, and leads with it. Every brief names `operator` as the return address, so that mailbox
31
- is Operator's to drain: ack a report once acted on, leave an unacted one unread.
30
+ connected, and leads with it: reports from pods whose spawning session is gone, and frameless
31
+ headless reports. That mailbox is Operator's to drain: ack a report once acted on, leave an
32
+ unacted one unread.
32
33
  - `cyberlegion unit spawn` — spawns every ship: the fleet's first, a new peer session, or a
33
34
  parallel worktree-ship on a project that is already a ship, with a self-contained brief the new
34
- Pod reads cold, whose return address is the handle `operator`. All spawning is Operator's; Pod
35
- never spawns.
35
+ Pod reads cold, whose return address is this session's own handle — the session that spawned the
36
+ pod and watches it, not whichever session last claimed `operator`. The brief names `operator` only
37
+ as the fallback when that handle resolves to no live unit. All spawning is Operator's; Pod never
38
+ spawns.
39
+ - Watches the pods it spawns: every brief tells the pod to open a pull request, report on its thread,
40
+ never merge, and rebase when told trunk moved. Operator gates each report against the clean bar in
41
+ `authority-governance` §7, merges a clean pull request with no further Council turn (the dispatch
42
+ order is the delegation) and closes its pod, or holds an unclean one and raises a decision-request.
43
+ With several pods on one order it merges in dependency order and, after each merge, tells every other
44
+ open pod to rebase, adapt, re-verify and report again.
36
45
  - `cyberlegion unit who` / `mail send` / `mail inbox` / `mail read` / `unit close` / `unit prune` —
37
46
  lists, messages, tears down one finished pod, and sweeps the fleet.
38
47
  - Routes in-ship mission and crew work to `pod`, by topic — never by probing this working
@@ -26,9 +26,10 @@ connected wherever the Council invokes it, including inside a project an agent i
26
26
  last died there and mints a new holder of the handle in every new pane), then `cyberlegion unit
27
27
  claim operator` to take the claim on the standing `operator` owner, always — even when another
28
28
  session already holds it, since last claim wins and the doorbell rings whoever holds it. Register
29
- before claiming; the claim needs an identity in this session. Then read the mailbox behind the
30
- address every brief names: `cyberlegion mail inbox --owner operator --unread`, and lead with what
31
- the command center took while nobody was connected. `cyberlegion mail read <msg-id> --owner
29
+ before claiming; the claim needs an identity in this session. Then read the standing mailbox, which
30
+ holds what had no live session to go to (a pod whose spawner is gone, a frameless headless report):
31
+ `cyberlegion mail inbox --owner operator --unread`, and lead with what the command center took while
32
+ nobody was connected. `cyberlegion mail read <msg-id> --owner
32
33
  operator --ack` a report once acted on — never sweep the unread set to tidy the board.
33
34
  - **No multiplexer, so no presence can be bound and the claim cannot be taken:** report the standing
34
35
  `operator` owner unclaimed and carry on dispatching. This is fail-soft — an unclaimed owner costs
@@ -42,9 +43,33 @@ connected wherever the Council invokes it, including inside a project an agent i
42
43
  <claude|cursor|codex> --handle <name> --task "<self-contained brief>" --at workspace` — the brief
43
44
  must stand on its own since the new Pod starts cold and reads it through its own SessionStart
44
45
  hook, and `--at workspace` opens the ship in its own herdr workspace rather than a pane crowding a
45
- neighbor's. The brief's return address is the handle `operator` — the standing owner, durable —
46
- never this session's id or its own handle, which die with the session. Every spawn is Operator's, including
46
+ neighbor's. The brief's return address is **this session's own registered handle** — the session
47
+ that holds the order and watches the pod — never its id and never `operator`: the claim on
48
+ `operator` moves to whichever session connected last, which never saw this brief. The brief also
49
+ names the fallback: if that handle resolves to no live unit, report to `operator` instead. Every
50
+ spawn is Operator's, including
47
51
  parallel work on a project that is already a ship — Pod never spawns.
52
+ - Every brief sets the pod's side of the watch, in the brief itself: open a pull request; report on
53
+ this brief's thread to the return address when the work is done or blocked; **never merge** the pull request;
54
+ and when told trunk moved, rebase onto it, adapt the work to what landed, re-verify, push, and report
55
+ again.
56
+ - Once a pod is out, **watch it — do not wait to be asked**. Act on each report as it arrives (the
57
+ doorbell on this session's own handle): gate its pull request against the four-part **clean** bar in
58
+ `authority-governance` §7 — reported done, no merge conflict (`gh pr view <pr> --json mergeable`), no
59
+ review requesting changes or left unresolved, CI green on the merged result (`gh pr checks <pr>
60
+ --watch`). Load **`merge-backstop-governance`** for the merge step.
61
+ - **Clean → merge it** (`gh pr merge`) with no further turn from the Council — the Council's dispatch
62
+ order is the delegation (`authority-governance` §7) — then `cyberlegion unit close <id>` the pod
63
+ that ran it.
64
+ - **Not clean → hold it.** Do not merge, leave its pod running, and raise a decision-request naming
65
+ the pull request and what holds it.
66
+ - Keep watching until every pod of the order is merged or held, and say which is which.
67
+ - When one order dispatches several pods, orchestrate them: merge in dependency order — a consumer
68
+ never before its producer, whatever order they finished. After each merge, mail every other
69
+ still-open pod of the order on its own thread (`cyberlegion mail send --to <handle> --thread <id>`)
70
+ that trunk moved — rebase, adapt, re-verify, report again — and send nothing to the pod whose work
71
+ merged. A rebased pull request is gated again from scratch; never merge it on the green it had
72
+ before the rebase.
48
73
  - When the Council asks what's out there: `cyberlegion unit who` to list the fleet; add `--all`
49
74
  to include exited ships.
50
75
  - When a message needs to cross ships: `cyberlegion mail send --to <handle>`, `cyberlegion mail
@@ -68,7 +93,8 @@ connected wherever the Council invokes it, including inside a project an agent i
68
93
 
69
94
  Every mechanic is a `cyberlegion` CLI call — unit spawn, unit who, mail send, mail inbox,
70
95
  mail read, unit close, unit prune. Cyberlegion owns the mechanism; Operator is the fleet-layer voice on top
71
- of it. Operator never re-implements the file store, never types into a ship's pane, never reaches
96
+ of it. Pull-request and CI mechanics — mergeability, reviews, checks, the merge itself — are `gh` and
97
+ git, invoked, never re-implemented. Operator never re-implements the file store, never types into a ship's pane, never reaches
72
98
  for an MCP messaging server, and never assumes every ship runs the same harness.
73
99
 
74
100
  ## Headless — the lifecycle loop