@danypops/papyrus 0.54.4 → 0.54.5

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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/src/client.ts +25 -11
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@danypops/papyrus",
3
- "version": "0.54.4",
3
+ "version": "0.54.5",
4
4
  "description": "Daemon-backed graph artifacts, evidence-bearing tasks, rules, skills, and native TUI workflows for Pi",
5
5
  "type": "module",
6
6
  "main": "./src/index.ts",
package/src/client.ts CHANGED
@@ -126,18 +126,31 @@ export interface ConnectPapyrusClientOptions {
126
126
  env?: Record<string, string | undefined>;
127
127
  /** Overrides the version connectWithVersionCheck compares against. Defaults to PAPYRUS_VERSION; test-only -- lets a test force a mismatch against a real daemon without a second build. */
128
128
  expectedVersion?: ExpectedVersion;
129
+ /**
130
+ * Overrides the default fail-closed behavior (see connectPapyrusClient's own doc comment for
131
+ * why that default changed). Test-only -- covers the auto-spawn mechanism itself
132
+ * (connect-client-auto-spawn.test.ts) and lets other real-daemon integration tests keep using
133
+ * it as convenient bootstrap. A real, non-Armada-supervised standalone deployment could also
134
+ * set this explicitly, but that is not this option's primary purpose.
135
+ */
136
+ autoStart?: boolean;
129
137
  }
130
138
 
131
139
  /**
132
- * Transparently starts the daemon first if it is not already running -- matches
133
- * every other daemon-backed ecosystem package that opted into auto-start (see
134
- * @danypops/vehicle-client's connectWithPolicy doc comment: web-spider opts in,
135
- * lector/pi-packed fail closed by design). Papyrus previously failed closed with
136
- * "install/start papyrus.service", requiring a human to separately discover and
137
- * run `papyrus service install` before the very first tool call could succeed.
138
- * A handle file that exists but points at a dead/unreachable daemon is a distinct
139
- * failure (stale, not "never started") and is NOT auto-recovered here -- it still
140
- * throws its own actionable "restart manually" error, unchanged from before.
140
+ * Fails closed if nothing is reachable at all -- matches lector/pi-packed (see
141
+ * @danypops/vehicle-client's connectWithPolicy doc comment). Papyrus used to auto-start here
142
+ * (autoStart: true) because it predated being a properly Armada-supervised Vehicle; that flag
143
+ * is now a genuine liability, not a convenience: a real, live race was traced to it directly --
144
+ * Armada's own systemd unit and THIS client's auto-spawn each independently tried to be "the one
145
+ * that starts Papyrus" whenever no daemon was momentarily reachable (e.g. mid-restart), and
146
+ * whichever one's child won the OS-level single-instance-lock race became an orphan invisible to
147
+ * systemd's own tracking, permanently confusing `armada status`. Now that Armada's systemd unit
148
+ * (Restart=on-failure) is the one and only thing responsible for keeping Papyrus running, a
149
+ * client that finds nothing reachable should say so plainly, not compete to fix it.
150
+ *
151
+ * Stale-VERSION self-healing (an already-running daemon reporting an older version than this
152
+ * client expects) is unrelated to autoStart and still works: connectWithVersionCheck's own kill-
153
+ * and-replace path only requires `spawn` to be defined, independent of the autoStart flag above.
141
154
  */
142
155
  export async function connectPapyrusClient(
143
156
  dir: string = daemonStateDir(),
@@ -147,7 +160,7 @@ export async function connectPapyrusClient(
147
160
  {
148
161
  readHandle: () => readDaemonHandle(dir) ?? null,
149
162
  buildClient: probedPapyrusClient,
150
- autoStart: true,
163
+ autoStart: options.autoStart ?? false,
151
164
  spawn: () => {
152
165
  spawnDetachedDaemon({
153
166
  binPath: papyrusCliPath(),
@@ -156,7 +169,8 @@ export async function connectPapyrusClient(
156
169
  spawn: spawnPapyrusDaemonProcess,
157
170
  });
158
171
  },
159
- fallbackMessage: "Papyrus daemon failed to start automatically; run `papyrus service install` or `papyrus serve` manually.",
172
+ fallbackMessage:
173
+ "Papyrus daemon is not running; Armada should be supervising it -- run `armada status`/`armada reconcile`, or `papyrus serve` directly if this is a standalone (non-Armada) setup.",
160
174
  },
161
175
  {
162
176
  expectedVersion: options.expectedVersion ?? papyrusExpectedVersion,