@sjawhar/pi-legion 9.8.0 → 9.8.2

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
@@ -15729,7 +15729,7 @@ function onEnvoyRoleRegained(listener) {
15729
15729
  // package.json
15730
15730
  var package_default = {
15731
15731
  name: "@sjawhar/pi-legion",
15732
- version: "9.8.0",
15732
+ version: "9.8.2",
15733
15733
  license: "Apache-2.0",
15734
15734
  type: "module",
15735
15735
  omp: {
@@ -16515,6 +16515,45 @@ function createControllerSession(deps) {
16515
16515
  // src/handoff-commit.ts
16516
16516
  import { execFile as execFile2 } from "child_process";
16517
16517
  import { promisify as promisify2 } from "util";
16518
+
16519
+ // src/git-lock.ts
16520
+ import { lstat } from "fs/promises";
16521
+ var GIT_LOCK_REPORTS = [
16522
+ /The lockfile at '([^']+)' might need manual deletion/g,
16523
+ /Unable to create '([^']+)': File exists/g
16524
+ ];
16525
+ function age(ms) {
16526
+ const total = Math.round(Math.abs(ms) / 1000);
16527
+ const sign = ms < 0 && total > 0 ? "-" : "";
16528
+ const hours = Math.floor(total / 3600);
16529
+ const minutes = Math.floor(total % 3600 / 60);
16530
+ const seconds = total % 60;
16531
+ if (hours > 0)
16532
+ return `${sign}${hours}h${minutes}m${seconds}s`;
16533
+ if (minutes > 0)
16534
+ return `${sign}${minutes}m${seconds}s`;
16535
+ return `${sign}${seconds}s`;
16536
+ }
16537
+ async function staleGitLockNote(output, now = Date.now()) {
16538
+ const locks = new Set;
16539
+ for (const report of GIT_LOCK_REPORTS) {
16540
+ for (const match of output.matchAll(report))
16541
+ locks.add(match[1]);
16542
+ }
16543
+ const notes = [];
16544
+ for (const lock of locks) {
16545
+ const written = await lstat(lock).then((info) => info.mtimeMs, () => {
16546
+ return;
16547
+ });
16548
+ if (written === undefined)
16549
+ continue;
16550
+ notes.push(`git lock ${lock} was last written ${age(now - written)} ago and blocks this command. Do not remove it while the issue's pod runs: another role's git, which this container cannot see, may hold it. Replacing the issue's pod removes it. Under the tmux runtime nothing removes it: remove it by hand only once no git or jj process on the host is using the repository.`);
16551
+ }
16552
+ return notes.join(`
16553
+ `);
16554
+ }
16555
+
16556
+ // src/handoff-commit.ts
16518
16557
  var FILE_BACKED = {
16519
16558
  planning: { word: "plan", role: "planner" },
16520
16559
  implementing: { word: "implement", role: "implementer" },
@@ -16531,7 +16570,9 @@ var pathJj = async (args, cwd) => {
16531
16570
  return stdout.trim();
16532
16571
  } catch (error48) {
16533
16572
  const detail = error48 !== null && typeof error48 === "object" && "stderr" in error48 ? String(error48.stderr).trim() : error48 instanceof Error ? error48.message : String(error48);
16534
- throw new Error(`jj ${args.join(" ")} failed: ${detail}`);
16573
+ const note = await staleGitLockNote(detail);
16574
+ throw new Error(`jj ${args.join(" ")} failed: ${detail}${note === "" ? "" : `
16575
+ ${note}`}`);
16535
16576
  }
16536
16577
  };
16537
16578
  function requiredVariable(env, name) {
@@ -197,7 +197,8 @@ credential can exist without any skill having told you so). When the evidence ge
197
197
  reachable, do not have a different running session perform the read on this tree's behalf and
198
198
  fold the result into the spec as if it were routine: write the missing capability as its own
199
199
  decision block — which external system, which read or write, why the spec needs it — addressed
200
- to the human, in the same spirit as the implementer reports a production-check gap (section 6) and leave it
200
+ to the human, in the same spirit as the implementer's ask to a person when the deployment
201
+ instructions name nobody for a deploy (section 6), and leave it
201
202
  open until the human resolves it. A workaround substituted for that record only hides the gap
202
203
  from the next tree that hits it.
203
204
 
@@ -314,9 +315,12 @@ The daemon keeps this order from its fixed table; you start none of its steps:
314
315
  It drives the changed path in production through the user's own access path and records
315
316
  what it saw on the pull request and on this issue. Sign off only after the implementer's production
316
317
  report exists. A defect it finds is a corrective child issue of this tree, not a note on a
317
- closed one; if the implementer cannot perform the deploy, it opens a `dispatch ask` that starts
318
- with the production gap and why it matters, then names the required step, its risk, and
319
- outcome-named options. The issue waits for that answer.
318
+ closed one. If the implementer cannot perform the deploy itself, it asks the agent or role the
319
+ deployment instructions name for that deploy (an Envoy role), gives it the merge commit, and
320
+ waits on the production signal the instructions name; the issue waits with it. It opens a
321
+ `dispatch ask` to a person only when the instructions name nobody for that deploy, starting
322
+ with the production gap and why it matters, then naming the required step, its risk, and
323
+ outcome-named options. No one is ever asked for approval to deploy.
320
324
 
321
325
  What returns the tree to review: a changed diff — a commit above the approved head that
322
326
  touches anything outside `docs/solutions/` and the issue's `.legion/<issue>/`, or a
@@ -180,7 +180,7 @@ dispatch message --issue <KEY> --body-file - <<'EOF'
180
180
 
181
181
  **Proofs read:** implementer <surface/command>, tester <surface/command>.
182
182
 
183
- **Production check:** <what the implementer will drive after the merge, or the deploy/restart step a human will have to perform first>
183
+ **Production check:** <what the implementer will drive after the merge, and any deploy or restart it waits on first, with the agent or role the deployment instructions name to perform it, or the person it asks when they name none>
184
184
 
185
185
  <!-- legion: {"session":"<session-id>","phase":"retro"} -->
186
186
  EOF
@@ -151,8 +151,12 @@ review posted without a completion leaves the issue in reviewing until you finis
151
151
  carrying the Legion footer, and a `dispatch message` on the issue — the reviewer and merger
152
152
  read GitHub, the architect reads the issue. When the deploy that carries the merge has not
153
153
  happened (a shared profile still holding the previous plugin release, a daemon still running
154
- the previous commit, a slot nobody has run), open a `dispatch ask` that starts with the
155
- production gap and why it matters, then names the required install or restart step, its risk,
156
- and outcome-named options. Keep the `Production:` line at `pending <what is missing>`, and
157
- complete the check once the human answers. Never record a staging pass as the production check,
158
- and never let the architect sign off on a `pending` line.
154
+ the previous commit, a slot nobody has run) and you cannot perform it yourself, ask the agent or
155
+ role the deployment instructions name for that deploy: `envoy_publish` to its role topic with the
156
+ merge commit and `expects_reply: required`, then wait on the production signal the instructions
157
+ name. Open a `dispatch ask` to a person only when the instructions name nobody for that deploy;
158
+ it starts with the production gap and why it matters, then names the required install or restart
159
+ step, its risk, and outcome-named options. Never ask anyone for approval to deploy. Keep the
160
+ `Production:` line at `pending <what is missing>`, and complete the check once that signal shows
161
+ the deploy carries the merge (or the person answers, when an ask was the route). Never record a
162
+ staging pass as the production check, and never let the architect sign off on a `pending` line.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sjawhar/pi-legion",
3
- "version": "9.8.0",
3
+ "version": "9.8.2",
4
4
  "license": "Apache-2.0",
5
5
  "type": "module",
6
6
  "omp": {