@rightkit/release 0.6.22 → 0.6.23

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.
Binary file
package/broker-wire.mjs CHANGED
@@ -217,6 +217,10 @@ export function refusalInCapturedOutput(text) {
217
217
  const diagnosis = diagnoseControlReply(event);
218
218
  if (diagnosis.kind === "refused") return { code: diagnosis.code, refusal: diagnosis.refusal, retryable: diagnosis.retryable === true, message: diagnosis.message };
219
219
  }
220
+ // The client's plain-text form of the same refusal (its stderr without --json): `rustright: admission is paused; resume with rustright resume-admission`.
221
+ // Without it a paused broker read as "no request reference" (HeardRight Mac, 2026-11-02).
222
+ const paused = /^rustright: (admission is paused\b[^\r\n]*)/m.exec(String(text ?? ""));
223
+ if (paused) return { code: "RK_ADMISSION_PAUSED", refusal: "paused", retryable: false, message: paused[1].trim() };
220
224
  return null;
221
225
  }
222
226
 
@@ -37,7 +37,7 @@ import { observedEnvOf, readRequestRef, verifySnapshotReceipt, writeSnapshotRequ
37
37
  import { SCAN_TOKEN_ENV, appendLedger, readLedger, scanTokenOf, unclaimedLedgers } from "./cargo-ledger.mjs";
38
38
  import { brokerSection, carryBrokerAdapterAsync, verifyBrokerLedger } from "./snapshot-broker.mjs";
39
39
  import { ADMISSION_POLL_MS, CARRIED_CANCEL_GRACE_MS, QUEUED_CEILING_FACTOR, createBrokerLive, createRunClock, createStatusPoller, watchBrokerAdmission } from "./broker-admission.mjs";
40
- import { CANCEL_WAIT_ENV, operationDeadlineEnv } from "./broker-wire.mjs";
40
+ import { CANCEL_WAIT_ENV, operationDeadlineEnv, refusalInCapturedOutput } from "./broker-wire.mjs";
41
41
  import { removeCarrier } from "./carrier-census.mjs";
42
42
 
43
43
  export const SCAN_RESULT_SCHEMA = "rightkit.deterministic-scans/1";
@@ -2755,6 +2755,14 @@ export async function runScans(plan, options = {}) {
2755
2755
  // The broker's signed account of that request: the receipt verifies against this host's pins and its snapshotEvidence names
2756
2756
  // this commit, this snapshot unchanged from START to exit, this ownership and the output directory. Anything less fails the row.
2757
2757
  if (carrier) {
2758
+ // A typed broker refusal with no request reference (admission paused, a cutover drain): nothing was admitted under this scan's sub-handle, so it is
2759
+ // recorded unsent at once, as a busy connection is; otherwise a dead owner's record could never be reclaimed (HeardRight Mac, 2026-11-02).
2760
+ if (!fs.existsSync(path.join(carrier.refDir, "request.json"))) {
2761
+ const refused = refusalInCapturedOutput(`${r?.stdout ?? ""}\n${r?.stderr ?? ""}`);
2762
+ if (refused && typeof deps.snapshotBroker?.markBrokerUnsent === "function") {
2763
+ try { deps.snapshotBroker.markBrokerUnsent(carrier.made.carrier.ownership.handle, `the broker refused the submit before admitting it (${refused.code}): nothing was spawned`); } catch { /* the reclaim then judges the sub-handle as before */ }
2764
+ }
2765
+ }
2758
2766
  try {
2759
2767
  const ref = readRequestRef(path.join(carrier.refDir, "request.json"));
2760
2768
  const receipt = await deps.snapshotBroker.receiptOf(ref.requestId);
package/disk-command.mjs CHANGED
@@ -210,7 +210,10 @@ function defaultGlobalRoots() {
210
210
  return roots;
211
211
  }
212
212
 
213
- export function scheduleSpec({ platform = process.platform, nodePath = process.execPath, cli = path.join(path.dirname(fileURLToPath(import.meta.url)), "cli", "right-release.mjs"), home = os.homedir() } = {}) {
213
+ // The node a scheduled job runs is the real file, never a version manager's link to it: nvm-windows' C:\\nvm4w\\nodejs is a symlink into the user profile that a
214
+ // scheduled task context cannot always follow (the Dell task failed with 0x80070003, path not found, 2026-11-02).
215
+ const realNode = () => { try { return realpathSync.native(process.execPath); } catch { return process.execPath; } };
216
+ export function scheduleSpec({ platform = process.platform, nodePath = realNode(), cli = path.join(path.dirname(fileURLToPath(import.meta.url)), "cli", "right-release.mjs"), home = os.homedir() } = {}) {
214
217
  if (platform === "darwin") {
215
218
  // launchd cannot open log files on an external volume for a background job (spawn fails with EX_CONFIG);
216
219
  // `disk run` writes its own structured log to disk-hygiene.jsonl on the heavy volume.
package/local-publish.mjs CHANGED
@@ -368,6 +368,10 @@ export function localTestPlan({ kind, unit, dir, config, manifest, batch = false
368
368
  // Every tested feature set is linted (-D warnings), not only the first.
369
369
  if (!batch) for (const features of featureSets) steps.push({ command: "cargo", args: ["clippy", "-p", unit, "--message-format=json-render-diagnostics", "--no-deps", "--all-targets", ...features, "--", "-D", "warnings"], test: false });
370
370
  for (const features of allFeatureCheckSets(entry)) steps.push({ command: "cargo", args: ["check", "-p", unit, "--message-format=json-render-diagnostics", "--all-targets", ...features], test: false });
371
+ // rustdoc with -D warnings, for the tested and the checked feature sets: the same rows the CI shards (scripts/ci/gate.mjs) and
372
+ // publish.yml's native verify run, so a broken or private intra-doc link fails this unit stage instead of a later verify.
373
+ const docSets = [...new Map([...featureSets, ...allFeatureCheckSets(entry)].map((features) => [JSON.stringify(features), features])).values()];
374
+ for (const features of docSets) steps.push({ command: "cargo", args: ["doc", "-p", unit, "--message-format=json-render-diagnostics", "--no-deps", ...features], test: false, env: { RUSTDOCFLAGS: "-D warnings" } });
371
375
  // Consumer rows (separate Cargo workspaces) gate only this crate: they come from this crate's own entry.
372
376
  const consumers = consumerRows(unit, entry);
373
377
  for (const row of consumers) steps.push(...consumerRowInvocations(row));
@@ -666,7 +670,7 @@ async function* publishUnitStages(parsed, deps, batch) {
666
670
  // A crate's own steps run in its Cargo workspace (its own Cargo.lock and target directory, #1285); a consumer row names its
667
671
  // separate workspace by --manifest-path relative to the repository root.
668
672
  const stepCwd = kind === "cargo" && step.command === "cargo" && !step.args.includes("--manifest-path") ? unitPath : workspaceRoot;
669
- const result = await run(step.command, step.command === "cargo" ? withCargoJobs(step.args, parsed.jobs) : step.args, { cwd: stepCwd, env });
673
+ const result = await run(step.command, step.command === "cargo" ? withCargoJobs(step.args, parsed.jobs) : step.args, { cwd: stepCwd, env: step.env ? { ...env, ...step.env } : env });
670
674
  const row = { command: commandText, ok: false, isTest: step.test && TEST_COMMAND.test(commandText) };
671
675
  if (result.error || result.status !== 0) {
672
676
  steps.push(row);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rightkit/release",
3
- "version": "0.6.22",
3
+ "version": "0.6.23",
4
4
  "description": "Portable release CLI/SDK with fail-closed public GitHub Releases and private R2 + RightApps distribution.",
5
5
  "license": "MIT OR Apache-2.0",
6
6
  "type": "module",
@@ -49,7 +49,7 @@
49
49
  "@rightkit/qa": "0.6.2",
50
50
  "@rightkit/qa-chrome": "0.1.12",
51
51
  "@rightkit/react-shell": "0.7.2",
52
- "@rightkit/release": "0.6.22",
52
+ "@rightkit/release": "0.6.23",
53
53
  "@rightkit/settings-ui": "0.7.0",
54
54
  "@rightkit/social-ui": "0.1.0",
55
55
  "@rightkit/system-ui": "0.1.0",
@@ -438,6 +438,10 @@ function carryBrokerCargoOnce({ words, cwd, env, section, workspace, checkoutWor
438
438
  // RK_BROKER_BUSY with no request reference: the connection never opened, so no byte reached the broker. That is the gate's own proof that this sub-handle was never sent (GB-21), recorded under
439
439
  // the ownership lock so the retry's own sub-handle, not this one, is what the stage waits on; a busy answer after a reference exists (a reconnect) proves nothing of the kind.
440
440
  if (outcome.status === "unverified" && outcome.code === "broker-busy" && ref === null) markCarriedUnsentRequest({ section, env, callHandle: made.carrier.ownership.handle, reason: "every broker connection was busy (RK_BROKER_BUSY): the connection never opened and no byte was sent" });
441
+ // A typed REJECTED result (admission paused, a cutover drain, ...) with no request reference: the broker refused the submit before it admitted anything, so nothing
442
+ // runs under this sub-handle and the broker will never list it as a member. Recorded unsent now, or a dead owner's record could never be reclaimed (HeardRight Mac,
443
+ // 2026-11-02: 42 paused refusals left a member-less sub-handle the broker answers UNKNOWN for).
444
+ else if (outcome.status === "unverified" && /^broker-refused-/.test(String(outcome.code)) && ref === null) markCarriedUnsentRequest({ section, env, callHandle: made.carrier.ownership.handle, reason: `the broker refused the submit before admitting it (${outcome.code}): nothing was spawned` });
441
445
  // GB-53: captured output that lost a frame to FRAME_OVER_CAP (or a result the broker replaced with RK_RESPONSE_OVER_CAP) is truncated: refused, never read as complete.
442
446
  if (outcome.status === "verified" && capture) {
443
447
  const drained = drainFrames(`${out.stdout}\n${out.stderr}`);
@@ -650,6 +654,10 @@ function* carryBrokerAdapterSteps({ adapter, words, cwd, env, section, record, e
650
654
  // RK_BROKER_BUSY with no request reference: the connection never opened, so no byte reached the broker. That is the gate's own proof that this sub-handle was never sent (GB-21), recorded under
651
655
  // the ownership lock so the retry's own sub-handle, not this one, is what the stage waits on; a busy answer after a reference exists (a reconnect) proves nothing of the kind.
652
656
  if (outcome.status === "unverified" && outcome.code === "broker-busy" && ref === null) markCarriedUnsentRequest({ section, env, callHandle: made.carrier.ownership.handle, reason: "every broker connection was busy (RK_BROKER_BUSY): the connection never opened and no byte was sent" });
657
+ // A typed REJECTED result (admission paused, a cutover drain, ...) with no request reference: the broker refused the submit before it admitted anything, so nothing
658
+ // runs under this sub-handle and the broker will never list it as a member. Recorded unsent now, or a dead owner's record could never be reclaimed (HeardRight Mac,
659
+ // 2026-11-02: 42 paused refusals left a member-less sub-handle the broker answers UNKNOWN for).
660
+ else if (outcome.status === "unverified" && /^broker-refused-/.test(String(outcome.code)) && ref === null) markCarriedUnsentRequest({ section, env, callHandle: made.carrier.ownership.handle, reason: `the broker refused the submit before admitting it (${outcome.code}): nothing was spawned` });
653
661
  // GB-53: captured output that lost a frame to FRAME_OVER_CAP (or a result the broker replaced with RK_RESPONSE_OVER_CAP) is truncated: refused, never read as complete.
654
662
  if (outcome.status === "verified" && capture) {
655
663
  const drained = drainFrames(`${out.stdout}\n${out.stderr}`);