@sjawhar/pi-legion-envoy 7.11.2 → 7.12.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/dist/legion.js CHANGED
@@ -18042,7 +18042,7 @@ function endInjectedUserTurns(sessionID) {
18042
18042
  // package.json
18043
18043
  var package_default = {
18044
18044
  name: "@sjawhar/pi-legion-envoy",
18045
- version: "7.11.2",
18045
+ version: "7.12.0",
18046
18046
  license: "Apache-2.0",
18047
18047
  type: "module",
18048
18048
  omp: {
@@ -18055,7 +18055,7 @@ var package_default = {
18055
18055
  ]
18056
18056
  },
18057
18057
  legion: {
18058
- daemonApiVersion: 13
18058
+ daemonApiVersion: 14
18059
18059
  },
18060
18060
  repository: {
18061
18061
  type: "git",
@@ -18778,8 +18778,19 @@ function createControllerSession(deps) {
18778
18778
  let mintControllerGrant;
18779
18779
  let controllerTranscript;
18780
18780
  const claim = async (context) => {
18781
+ const supervised = classifySession(process.env).kind === "controller" && (process.env.LEGION_BOOT_TOKEN_FILE !== undefined || process.env.LEGION_BOOT_TOKEN !== undefined);
18782
+ if (!supervised)
18783
+ return claimWith(context, false);
18784
+ try {
18785
+ await claimWith(context, true);
18786
+ } catch (error48) {
18787
+ console.error(`[legion] the daemon-launched controller's claim failed; exiting so the daemon launches it again: ${messageFor(error48)}`);
18788
+ deps.exitProcess(1);
18789
+ }
18790
+ };
18791
+ const claimWith = async (context, supervised) => {
18781
18792
  const sessionID = context.sessionManager.getSessionId();
18782
- const capability = controllerCapability ?? requiredControllerCapability(process.env);
18793
+ const capability = controllerCapability ?? (supervised ? requiredSecret(process.env, "LEGION_BOOT_TOKEN") : requiredControllerCapability(process.env));
18783
18794
  controllerCapability = capability;
18784
18795
  const { sessionFile, agentId } = await persistedTranscript(context);
18785
18796
  const launched = classifySession(process.env).kind === "controller";
@@ -18810,6 +18821,14 @@ function createControllerSession(deps) {
18810
18821
  const envoyContext = "setInterval" in context ? context : undefined;
18811
18822
  await claimEnvoyRole(sessionID, registration.claimToken, envoyContext);
18812
18823
  await subscribeLegionNotice(sessionID, legionControllerNoticeSubject(project), envoyContext, registration.claimToken);
18824
+ if (supervised) {
18825
+ await client.ready({
18826
+ claimToken: registration.claimToken,
18827
+ sessionId: sessionID,
18828
+ secret: registration.secret,
18829
+ generation: registration.generation
18830
+ });
18831
+ }
18813
18832
  mintControllerGrant = () => client.controllerGrant({ sessionId: sessionID, secret: registration.secret });
18814
18833
  controllerSessionID = sessionID;
18815
18834
  controllerTranscript = launched ? sessionFile : undefined;
@@ -19560,7 +19579,8 @@ function legionExtension(pi) {
19560
19579
  });
19561
19580
  const controllerSession = createControllerSession({
19562
19581
  daemon: roleDaemon,
19563
- persistedTranscript
19582
+ persistedTranscript,
19583
+ exitProcess: (code) => exitProcess(code)
19564
19584
  });
19565
19585
  const titleSession = async (context) => {
19566
19586
  const title = legionSessionTitle(classifySession(process.env), process.env.LEGION_PROJECT);
@@ -26,8 +26,8 @@ For an interactive takeover from a hand-started OMP session, start OMP with
26
26
  `LEGION_DAEMON_URL`, `LEGION_PROJECT` (the daemon's project), `LEGION_STATE_DIR`, and `LEGION_GRANT_FILE`
27
27
  (an absolute path to a file only you can read, under a 0700 directory; the extension writes
28
28
  each command's grant there and every `bash` call is blocked without it) in its environment. Do
29
- not set `LEGION_CONTROLLER=1` — that marker is `legion controller start`'s own, and a session
30
- carrying it claims at startup. Then run:
29
+ not set `LEGION_CONTROLLER=1` — that marker is the launched controller's own (`legion controller
30
+ start`'s session, or the daemon's pod), and a session carrying it claims at startup. Then run:
31
31
 
32
32
  ```text
33
33
  /legion-claim-controller
@@ -50,12 +50,27 @@ retry. And the role does not follow `/new` or `/fork` in a takeover session —
50
50
  `LEGION_CONTROLLER=1` the new session is not a Legion session to the extension — so after either
51
51
  command run `/legion-claim-controller` again.
52
52
 
53
- The daemon holds nothing for a controller: daemon state and the Dispatch project remain
54
- authoritative, and the start procedure below reads what happened while no controller ran.
53
+ Daemon state and the Dispatch project remain authoritative, and the start procedure below reads
54
+ what happened while no controller ran. Who launched you is the deployment's `controller` setting:
55
+ the operator, or the daemon itself. The `How this controller runs` part of your system prompt says
56
+ which.
57
+
58
+ ### Started by the daemon
59
+
60
+ Under `controller: daemon` the daemon launched you as a pod in the cluster and supervises you like
61
+ a root architect: you run headless (`omp --mode rpc`), nobody types into your session, and nobody
62
+ reads your replies as they appear. The extension registered with your launch's boot token, claimed
63
+ the role, subscribed to the controller topic and reported ready; the daemon then sent your start
64
+ message. When your pod dies the daemon relaunches it and resumes this same session, with a new
65
+ start message, so run the start procedure each time one arrives. A human reaches you through
66
+ Dispatch (a message to your session on the Agents page, a reply to an ask you opened, a mention) or
67
+ Envoy: answer them where they will read it, a Dispatch message or reply, since text left only in
68
+ your session reaches no one. `legion state` and `legion status <KEY> <status>` work as below. There
69
+ is no `legion controller start` against this daemon, and nobody can replace you with one.
55
70
 
56
71
  ### Started by the operator
57
72
 
58
- The daemon launches no controller, under either runtime: the operator ran
73
+ Under `controller: operator`, the default, the daemon launches no controller: the operator ran
59
74
  `legion controller start --config controller.yaml [--daemon-url <url>]` on
60
75
  their own machine, and you are that foreground OMP session. The command fetched a fresh controller
61
76
  secret from the daemon with the operator's token, wrote it to a 0600 file under `LEGION_STATE_DIR`
@@ -78,8 +93,10 @@ mints a new secret, so your grants stop working and the role moves to the new se
78
93
  The Go daemon's controller topic is a wake for a session that is running when it is published.
79
94
  Envoy hands an Oh My Pi session no retained copy of a notice published before it subscribed, so a
80
95
  hold, a tree architect's failed claim, a new triage root, or a freed slot from while no controller
81
- ran never arrives as a wake. `legion controller start` opens your first turn with a start message
82
- (`Legion controller start: …`), so every start and restart runs this procedure with nothing typed.
96
+ ran never arrives as a wake. Every launch opens your first turn with a start message
97
+ (`Legion controller start: …`) — `legion controller start` passes it, and the daemon sends it to a
98
+ controller it launched once that controller is ready — so every start and restart runs this
99
+ procedure with nothing typed.
83
100
  At every start, after the claim recheck ([Turn discipline](#turn-discipline)) and before anything
84
101
  else:
85
102
 
@@ -350,7 +367,7 @@ priority first, then board rank ([Keeping the slots full](#keeping-the-slots-ful
350
367
  `unassigned`, `Unassigned — nobody's Inbox shows this tree's questions or its design approval
351
368
  until someone takes it from the issue header (Assignee, beside Priority)`. The design approval
352
369
  is promised only when the `Design gate policy:` line of your system prompt, which
353
- `legion controller start` writes from the daemon's own configuration, says
370
+ whoever launched you writes from the daemon's own configuration, says
354
371
  `gates.design: root-issues`. Under `gates.design: off` nobody approves a design, so drop "and
355
372
  its design approval" (and "or its design approval") from the sentence. An unassigned root
356
373
  still runs; the architect's asks wait in every Inbox's Unassigned band.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sjawhar/pi-legion-envoy",
3
- "version": "7.11.2",
3
+ "version": "7.12.0",
4
4
  "license": "Apache-2.0",
5
5
  "type": "module",
6
6
  "omp": {
@@ -13,7 +13,7 @@
13
13
  ]
14
14
  },
15
15
  "legion": {
16
- "daemonApiVersion": 13
16
+ "daemonApiVersion": 14
17
17
  },
18
18
  "repository": {
19
19
  "type": "git",