run402 4.41.0 → 4.42.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.
Files changed (41) hide show
  1. package/README.md +2 -2
  2. package/lib/argparse.mjs +1 -1
  3. package/lib/assets.mjs +10 -14
  4. package/lib/command-manifest.mjs +24 -26
  5. package/lib/deploy-v2.mjs +7 -10
  6. package/lib/doctor.mjs +8 -1
  7. package/lib/gitvault-target.mjs +7 -9
  8. package/lib/gitvault.mjs +7 -8
  9. package/lib/notifications.mjs +4 -8
  10. package/lib/operator.mjs +1 -1
  11. package/lib/org.mjs +3 -3
  12. package/lib/repos.mjs +79 -56
  13. package/lib/rooms-context.mjs +2 -3
  14. package/lib/rooms.mjs +11 -14
  15. package/lib/update-check.mjs +6 -8
  16. package/package.json +1 -1
  17. package/sdk/dist/namespaces/admin.d.ts +1 -1
  18. package/sdk/dist/namespaces/admin.js +1 -1
  19. package/sdk/dist/namespaces/deploy.types.d.ts +2 -2
  20. package/sdk/dist/namespaces/gitvault.crypto.d.ts +10 -0
  21. package/sdk/dist/namespaces/gitvault.crypto.d.ts.map +1 -1
  22. package/sdk/dist/namespaces/gitvault.crypto.js +11 -1
  23. package/sdk/dist/namespaces/gitvault.crypto.js.map +1 -1
  24. package/sdk/dist/namespaces/gitvault.d.ts +136 -43
  25. package/sdk/dist/namespaces/gitvault.d.ts.map +1 -1
  26. package/sdk/dist/namespaces/gitvault.js +157 -47
  27. package/sdk/dist/namespaces/gitvault.js.map +1 -1
  28. package/sdk/dist/namespaces/projects.d.ts +1 -1
  29. package/sdk/dist/namespaces/projects.js +1 -1
  30. package/sdk/dist/namespaces/projects.types.d.ts +1 -1
  31. package/sdk/dist/namespaces/projects.types.d.ts.map +1 -1
  32. package/sdk/dist/node/gitvault-publication.d.ts +48 -17
  33. package/sdk/dist/node/gitvault-publication.d.ts.map +1 -1
  34. package/sdk/dist/node/gitvault-publication.js +7 -5
  35. package/sdk/dist/node/gitvault-publication.js.map +1 -1
  36. package/sdk/dist/node/gitvault-recover.d.ts +15 -1
  37. package/sdk/dist/node/gitvault-recover.d.ts.map +1 -1
  38. package/sdk/dist/node/gitvault-recover.js +8 -4
  39. package/sdk/dist/node/gitvault-recover.js.map +1 -1
  40. package/sdk/dist/scoped.d.ts +2 -2
  41. package/sdk/dist/scoped.js +1 -1
package/README.md CHANGED
@@ -54,7 +54,7 @@ For typed `run402.deploy.ts` configs, pass `--manifest` explicitly because TypeS
54
54
 
55
55
  ### repos — host-blind encrypted git repos (zero deploy ceremony)
56
56
 
57
- One noun, twelve verbs (repo-surface-consolidation; `repo` singular resolves identically). `run402 gitvault <verb>` is RETIRED — every old spelling now answers `COMMAND_MOVED`/`COMMAND_REMOVED`.
57
+ One noun, twelve verbs (`repo` singular resolves identically). `run402 gitvault <verb>` answers `COMMAND_MOVED`/`COMMAND_REMOVED`.
58
58
 
59
59
  ```bash
60
60
  run402 init # once per machine
@@ -70,7 +70,7 @@ run402 repos delete --project prj_xyz --force # refuses without --force while th
70
70
 
71
71
  A hosted git remote, encrypted before it leaves the machine — no deploy, no manifest, no app. `origin` is claimed additively — an existing `origin` is never touched, the run402 remote falls back to `run402` instead. Every mutating `repos` verb (`create`, `rename`, `delete`, `snapshot`, `policy`, `mirror`, `gc`) is CLI/OpenClaw-only by design — no MCP tool exists or will exist for them (one-shot recovery receipts, immutable generations, irreversible delete). Three READ-ONLY tools do exist — `repos_view`, `repos_list_heads`, `repos_fsck` — teaching only `repos` spellings. See `run402 repos --help` for the full tiered surface (common: `create`/`view`/`list`; occasional: `snapshot`/`mirror`/`recover`; lifecycle: `rename`/`delete`; maintenance: `fsck`/`gc`/`access`/`policy`), and the CLI reference's `repos` section for the terminal-loss statement and the progressive backup warning.
72
72
 
73
- **Named addressing (design D6).** `run402 org slug <slug>` (owner-only, small one-time fee) claims an org's globally-unique, address-form slug, after which `run402::<slug>/<name>` addresses any repo under it — `git push` to a name that doesn't exist yet push-to-creates it. `run402 repos rename <name> [--project <id>]` claims the per-org-unique `<name>` half explicitly (no fee, absorbs the old `repos name`); `repos create` claims one automatically, best-effort, when the org already has a slug. Also CLI/SDK-only — no MCP tool.
73
+ **Named addressing.** `run402 org slug <slug>` (owner-only, small one-time fee) claims an org's globally-unique, address-form slug, after which `run402::<slug>/<name>` addresses any repo under it — `git push` to a name that doesn't exist yet push-to-creates it. `run402 repos rename <name> [--project <id>]` claims the per-org-unique `<name>` half explicitly (no fee); `repos create` claims one automatically, best-effort, when the org already has a slug. Also CLI/SDK-only — no MCP tool.
74
74
 
75
75
  ### Allowance
76
76
 
package/lib/argparse.mjs CHANGED
@@ -272,7 +272,7 @@ export function requirePositionalCount(args = [], flagsWithValues = [], opts = {
272
272
  return pos;
273
273
  }
274
274
 
275
- // Resolve a positional project_id argument with active-project fallback (GH-102, GH-187).
275
+ // Resolve a positional project_id argument with active-project fallback.
276
276
  // If the first positional starts with "prj_", treat it as the project id and
277
277
  // strip it from the rest. Otherwise, fall through to the active project from
278
278
  // the keystore. Callers can tighten the legacy shorthand when a bare non-prj
package/lib/assets.mjs CHANGED
@@ -265,7 +265,7 @@ function parseArgs(rawArgs) {
265
265
  else if (a === "--limit") out.limit = parseIntegerFlag("--limit", args[++i], { min: 1, max: 1000 });
266
266
  else if (a === "--output" || a === "-o") out.output = args[++i];
267
267
  else if (a === "--ttl") out.ttl = parseIntegerFlag("--ttl", args[++i], { min: 60, max: 604800 });
268
- // v1.50: repeatable --meta key=value (number-coerce on pure digits,
268
+ // Repeatable --meta key=value (number-coerce on pure digits,
269
269
  // comma-split into string[] when value contains ',', "true"/"false"
270
270
  // → boolean, else string). Multiple --meta flags accumulate into a
271
271
  // single flat metadata object.
@@ -274,7 +274,7 @@ function parseArgs(rawArgs) {
274
274
  applyMetaFlag(out.metadata, args[++i]);
275
275
  }
276
276
  else if (a === "--exif-policy") out.exifPolicy = parseExifPolicyFlag(args[++i]);
277
- // v1.50: ls --sort and repeatable --filter k=v.
277
+ // ls --sort and repeatable --filter k=v.
278
278
  else if (a === "--sort") out.sort = parseSortFlag(args[++i]);
279
279
  else if (a === "--filter") {
280
280
  if (out.filter === null) out.filter = {};
@@ -285,7 +285,7 @@ function parseArgs(rawArgs) {
285
285
  return out;
286
286
  }
287
287
 
288
- /** v1.50: parse a single `--meta key=value` token. Coerces value:
288
+ /** Parses a single `--meta key=value` token. Coerces value:
289
289
  * - numeric digits (with optional leading `-` / decimal) → number
290
290
  * - "true" / "false" → boolean
291
291
  * - commas → string[] (each segment stays a string; agents wanting
@@ -436,23 +436,19 @@ async function putOne(projectId, filePath, opts) {
436
436
  }
437
437
  const destKey = computeDestKey(filePath, opts.key);
438
438
 
439
- // v2.1.0: the legacy /storage/v1/uploads* session API is gone. The CLI
440
- // now delegates to `sdk.assets.put`, which routes through the
439
+ // The CLI delegates to `sdk.assets.put`, which routes through the
441
440
  // unified-apply hero (apply/v1/plans -> content/v1/plans -> S3 PUT ->
442
- // commit).
443
- //
444
- // Trade-off vs v2.0.x: resumable uploads via persisted state under
445
- // ~/.run402/uploads/ are no longer supported. Resume semantics now live
446
- // at the apply-plan level (24h plan TTL); a future CLI redesign can
447
- // expose that. The --concurrency and --no-resume flags are accepted but
448
- // ignored — the SDK upload paths handle parallelism internally.
441
+ // commit). Resume semantics live at the apply-plan level (24h plan TTL);
442
+ // a future CLI redesign can expose that. The --concurrency and --no-resume
443
+ // flags are accepted but ignored the SDK upload paths handle parallelism
444
+ // internally.
449
445
  log(opts, { event: "start", key: destKey, size_bytes: stat.size });
450
446
  const bytes = new Uint8Array(readFileSync(filePath));
451
447
  const result = await getSdk().assets.put(projectId, destKey, { bytes }, {
452
448
  contentType: opts.contentType ?? guessContentType(destKey),
453
449
  visibility: opts.private ? "private" : "public",
454
450
  immutable: opts.immutable,
455
- // v1.50: thread caller-supplied metadata + EXIF policy through. The
451
+ // Threads caller-supplied metadata + EXIF policy through. The
456
452
  // SDK validates each value with the same error code (INVALID_ASSET_
457
453
  // METADATA / INVALID_EXIF_POLICY) the gateway returns, so a bad
458
454
  // --meta / --exif-policy fails fast without an HTTP roundtrip.
@@ -532,7 +528,7 @@ async function ls(argv) {
532
528
  const data = await getSdk().assets.ls(resolvedId, {
533
529
  prefix: opts.prefix ?? undefined,
534
530
  limit: opts.limit ?? undefined,
535
- // v1.50: forward sort + filter to the SDK. Cursor stays absent for
531
+ // Forward sort + filter to the SDK. Cursor stays absent for
536
532
  // first-page calls; agents pass `--cursor` for follow-ups but the
537
533
  // cursor is sort-pinned by the gateway so it doesn't accept a
538
534
  // separate `--cursor` flag here yet.
@@ -197,7 +197,7 @@ export const COMMAND_MANIFEST = [
197
197
  { path: ["org", "get"], positionals: [p("org_id")], projectScoped: false, legacyPositionalProject: false, minimalArgs: ["org_gate1"] },
198
198
  { path: ["org", "rename"], positionals: [p("org_id")], projectScoped: false, legacyPositionalProject: false, minimalArgs: ["org_gate1", "--name", "Gate"] },
199
199
  { path: ["org", "payout-wallet"], positionals: [p("org_id")], projectScoped: false, legacyPositionalProject: false, minimalArgs: ["org_gate1", "--wallet", "0x1111111111111111111111111111111111111111"] },
200
- // repo-first-onramp task 4.1 (design D6). `--org` (not a positional org_id
200
+ // `--org` (not a positional org_id
201
201
  // like rename/payout-wallet above) goes through resolveOrg's SHAPE
202
202
  // validation (a real UUID) — "org_gate1" fails that locally, so this needs
203
203
  // the same UUID-shaped fixture `org use` below already established.
@@ -255,13 +255,13 @@ export const COMMAND_MANIFEST = [
255
255
  { path: ["claims", "list"], positionals: [], projectScoped: true, legacyPositionalProject: false, minimalArgs: [], runStyle: "sub" },
256
256
  { path: ["claims", "release"], positionals: [p("claim_id")], projectScoped: true, legacyPositionalProject: false, minimalArgs: ["clm_1"], runStyle: "sub" },
257
257
 
258
- // ── gitvault — RETIRED (repo-surface-consolidation, design D7) ──────────
259
- // No manifest entries: `cli/lib/gitvault.mjs`'s dispatcher retired, and
260
- // every `gitvault <verb>` now answers a structural COMMAND_MOVED (or, for
261
- // `push`/`reconcile`, COMMAND_REMOVED) redirect that dispatches nothing —
262
- // see RESERVED_SUBCOMMANDS below, and "gitvault" in SKIPPED_FAMILIES.
258
+ // ── gitvault — no manifest entries ──────────────────────
259
+ // `cli/lib/gitvault.mjs`'s dispatcher handles every `gitvault <verb>` and
260
+ // answers a structural COMMAND_MOVED (or, for `push`/`reconcile`,
261
+ // COMMAND_REMOVED) redirect that dispatches nothing — see
262
+ // RESERVED_SUBCOMMANDS below, and "gitvault" in SKIPPED_FAMILIES.
263
263
 
264
- // ── repos (repo-surface-consolidation — the consolidated 12-verb family) ─
264
+ // ── repos (the consolidated 12-verb family) ─
265
265
  // Every verb needs a real principal keystore and, for most, an allocated
266
266
  // repo and a local git working tree, so the gate runs structural checks
267
267
  // only — an in-process behavioral run would either no-op against the
@@ -269,21 +269,19 @@ export const COMMAND_MANIFEST = [
269
269
  { path: ["repos", "create"], positionals: [p("name", { required: false })], projectScoped: false, legacyPositionalProject: false, minimalArgs: ["my-notes"], runStyle: "sub", skipBehavioral: "provisions a project, allocates a repo, and scaffolds a real git remote into cwd" },
270
270
  { path: ["repos", "list"], positionals: [], projectScoped: false, legacyPositionalProject: false, minimalArgs: [], runStyle: "sub", skipBehavioral: "reads the live bulk vaults-by-org route, or falls back to a live per-project walk" },
271
271
  { path: ["repos", "view"], positionals: [], projectScoped: true, legacyPositionalProject: false, minimalArgs: [], runStyle: "sub", skipBehavioral: "reads the local principal keystore and the live repo record" },
272
- // repo-surface-consolidation D2 (`gh repo rename`): absorbs the old
273
- // `repos name` same claim/rename, `--repo`/`--project` addressing added.
272
+ // (`gh repo rename`): claims/renames the per-org-unique address-form
273
+ // name, with `--repo`/`--project` addressing.
274
274
  { path: ["repos", "rename"], positionals: [p("new_name")], projectScoped: true, legacyPositionalProject: false, minimalArgs: ["my-notes"], runStyle: "sub", skipBehavioral: "claims a per-org-unique repo name against a live project" },
275
- { path: ["repos", "delete"], positionals: [], projectScoped: true, legacyPositionalProject: true, minimalArgs: [], runStyle: "sub", skipBehavioral: "irreversibly deletes a project after reading its live non-repo-resource state and vault generation count (design D9)" },
275
+ { path: ["repos", "delete"], positionals: [], projectScoped: true, legacyPositionalProject: true, minimalArgs: [], runStyle: "sub", skipBehavioral: "irreversibly deletes a project after reading its live non-repo-resource state and vault generation count" },
276
276
  { path: ["repos", "snapshot"], positionals: [], projectScoped: true, legacyPositionalProject: false, minimalArgs: [], runStyle: "sub", skipBehavioral: "captures the cwd git working tree and publishes a signed head" },
277
277
  { path: ["repos", "policy"], positionals: [p("repos_policy")], projectScoped: true, legacyPositionalProject: false, minimalArgs: ["required"], runStyle: "sub", skipBehavioral: "owner + step-up mutation of the live project's activation policy" },
278
- // design D4 — ONE flag-driven verb; `<destination>` is a real attribute
279
- // (not a sub-verb literal like the old `mirror set/remove/...`), so this
280
- // stays a single manifest entry.
278
+ // ONE flag-driven verb; `<destination>` is a real attribute (not a
279
+ // sub-verb literal), so this stays a single manifest entry.
281
280
  { path: ["repos", "mirror"], positionals: [p("destination", { required: false })], projectScoped: true, legacyPositionalProject: false, minimalArgs: [], runStyle: "sub", skipBehavioral: "reads/writes mirror destination config beside the keystore and may move real bytes into a customer-owned bucket" },
282
281
  { path: ["repos", "fsck"], positionals: [], projectScoped: true, legacyPositionalProject: false, minimalArgs: [], runStyle: "sub", skipBehavioral: "walks the live head chain and materializes the ref map against the keystore's local pins" },
283
282
  { path: ["repos", "gc"], positionals: [], projectScoped: true, legacyPositionalProject: false, minimalArgs: [], runStyle: "sub", skipBehavioral: "publishes a checkpoint under a maintenance lease and materializes the live vault head to enumerate retention roots" },
284
- // `access repair` is a nested sub-verb literal (same shape the old
285
- // `gitvault mirror set/remove/...` used) two manifest entries, one
286
- // dispatched `run("access", ...)` case in repos.mjs, matching precedent.
283
+ // `access repair` is a nested sub-verb literal two manifest entries,
284
+ // one dispatched `run("access", ...)` case in repos.mjs.
287
285
  { path: ["repos", "access"], positionals: [], projectScoped: true, legacyPositionalProject: false, minimalArgs: [], runStyle: "sub", skipBehavioral: "reads the live org encryption-key directory + vault envelope recipients" },
288
286
  { path: ["repos", "access", "repair"], positionals: [], projectScoped: true, legacyPositionalProject: false, minimalArgs: [], runStyle: "sub", skipBehavioral: "always refuses — gated on gitvault-human-envelopes' epoch-rotation work, not shipped yet" },
289
287
  { path: ["repos", "recover"], positionals: [p("source")], projectScoped: false, legacyPositionalProject: false, minimalArgs: ["s3://example-mirror-bucket", "--out", "__SCRATCH_DIR__/recover-out"], runStyle: "sub", skipBehavioral: "materializes a git repository from a mirror source, offline, with no server call" },
@@ -439,7 +437,7 @@ export const COMMAND_MANIFEST = [
439
437
  { path: ["service", "health"], positionals: [], projectScoped: false, legacyPositionalProject: false, minimalArgs: [] },
440
438
  { path: ["cache", "inspect"], positionals: [p("url")], projectScoped: false, legacyPositionalProject: false, minimalArgs: ["https://example.com/"] },
441
439
  { path: ["cache", "invalidate"], positionals: [p("url", { required: false })], projectScoped: false, legacyPositionalProject: false, minimalArgs: ["--all", "--host", "example.com"] },
442
- // projectScoped (kychee-com/run402#566): --project targets the gitvault
440
+ // projectScoped: --project targets the gitvault
443
441
  // check only (see doctor.mjs's own HELP) — every other check stays
444
442
  // wallet/machine-wide, but the gate's contract is "accepts --project
445
443
  // without rejecting it," which this satisfies.
@@ -461,13 +459,13 @@ export const SKIPPED_FAMILIES = {
461
459
  // Split into `deliveries` / `contacts` / `subscriptions`; every subcommand
462
460
  // answers COMMAND_REMOVED naming its successor.
463
461
  "notifications": "reserved group; split by legible-cli-surface",
464
- // repo-surface-consolidation D7: the dispatcher retired. Every
465
- // `gitvault <verb>` answers COMMAND_MOVED/COMMAND_REMOVED (see
466
- // RESERVED_SUBCOMMANDS below for the per-verb list) the family stays
467
- // dispatched in cli.mjs (so the redirect fires instead of UNKNOWN_COMMAND)
468
- // but has zero manifest entries, since a redirect dispatches nothing.
462
+ // The gitvault dispatcher answers COMMAND_MOVED/COMMAND_REMOVED for every
463
+ // `gitvault <verb>` (see RESERVED_SUBCOMMANDS below for the per-verb list)
464
+ // the family stays dispatched in cli.mjs (so the redirect fires instead
465
+ // of UNKNOWN_COMMAND) but has zero manifest entries, since a redirect
466
+ // dispatches nothing.
469
467
  "gitvault": "retired; every subcommand answers COMMAND_MOVED/COMMAND_REMOVED naming its `repos`/git successor",
470
- // `repo` singular resolves identically to `repos` (design D1) — same
468
+ // `repo` singular resolves identically to `repos` — same
471
469
  // module, same case block in cli.mjs, so it needs no manifest of its own.
472
470
  "repo": "alias for `repos`, resolves identically (design D1)",
473
471
  };
@@ -481,8 +479,8 @@ export const SKIPPED_FAMILIES = {
481
479
  * belongs in no capability mapping, so the inventory gate must not demand one.
482
480
  *
483
481
  * The family-level equivalent is SKIPPED_FAMILIES above. This exists because
484
- * legible-cli-surface retired four spellings INSIDE a family rather than a
485
- * whole family, which the family list could not express.
482
+ * some spellings are retired INSIDE a family rather than as a whole family,
483
+ * which the family list cannot express.
486
484
  */
487
485
  export const RESERVED_SUBCOMMANDS = {
488
486
  "rooms:who": "renamed to `rooms join` — an interrogative must not name a write",
@@ -495,7 +493,7 @@ export const RESERVED_SUBCOMMANDS = {
495
493
  "rooms:get": "moved to `messages get` — the verb acts on a message",
496
494
  "rooms:ack": "moved to `messages ack` — the verb acts on a message",
497
495
  "escalations:contacts": "merged into `contacts` — the ladder and Telegram channels are one question",
498
- // repo-surface-consolidation D7: every `gitvault <verb>` spelling. Nine
496
+ // Every `gitvault <verb>` spelling. Nine
499
497
  // answer COMMAND_MOVED naming their `repos` successor; `push` and
500
498
  // `reconcile` answer COMMAND_REMOVED (no equivalent successor for either —
501
499
  // `push`'s one-release alias window is over, `reconcile` was a workaround
package/lib/deploy-v2.mjs CHANGED
@@ -1400,16 +1400,13 @@ const CI_DEPLOY_ERROR_GUIDANCE = {
1400
1400
  };
1401
1401
 
1402
1402
  /**
1403
- * The gitvault advisory rewrite is RETIRED (change `gitvault-deploy-lane`,
1404
- * design D4). `GITVAULT_DEPLOY_LANE = "unsupported"` and the client-side
1405
- * rewrite of `GITVAULT_CLIENT_UPGRADE_REQUIRED` existed only for as long as no
1406
- * published client could satisfy `gitvault_policy: required`. This one can:
1407
- * `applyCmd` deploys through `applyWithGitvault`, which declares
1408
- * `{capture_id, snapshot_oid_hmac}` at plan time and presents an activation
1409
- * token at commit. The gateway's envelope — `upgrade_client` first, then
1410
- * `grandfather_policy` — is now TRUE as written, so it is relayed untouched;
1411
- * re-authoring it here would be the client lying in the opposite direction.
1412
- * `cli-deploy-gitvault-lane.test.mjs` is the successor gate.
1403
+ * The gateway's envelope for gitvault deploy errors `upgrade_client` first,
1404
+ * then `grandfather_policy` is relayed untouched: `applyCmd` deploys
1405
+ * through `applyWithGitvault`, which declares `{capture_id,
1406
+ * snapshot_oid_hmac}` at plan time and presents an activation token at
1407
+ * commit, satisfying `gitvault_policy: required`, so no client-side rewrite
1408
+ * of the envelope is needed. `cli-deploy-gitvault-lane.test.mjs` is the gate
1409
+ * for this behavior.
1413
1410
  */
1414
1411
  function reportDeployApplyError(err, useGithubActionsOidc) {
1415
1412
  const warningEnhanced = enhanceDeployWarningError(err);
package/lib/doctor.mjs CHANGED
@@ -568,6 +568,11 @@ export async function run(sub, args = []) {
568
568
  pending_overrides: gv.pending_overrides,
569
569
  pins: gv.pins,
570
570
  remote: gv.remote,
571
+ // dogfood item 2: `null` (unknown) or <= 1 means the single-principal
572
+ // V0-A terminal-loss statement below is honest; >= 2 means the SDK
573
+ // already proved a second covering recipient, so the hint switches
574
+ // to the durability sentence instead of the terminal-loss claim.
575
+ covering_recipients: gv.covering_recipients ?? null,
571
576
  };
572
577
  const gaps = [];
573
578
  // The one that actually breaks the next deploy: the project demands a
@@ -632,7 +637,9 @@ export async function run(sub, args = []) {
632
637
  value: gaps.length > 0 ? { ...value, gaps } : value,
633
638
  hint: gv.vault === null
634
639
  ? `No vault for this project (that is a normal shape). Allocate one with 'run402 repos create --project <id>'. Keystore: ${gv.keystore.root}`
635
- : `Back up ${gv.keystore.root} — whole-machine or whole-keystore loss is terminal for vault history.`,
640
+ : gv.durability_statement
641
+ ? `Back up ${gv.keystore.root} anyway — ${gv.durability_statement} (covering_recipients: ${gv.covering_recipients})`
642
+ : `Back up ${gv.keystore.root} — whole-machine or whole-keystore loss is terminal for vault history.`,
636
643
  });
637
644
  } catch (err) {
638
645
  // A gateway without gitvault, an unreachable API, or a project this
@@ -1,19 +1,17 @@
1
1
  /**
2
2
  * Shared "which vault does this repo mean" resolution for `run402 gitvault`
3
- * and `run402 doctor`'s gitvault check (repo-first-onramp follow-up,
4
- * kychee-com/run402#559's design gap): gitvault verbs were purely
5
- * active-project-scoped even when run standing inside a repository that
6
- * already names its own vault via a pinned repo id or a run402/origin
7
- * remote — git muscle memory says a command run inside a repo acts on THAT
8
- * repo, and a stale active-project pointer silently targeted a DIFFERENT
9
- * one instead (GITVAULT_ACCESS_DENIED, or worse, a silently WRONG vault).
3
+ * and `run402 doctor`'s gitvault check. When a verb runs standing inside a
4
+ * repository that already names its own vault via a pinned repo id or a
5
+ * run402/origin remote, targeting prefers that repo over the active-project
6
+ * pointer git muscle memory says a command run inside a repo acts on THAT
7
+ * repo.
10
8
  *
11
9
  * Targeting order for a verb run standing inside a git repository, highest
12
10
  * first:
13
11
  * 1. an explicit --repo/--project flag (owned by each call site — this
14
12
  * module supplies only the fallback chain beneath it, plus the
15
13
  * mismatch warning against tier 3)
16
- * 2. the 4.38.0 pin (`r402.repoId` in local git config) — addresses the
14
+ * 2. the pinned `r402.repoId` in local git config — addresses the
17
15
  * vault by repo_id directly, no network read at all
18
16
  * 3. the repo's run402/origin remote address — id-form is parsed
19
17
  * directly out of the address string (free, no network); slug-form is
@@ -24,7 +22,7 @@
24
22
  * 5. the profile's active project
25
23
  *
26
24
  * Outside a repository (or when repo detection itself fails), only tiers 4
27
- * and 5 apply — unchanged from before this module existed.
25
+ * and 5 apply.
28
26
  *
29
27
  * ARCHITECTURAL NOTE: this is CLI-edge policy (which flag/env/file wins),
30
28
  * not gitvault protocol behavior — the same class of concern
package/lib/gitvault.mjs CHANGED
@@ -1,18 +1,17 @@
1
1
  /**
2
- * `run402 gitvault` — RETIRED (repo-surface-consolidation, design D7).
2
+ * `run402 gitvault` — retired from the CLI; every spelling answers a
3
+ * structured error naming its `repos`/git successor.
3
4
  *
4
- * The 19-command dispatcher this module used to hold is gone. Every old
5
- * spelling now answers a proper stderr JSON error envelope: typed
5
+ * Every spelling answers a proper stderr JSON error envelope: typed
6
6
  * `next_actions`, non-zero exit, EMPTY stdout — never silence, never new
7
7
  * behavior. Renamed verbs answer `COMMAND_MOVED` naming their `repos`
8
8
  * successor; verbs with no behavioral successor answer `COMMAND_REMOVED`
9
- * (never a `COMMAND_MOVED` that would lie about equivalence design
10
- * D7/D10). The freed spellings are RESERVED for one release, never
11
- * re-pointed at different behavior — the `rooms`→`messages` precedent.
9
+ * (never a `COMMAND_MOVED` that would lie about equivalence). The freed
10
+ * spellings are never re-pointed at different behavior.
12
11
  *
13
12
  * `gitvault` itself survives only as protocol/infrastructure language: the
14
- * SDK keeps `r.gitvault.*` (design D1 — "gitvault is what the thing IS;
15
- * repos is what the user HAS"). This module's one surviving export,
13
+ * SDK keeps `r.gitvault.*` ("gitvault is what the thing IS; repos is what
14
+ * the user HAS"). This module's one surviving export,
16
15
  * `printKeystoreLocation`, is a shared print helper `cli/lib/repos.mjs`
17
16
  * still composes — moving it there instead would make repos.mjs restate
18
17
  * logic this file already owns for zero benefit.
@@ -1,18 +1,14 @@
1
1
  /**
2
- * `run402 notifications` — RETIRED (legible-cli-surface).
3
- *
4
- * The group was two nouns in one coat: `list`/`get` read delivery RECORDS
5
- * while `preferences`/`channels`/`rules` were the CONFIGURATION producing
6
- * them. It has been split along that line:
2
+ * `run402 notifications` — tombstone dispatcher. Delivery RECORDS and the
3
+ * CONFIGURATION producing them live under separate nouns:
7
4
  *
8
5
  * notifications list|get -> deliveries list|get
9
6
  * notifications channels -> contacts (merged with escalations contacts)
10
7
  * notifications rules -> subscriptions
11
8
  * notifications preferences -> contacts preferences
12
9
  *
13
- * Reserved, not aliased (design D3): each subcommand names its successor so
14
- * one failed call teaches the new model, where an alias would teach the old
15
- * one forever.
10
+ * Reserved, not aliased: each subcommand names its successor so one failed
11
+ * call teaches the new model, where an alias would teach the old one forever.
16
12
  */
17
13
  import { fail } from "./sdk-errors.mjs";
18
14
  import { hasHelp } from "./argparse.mjs";
package/lib/operator.mjs CHANGED
@@ -14,7 +14,7 @@
14
14
  *
15
15
  * Agent-first: JSON to stdout. `login` additionally prints the verification URL
16
16
  * + user code to stderr (human-in-the-loop) and degrades gracefully when not a
17
- * TTY. Gated on the gateway device-auth bridge (kychee-com/run402-private#443).
17
+ * TTY. Gated on the gateway device-auth bridge.
18
18
  */
19
19
 
20
20
  import { setTimeout as sleep } from "node:timers/promises";
package/lib/org.mjs CHANGED
@@ -438,9 +438,9 @@ async function payoutWallet(args) {
438
438
  }
439
439
 
440
440
  /**
441
- * `run402 org slug <slug>` — claim or rename the org's address-form slug
442
- * (repo-first-onramp design D6). Owner-only, and a genesis claim spends a
443
- * one-time claim fee — this is a PAID, side-effecting mutation, so it
441
+ * `run402 org slug <slug>` — claim or rename the org's address-form slug.
442
+ * Owner-only, and a genesis claim spends a one-time claim fee — this is a
443
+ * PAID, side-effecting mutation, so it
444
444
  * requires `Idempotency-Key`; the SDK generates one client-side when
445
445
  * `--idempotency-key` is omitted, so a retried call after a dropped response
446
446
  * can never double-bill.