@staff0rd/assist 0.492.0 → 0.494.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/index.js CHANGED
@@ -6,7 +6,7 @@ import { Command } from "commander";
6
6
  // package.json
7
7
  var package_default = {
8
8
  name: "@staff0rd/assist",
9
- version: "0.492.0",
9
+ version: "0.494.0",
10
10
  type: "module",
11
11
  main: "dist/index.js",
12
12
  bin: {
@@ -416,7 +416,7 @@ function resolveRepoWriteLabel(globalRaw, origin) {
416
416
  }
417
417
 
418
418
  // src/shared/types.ts
419
- import { z as z2 } from "zod";
419
+ import { z as z3 } from "zod";
420
420
 
421
421
  // src/shared/runConfigSchema.ts
422
422
  import { z } from "zod";
@@ -444,182 +444,194 @@ var runLinkSchema = z.strictObject({
444
444
  prefix: z.string()
445
445
  });
446
446
 
447
+ // src/shared/secretConfigValue.ts
448
+ import { z as z2 } from "zod";
449
+ var SECRET_META_KEY = "assistSecret";
450
+ function secretConfigValue(schema2) {
451
+ return schema2.meta({ [SECRET_META_KEY]: true });
452
+ }
453
+ function isSecretSchemaNode(node) {
454
+ const meta = z2.globalRegistry.get(node);
455
+ return meta?.[SECRET_META_KEY] === true;
456
+ }
457
+
447
458
  // src/shared/types.ts
448
- var transcriptConfigSchema = z2.strictObject({
449
- vttDir: z2.string(),
450
- transcriptsDir: z2.string(),
451
- summaryDir: z2.string()
459
+ var transcriptConfigSchema = z3.strictObject({
460
+ vttDir: z3.string(),
461
+ transcriptsDir: z3.string(),
462
+ summaryDir: z3.string()
452
463
  });
453
464
  var DEFAULT_WAKE_WORDS = ["computer"];
454
465
  var DEFAULT_MODELS_DIR = "~/.assist/voice/models";
455
466
  var DEFAULT_BACKUP_DIR = "~/.assist/backups";
456
467
  var DEFAULT_CLONE_DIR = "~/git";
457
468
  var assistConfigShape = {
458
- backup: z2.strictObject({
459
- dir: z2.string().default(DEFAULT_BACKUP_DIR)
469
+ backup: z3.strictObject({
470
+ dir: z3.string().default(DEFAULT_BACKUP_DIR)
460
471
  }).default({ dir: DEFAULT_BACKUP_DIR }),
461
- clone: z2.strictObject({
462
- baseDir: z2.string().default(DEFAULT_CLONE_DIR)
472
+ clone: z3.strictObject({
473
+ baseDir: z3.string().default(DEFAULT_CLONE_DIR)
463
474
  }).default({ baseDir: DEFAULT_CLONE_DIR }),
464
- commit: z2.strictObject({
465
- conventional: z2.boolean().default(false),
466
- pull: z2.boolean().default(false),
467
- push: z2.boolean().default(false),
468
- expectedBranch: z2.string().optional()
475
+ commit: z3.strictObject({
476
+ conventional: z3.boolean().default(false),
477
+ pull: z3.boolean().default(false),
478
+ push: z3.boolean().default(false),
479
+ expectedBranch: z3.string().optional()
469
480
  }).default({ conventional: false, pull: false, push: false }),
470
- branch: z2.strictObject({
471
- prefix: z2.string().optional(),
472
- defaultBranch: z2.string().optional()
481
+ branch: z3.strictObject({
482
+ prefix: z3.string().optional(),
483
+ defaultBranch: z3.string().optional()
473
484
  }).optional(),
474
- devlog: z2.strictObject({
475
- name: z2.string().optional(),
476
- ignore: z2.array(z2.string()).optional(),
477
- skip: z2.record(z2.string(), z2.array(z2.string())).optional()
485
+ devlog: z3.strictObject({
486
+ name: z3.string().optional(),
487
+ ignore: z3.array(z3.string()).optional(),
488
+ skip: z3.record(z3.string(), z3.array(z3.string())).optional()
478
489
  }).optional(),
479
- notify: z2.strictObject({
480
- enabled: z2.boolean().default(true)
490
+ notify: z3.strictObject({
491
+ enabled: z3.boolean().default(true)
481
492
  }).default({ enabled: true }),
482
- complexity: z2.strictObject({
483
- ignore: z2.array(z2.string()).default(["**/*test.ts*"])
493
+ complexity: z3.strictObject({
494
+ ignore: z3.array(z3.string()).default(["**/*test.ts*"])
484
495
  }).default({ ignore: ["**/*test.ts*"] }),
485
- hardcodedColors: z2.strictObject({
486
- ignore: z2.array(z2.string()).default([])
496
+ hardcodedColors: z3.strictObject({
497
+ ignore: z3.array(z3.string()).default([])
487
498
  }).optional(),
488
- blockCodeComments: z2.strictObject({
489
- ignore: z2.array(z2.string()).default([])
499
+ blockCodeComments: z3.strictObject({
500
+ ignore: z3.array(z3.string()).default([])
490
501
  }).optional(),
491
- restructure: z2.strictObject({
492
- ignore: z2.array(z2.string()).default([])
502
+ restructure: z3.strictObject({
503
+ ignore: z3.array(z3.string()).default([])
493
504
  }).optional(),
494
- jira: z2.strictObject({
495
- acField: z2.string().default("customfield_11937")
505
+ jira: z3.strictObject({
506
+ acField: z3.string().default("customfield_11937")
496
507
  }).optional(),
497
- roam: z2.strictObject({
498
- clientId: z2.string(),
499
- clientSecret: z2.string(),
500
- accessToken: z2.string().optional(),
501
- refreshToken: z2.string().optional(),
502
- tokenExpiresAt: z2.number().optional()
508
+ roam: z3.strictObject({
509
+ clientId: secretConfigValue(z3.string()),
510
+ clientSecret: secretConfigValue(z3.string()),
511
+ accessToken: secretConfigValue(z3.string()).optional(),
512
+ refreshToken: secretConfigValue(z3.string()).optional(),
513
+ tokenExpiresAt: z3.number().optional()
503
514
  }).optional(),
504
- prs: z2.strictObject({
505
- slack: z2.string().optional(),
506
- required: z2.boolean().default(false),
507
- promptJira: z2.boolean().default(false)
515
+ prs: z3.strictObject({
516
+ slack: z3.string().optional(),
517
+ required: z3.boolean().default(false),
518
+ promptJira: z3.boolean().default(false)
508
519
  }).optional(),
509
- worktree: z2.strictObject({
510
- enabled: z2.boolean().default(false),
511
- trunk: z2.boolean().default(false),
512
- includeDrafts: z2.boolean().default(false),
513
- root: z2.string().optional(),
514
- install: z2.union([z2.boolean(), z2.string()]).default(true),
515
- commitBeforeManualChecks: z2.boolean().default(false),
516
- copy: z2.array(z2.string()).default([
520
+ worktree: z3.strictObject({
521
+ enabled: z3.boolean().default(false),
522
+ trunk: z3.boolean().default(false),
523
+ includeDrafts: z3.boolean().default(false),
524
+ root: z3.string().optional(),
525
+ install: z3.union([z3.boolean(), z3.string()]).default(true),
526
+ commitBeforeManualChecks: z3.boolean().default(false),
527
+ copy: z3.array(z3.string()).default([
517
528
  ".env",
518
529
  "settings.local.json",
519
530
  ".claude/settings.local.json"
520
531
  ])
521
532
  }).optional(),
522
- run: z2.array(z2.union([runConfigSchema, runLinkSchema])).optional(),
523
- subtasks: z2.array(
524
- z2.strictObject({
525
- title: z2.string(),
526
- description: z2.string().optional()
533
+ run: z3.array(z3.union([runConfigSchema, runLinkSchema])).optional(),
534
+ subtasks: z3.array(
535
+ z3.strictObject({
536
+ title: z3.string(),
537
+ description: z3.string().optional()
527
538
  })
528
539
  ).optional(),
529
540
  transcript: transcriptConfigSchema.optional(),
530
- cliReadVerbs: z2.record(z2.string(), z2.array(z2.string())).optional(),
531
- dotnet: z2.strictObject({
532
- inspect: z2.strictObject({
533
- suppress: z2.array(z2.string()).default([])
541
+ cliReadVerbs: z3.record(z3.string(), z3.array(z3.string())).optional(),
542
+ dotnet: z3.strictObject({
543
+ inspect: z3.strictObject({
544
+ suppress: z3.array(z3.string()).default([])
534
545
  }).default({ suppress: [] })
535
546
  }).optional(),
536
- ravendb: z2.strictObject({
537
- connections: z2.array(
538
- z2.strictObject({
539
- name: z2.string(),
540
- url: z2.string(),
541
- database: z2.string(),
542
- apiKeyRef: z2.string()
547
+ ravendb: z3.strictObject({
548
+ connections: z3.array(
549
+ z3.strictObject({
550
+ name: z3.string(),
551
+ url: z3.string(),
552
+ database: z3.string(),
553
+ apiKeyRef: z3.string()
543
554
  })
544
555
  ).default([]),
545
- defaultConnection: z2.string().optional()
556
+ defaultConnection: z3.string().optional()
546
557
  }).optional(),
547
- seq: z2.strictObject({
548
- connections: z2.array(
549
- z2.strictObject({
550
- name: z2.string(),
551
- url: z2.string(),
552
- apiToken: z2.string()
558
+ seq: z3.strictObject({
559
+ connections: z3.array(
560
+ z3.strictObject({
561
+ name: z3.string(),
562
+ url: z3.string(),
563
+ apiToken: secretConfigValue(z3.string())
553
564
  })
554
565
  ).default([]),
555
- defaultConnection: z2.string().optional()
566
+ defaultConnection: z3.string().optional()
556
567
  }).optional(),
557
- sql: z2.strictObject({
558
- connections: z2.array(
559
- z2.strictObject({
560
- name: z2.string(),
561
- server: z2.string(),
562
- port: z2.number(),
563
- user: z2.string(),
564
- password: z2.string(),
565
- database: z2.string()
568
+ sql: z3.strictObject({
569
+ connections: z3.array(
570
+ z3.strictObject({
571
+ name: z3.string(),
572
+ server: z3.string(),
573
+ port: z3.number(),
574
+ user: z3.string(),
575
+ password: secretConfigValue(z3.string()),
576
+ database: z3.string()
566
577
  })
567
578
  ).default([]),
568
- defaultConnection: z2.string().optional()
579
+ defaultConnection: z3.string().optional()
569
580
  }).optional(),
570
- screenshot: z2.strictObject({
571
- outputDir: z2.string().default("./screenshots")
581
+ screenshot: z3.strictObject({
582
+ outputDir: z3.string().default("./screenshots")
572
583
  }).default({ outputDir: "./screenshots" }),
573
- sessions: z2.strictObject({
584
+ sessions: z3.strictObject({
574
585
  // why: Windows .claude/projects root as seen from WSL (e.g. /mnt/c/Users/<user>/.claude/projects); when set its transcripts are discovered and tagged windows-origin
575
- windowsProjectsRoot: z2.string().optional(),
586
+ windowsProjectsRoot: z3.string().optional(),
576
587
  // why: host the WSL daemon dials to reach the native Windows daemon over TCP (WSL can't use the Windows named pipe); defaults to 127.0.0.1 (WSL2 mirrored networking). NAT-mode users set the Windows host IP.
577
- windowsDaemonHost: z2.string().optional(),
588
+ windowsDaemonHost: z3.string().optional(),
578
589
  // why: TCP port the native Windows daemon listens on for the WSL bridge; defaults to 51764
579
- windowsDaemonPort: z2.number().optional(),
580
- windowsVersionCheck: z2.enum(["block", "warn", "off"]).default("block"),
581
- includeCommittedChanges: z2.boolean().default(true),
582
- topBar: z2.boolean().default(true),
583
- floatWaiting: z2.boolean().default(true),
584
- floatWaitingAfterMs: z2.number().default(5e3)
590
+ windowsDaemonPort: z3.number().optional(),
591
+ windowsVersionCheck: z3.enum(["block", "warn", "off"]).default("block"),
592
+ includeCommittedChanges: z3.boolean().default(true),
593
+ topBar: z3.boolean().default(true),
594
+ floatWaiting: z3.boolean().default(true),
595
+ floatWaitingAfterMs: z3.number().default(5e3),
596
+ maxLive: z3.number().default(24)
585
597
  }).optional(),
586
- database: z2.strictObject({
587
- url: z2.string().optional()
598
+ database: z3.strictObject({
599
+ url: secretConfigValue(z3.string()).optional()
588
600
  }).default({}),
589
- mermaid: z2.strictObject({
590
- krokiUrl: z2.string().default("https://kroki.io")
601
+ mermaid: z3.strictObject({
602
+ krokiUrl: z3.string().default("https://kroki.io")
591
603
  }).default({ krokiUrl: "https://kroki.io" }),
592
- deny: z2.array(
593
- z2.strictObject({
594
- pattern: z2.string(),
595
- message: z2.string()
604
+ deny: z3.array(
605
+ z3.strictObject({
606
+ pattern: z3.string(),
607
+ message: z3.string()
596
608
  })
597
609
  ).optional(),
598
- forbiddenStrings: z2.array(
599
- z2.strictObject({
600
- file: z2.string(),
601
- paths: z2.array(z2.string()),
602
- disallowed: z2.string()
610
+ forbiddenStrings: z3.array(
611
+ z3.strictObject({
612
+ file: z3.string(),
613
+ paths: z3.array(z3.string()),
614
+ disallowed: z3.string()
603
615
  })
604
616
  ).optional(),
605
- sync: z2.strictObject({
606
- autoConfirm: z2.boolean().default(false)
617
+ sync: z3.strictObject({
618
+ autoConfirm: z3.boolean().default(false)
607
619
  }).default({ autoConfirm: false }),
608
- harness: z2.strictObject({
609
- engine: z2.enum(["claude", "codex", "pi"]).default("claude"),
610
- exposeCodexActions: z2.boolean().optional(),
611
- exposePiActions: z2.boolean().optional()
620
+ harness: z3.strictObject({
621
+ engine: z3.enum(["claude", "codex", "pi"]).default("claude"),
622
+ exposeCodexActions: z3.boolean().optional(),
623
+ exposePiActions: z3.boolean().optional()
612
624
  }).default({ engine: "claude" }),
613
- voice: z2.strictObject({
614
- wakeWords: z2.array(z2.string()).default(DEFAULT_WAKE_WORDS),
615
- mic: z2.string().optional(),
616
- cwd: z2.string().optional(),
617
- modelsDir: z2.string().default(DEFAULT_MODELS_DIR),
618
- lockDir: z2.string().optional(),
619
- submitWindows: z2.array(z2.string()).optional(),
620
- models: z2.strictObject({
621
- vad: z2.string().optional(),
622
- smartTurn: z2.string().optional()
625
+ voice: z3.strictObject({
626
+ wakeWords: z3.array(z3.string()).default(DEFAULT_WAKE_WORDS),
627
+ mic: z3.string().optional(),
628
+ cwd: z3.string().optional(),
629
+ modelsDir: z3.string().default(DEFAULT_MODELS_DIR),
630
+ lockDir: z3.string().optional(),
631
+ submitWindows: z3.array(z3.string()).optional(),
632
+ models: z3.strictObject({
633
+ vad: z3.string().optional(),
634
+ smartTurn: z3.string().optional()
623
635
  }).default({})
624
636
  }).default({
625
637
  wakeWords: DEFAULT_WAKE_WORDS,
@@ -627,10 +639,10 @@ var assistConfigShape = {
627
639
  models: {}
628
640
  })
629
641
  };
630
- var repoConfigSchema = z2.strictObject(assistConfigShape).partial();
631
- var assistConfigSchema = z2.strictObject({
642
+ var repoConfigSchema = z3.strictObject(assistConfigShape).partial();
643
+ var assistConfigSchema = z3.strictObject({
632
644
  ...assistConfigShape,
633
- repos: z2.record(z2.string(), repoConfigSchema).optional()
645
+ repos: z3.record(z3.string(), repoConfigSchema).optional()
634
646
  });
635
647
 
636
648
  // src/shared/loadConfigFrom.ts
@@ -3812,10 +3824,12 @@ function opaqueConfigNode(inner, base) {
3812
3824
  }
3813
3825
  function build(node, path71) {
3814
3826
  const { inner, defaultValue, optional } = unwrapSchemaNode(node);
3827
+ const secret = isSecretSchemaNode(node) || isSecretSchemaNode(inner);
3815
3828
  const base = {
3816
3829
  path: path71,
3817
3830
  ...optional ? { optional: true } : {},
3818
- ...defaultValue === void 0 ? {} : { defaultValue }
3831
+ ...defaultValue === void 0 ? {} : { defaultValue },
3832
+ ...secret ? { secret: true } : {}
3819
3833
  };
3820
3834
  return scalarConfigNode(inner, base) ?? objectConfigNode(inner, base, build) ?? listConfigNode(inner, base, build) ?? recordConfigNode(inner, base, build) ?? unionOfObjectsConfigNode(inner, base, build) ?? opaqueConfigNode(inner, base);
3821
3835
  }
@@ -3868,6 +3882,7 @@ function toLeaf(node) {
3868
3882
  }
3869
3883
  if (node.kind === "scalarList") leaf.itemType = node.itemType;
3870
3884
  if (node.defaultValue !== void 0) leaf.defaultValue = node.defaultValue;
3885
+ if (node.secret) leaf.secret = true;
3871
3886
  return leaf;
3872
3887
  }
3873
3888
  function flatten(node, out) {
@@ -6379,92 +6394,92 @@ async function loadAllItems(orm, origin) {
6379
6394
  import { readFileSync as readFileSync15 } from "fs";
6380
6395
 
6381
6396
  // src/commands/backlog/types.ts
6382
- import { z as z3 } from "zod";
6383
- var backlogStatusSchema = z3.enum(["todo", "in-progress", "done", "wontdo"]);
6384
- var backlogTypeSchema = z3.enum(["story", "bug"]);
6385
- var planTaskSchema = z3.object({
6386
- task: z3.string()
6397
+ import { z as z4 } from "zod";
6398
+ var backlogStatusSchema = z4.enum(["todo", "in-progress", "done", "wontdo"]);
6399
+ var backlogTypeSchema = z4.enum(["story", "bug"]);
6400
+ var planTaskSchema = z4.object({
6401
+ task: z4.string()
6387
6402
  }).strip();
6388
- var planPhaseSchema = z3.strictObject({
6389
- name: z3.string(),
6390
- tasks: z3.array(planTaskSchema),
6391
- manualChecks: z3.array(z3.string()).optional()
6403
+ var planPhaseSchema = z4.strictObject({
6404
+ name: z4.string(),
6405
+ tasks: z4.array(planTaskSchema),
6406
+ manualChecks: z4.array(z4.string()).optional()
6392
6407
  });
6393
- var phaseUsageSchema = z3.strictObject({
6394
- phaseIdx: z3.number(),
6395
- tokensUp: z3.number(),
6396
- tokensDown: z3.number(),
6397
- activeMs: z3.number(),
6398
- peakContextPct: z3.number()
6408
+ var phaseUsageSchema = z4.strictObject({
6409
+ phaseIdx: z4.number(),
6410
+ tokensUp: z4.number(),
6411
+ tokensDown: z4.number(),
6412
+ activeMs: z4.number(),
6413
+ peakContextPct: z4.number()
6399
6414
  });
6400
- var phaseSessionSchema = z3.strictObject({
6401
- phaseIdx: z3.number(),
6402
- claudeSessionId: z3.string(),
6403
- hostname: z3.string(),
6404
- osUser: z3.string()
6415
+ var phaseSessionSchema = z4.strictObject({
6416
+ phaseIdx: z4.number(),
6417
+ claudeSessionId: z4.string(),
6418
+ hostname: z4.string(),
6419
+ osUser: z4.string()
6405
6420
  });
6406
- var phaseUsageTotalSchema = z3.strictObject({
6407
- tokensUp: z3.number(),
6408
- tokensDown: z3.number(),
6409
- activeMs: z3.number(),
6410
- peakContextPct: z3.number()
6421
+ var phaseUsageTotalSchema = z4.strictObject({
6422
+ tokensUp: z4.number(),
6423
+ tokensDown: z4.number(),
6424
+ activeMs: z4.number(),
6425
+ peakContextPct: z4.number()
6411
6426
  });
6412
- var subtaskStatusSchema = z3.enum(["todo", "in-progress", "done"]);
6413
- var subtaskSchema = z3.strictObject({
6414
- title: z3.string(),
6415
- description: z3.string().optional(),
6427
+ var subtaskStatusSchema = z4.enum(["todo", "in-progress", "done"]);
6428
+ var subtaskSchema = z4.strictObject({
6429
+ title: z4.string(),
6430
+ description: z4.string().optional(),
6416
6431
  status: subtaskStatusSchema.default("todo")
6417
6432
  });
6418
- var backlogCommentTypeSchema = z3.enum(["comment", "summary"]);
6419
- var backlogCommentSchema = z3.strictObject({
6420
- id: z3.number().optional(),
6421
- text: z3.string(),
6422
- phase: z3.number().optional(),
6423
- timestamp: z3.string(),
6433
+ var backlogCommentTypeSchema = z4.enum(["comment", "summary"]);
6434
+ var backlogCommentSchema = z4.strictObject({
6435
+ id: z4.number().optional(),
6436
+ text: z4.string(),
6437
+ phase: z4.number().optional(),
6438
+ timestamp: z4.string(),
6424
6439
  type: backlogCommentTypeSchema
6425
6440
  });
6426
- var gitRefKindSchema = z3.enum([
6441
+ var gitRefKindSchema = z4.enum([
6427
6442
  "branch",
6428
6443
  "commit",
6429
6444
  "commit-parent",
6430
6445
  "pr",
6431
6446
  "slack"
6432
6447
  ]);
6433
- var gitRefSchema = z3.strictObject({
6448
+ var gitRefSchema = z4.strictObject({
6434
6449
  kind: gitRefKindSchema,
6435
- ref: z3.string(),
6436
- title: z3.string().optional(),
6437
- url: z3.string().optional(),
6438
- state: z3.string().optional(),
6439
- createdAt: z3.string().optional()
6450
+ ref: z4.string(),
6451
+ title: z4.string().optional(),
6452
+ url: z4.string().optional(),
6453
+ state: z4.string().optional(),
6454
+ createdAt: z4.string().optional()
6440
6455
  });
6441
- var backlogLinkTypeSchema = z3.enum(["relates-to", "depends-on"]);
6442
- var backlogLinkSchema = z3.strictObject({
6456
+ var backlogLinkTypeSchema = z4.enum(["relates-to", "depends-on"]);
6457
+ var backlogLinkSchema = z4.strictObject({
6443
6458
  type: backlogLinkTypeSchema,
6444
- targetId: z3.number()
6459
+ targetId: z4.number()
6445
6460
  });
6446
- var backlogItemSchema = z3.strictObject({
6447
- id: z3.number(),
6461
+ var backlogItemSchema = z4.strictObject({
6462
+ id: z4.number(),
6448
6463
  type: backlogTypeSchema.default("story"),
6449
- name: z3.string(),
6450
- description: z3.string().optional(),
6451
- acceptanceCriteria: z3.array(z3.string()),
6452
- plan: z3.array(planPhaseSchema).optional(),
6453
- currentPhase: z3.number().optional(),
6454
- starred: z3.boolean().default(false),
6464
+ name: z4.string(),
6465
+ description: z4.string().optional(),
6466
+ acceptanceCriteria: z4.array(z4.string()),
6467
+ plan: z4.array(planPhaseSchema).optional(),
6468
+ currentPhase: z4.number().optional(),
6469
+ starred: z4.boolean().default(false),
6455
6470
  status: backlogStatusSchema,
6456
- comments: z3.array(backlogCommentSchema).optional(),
6457
- subtasks: z3.array(subtaskSchema).optional(),
6458
- links: z3.array(backlogLinkSchema).optional(),
6459
- phaseUsage: z3.array(phaseUsageSchema).optional(),
6460
- phaseSessions: z3.array(phaseSessionSchema).optional(),
6471
+ comments: z4.array(backlogCommentSchema).optional(),
6472
+ subtasks: z4.array(subtaskSchema).optional(),
6473
+ links: z4.array(backlogLinkSchema).optional(),
6474
+ phaseUsage: z4.array(phaseUsageSchema).optional(),
6475
+ phaseSessions: z4.array(phaseSessionSchema).optional(),
6461
6476
  usageTotal: phaseUsageTotalSchema.optional(),
6462
- gitRefs: z3.array(gitRefSchema).optional(),
6463
- origin: z3.string().optional(),
6464
- jiraKey: z3.string().optional(),
6465
- githubIssue: z3.string().optional()
6477
+ gitRefs: z4.array(gitRefSchema).optional(),
6478
+ origin: z4.string().optional(),
6479
+ jiraKey: z4.string().optional(),
6480
+ githubIssue: z4.string().optional()
6466
6481
  });
6467
- var backlogFileSchema = z3.array(backlogItemSchema);
6482
+ var backlogFileSchema = z4.array(backlogItemSchema);
6468
6483
 
6469
6484
  // src/commands/backlog/parseBacklogJsonl.ts
6470
6485
  function parseBacklogJsonl(path71) {
@@ -7516,18 +7531,18 @@ async function persistPhaseSessionId(itemId2, phaseIdx, claudeSessionId) {
7516
7531
  import { mkdirSync as mkdirSync9, readFileSync as readFileSync18, rmSync as rmSync2, writeFileSync as writeFileSync19 } from "fs";
7517
7532
  import { homedir as homedir10 } from "os";
7518
7533
  import { dirname as dirname17, join as join22 } from "path";
7519
- import { z as z4 } from "zod";
7520
- var activitySchema = z4.object({
7521
- kind: z4.enum(["command", "backlog"]),
7522
- harness: z4.enum(["claude", "codex", "pi"]).optional(),
7523
- name: z4.string().optional(),
7524
- itemId: z4.number().optional(),
7525
- itemName: z4.string().optional(),
7526
- phase: z4.number().optional(),
7527
- phaseName: z4.string().optional(),
7528
- totalPhases: z4.number().optional(),
7529
- claudeSessionId: z4.string().optional(),
7530
- startedAt: z4.number()
7534
+ import { z as z5 } from "zod";
7535
+ var activitySchema = z5.object({
7536
+ kind: z5.enum(["command", "backlog"]),
7537
+ harness: z5.enum(["claude", "codex", "pi"]).optional(),
7538
+ name: z5.string().optional(),
7539
+ itemId: z5.number().optional(),
7540
+ itemName: z5.string().optional(),
7541
+ phase: z5.number().optional(),
7542
+ phaseName: z5.string().optional(),
7543
+ totalPhases: z5.number().optional(),
7544
+ claudeSessionId: z5.string().optional(),
7545
+ startedAt: z5.number()
7531
7546
  });
7532
7547
  function activityPath(sessionId) {
7533
7548
  return join22(homedir10(), ".assist", "activity", `activity-${sessionId}.json`);
@@ -9771,6 +9786,78 @@ async function getBackups(_req, res) {
9771
9786
  respondJson(res, 200, await listBackups(await getDb()));
9772
9787
  }
9773
9788
 
9789
+ // src/shared/configNodeFieldName.ts
9790
+ function configNodeFieldName(node) {
9791
+ const last = node.path.at(-1);
9792
+ return last?.kind === "key" ? last.name : void 0;
9793
+ }
9794
+
9795
+ // src/shared/configNodeField.ts
9796
+ function fieldsOf(node) {
9797
+ if (node.kind === "object") return node.fields;
9798
+ if (node.kind === "unionOfObjects")
9799
+ return node.variants.flatMap((variant) => variant.fields);
9800
+ return [];
9801
+ }
9802
+ function configNodeField(node, name) {
9803
+ const matches = fieldsOf(node).filter(
9804
+ (field) => configNodeFieldName(field) === name
9805
+ );
9806
+ return matches.find((field) => field.secret) ?? matches[0];
9807
+ }
9808
+
9809
+ // src/shared/isPlainRecord.ts
9810
+ function isPlainRecord(value) {
9811
+ return typeof value === "object" && value !== null && !Array.isArray(value);
9812
+ }
9813
+
9814
+ // src/shared/mapConfigSecrets.ts
9815
+ function mapChildren(value, path71, childNode, map) {
9816
+ if (!isPlainRecord(value)) return value;
9817
+ return Object.fromEntries(
9818
+ Object.entries(value).map(([name, child]) => [
9819
+ name,
9820
+ walk(child, [...path71, name], childNode(name), map)
9821
+ ])
9822
+ );
9823
+ }
9824
+ function mapItems(value, path71, item, map) {
9825
+ if (!Array.isArray(value)) return value;
9826
+ return value.map((entry, index3) => walk(entry, [...path71, index3], item, map));
9827
+ }
9828
+ function walk(value, path71, node, map) {
9829
+ if (!node || value === void 0 || value === null) return value;
9830
+ if (node.secret) return map(value, path71);
9831
+ switch (node.kind) {
9832
+ case "object":
9833
+ case "unionOfObjects":
9834
+ return mapChildren(
9835
+ value,
9836
+ path71,
9837
+ (name) => configNodeField(node, name),
9838
+ map
9839
+ );
9840
+ case "objectList":
9841
+ return mapItems(value, path71, node.item, map);
9842
+ case "record":
9843
+ return mapChildren(value, path71, () => node.value, map);
9844
+ default:
9845
+ return value;
9846
+ }
9847
+ }
9848
+ function mapConfigSecrets(value, node, map) {
9849
+ return walk(value, [], node, map);
9850
+ }
9851
+
9852
+ // src/shared/redactConfigSecrets.ts
9853
+ var REDACTED_SECRET = { assistSecret: "set" };
9854
+ function isRedactedSecret(value) {
9855
+ return typeof value === "object" && value !== null && value.assistSecret === "set";
9856
+ }
9857
+ function redactConfigSecrets(value, node) {
9858
+ return mapConfigSecrets(value, node, () => REDACTED_SECRET);
9859
+ }
9860
+
9774
9861
  // src/commands/config/getNestedValue.ts
9775
9862
  function isTraversable(value) {
9776
9863
  return value !== null && value !== void 0 && typeof value === "object";
@@ -9819,12 +9906,6 @@ function resolveConfigSources(key, layers) {
9819
9906
  return sources;
9820
9907
  }
9821
9908
 
9822
- // src/shared/configNodeFieldName.ts
9823
- function configNodeFieldName(node) {
9824
- const last = node.path.at(-1);
9825
- return last?.kind === "key" ? last.name : void 0;
9826
- }
9827
-
9828
9909
  // src/shared/findConfigNode.ts
9829
9910
  function objectField(node, segment) {
9830
9911
  if (segment.kind !== "key") return void 0;
@@ -9914,14 +9995,16 @@ function readConfigEntries(cwd) {
9914
9995
  return describeConfigLeaves(assistConfigSchema).filter((leaf) => !KEYS_STRIPPED_FROM_MERGED_CONFIG.has(leaf.key)).map((leaf) => {
9915
9996
  const sources = resolveConfigSources(leaf.key, layers);
9916
9997
  const source = sources[0] ?? "default";
9998
+ const node = configEntryNode(schema2, leaf.key);
9917
9999
  return {
9918
10000
  ...leaf,
9919
- value: getNestedValue(config, leaf.key),
10001
+ ...leaf.defaultValue === void 0 ? {} : { defaultValue: redactConfigSecrets(leaf.defaultValue, node) },
10002
+ value: redactConfigSecrets(getNestedValue(config, leaf.key), node),
9920
10003
  source,
9921
10004
  sources,
9922
10005
  ...layers.repoKey ? { repoKey: layers.repoKey } : {},
9923
10006
  globalOnly: isGlobalOnlyConfigKey(leaf.key),
9924
- node: configEntryNode(schema2, leaf.key)
10007
+ node
9925
10008
  };
9926
10009
  });
9927
10010
  }
@@ -10808,6 +10891,38 @@ function coerceUnion(key, raw, types) {
10808
10891
  return { ok: false, error: `${key}: expected ${types.join(" or ")}` };
10809
10892
  }
10810
10893
 
10894
+ // src/shared/valueAtConfigPath.ts
10895
+ function valueAtConfigPath(value, path71) {
10896
+ let current = value;
10897
+ for (const key of path71) {
10898
+ if (typeof key === "number") {
10899
+ if (!Array.isArray(current)) return void 0;
10900
+ current = current[key];
10901
+ continue;
10902
+ }
10903
+ if (typeof current !== "object" || current === null) return void 0;
10904
+ current = current[key];
10905
+ }
10906
+ return current;
10907
+ }
10908
+
10909
+ // src/shared/restoreConfigSecrets.ts
10910
+ function restoreConfigSecrets(value, stored, node) {
10911
+ return mapConfigSecrets(
10912
+ value,
10913
+ node,
10914
+ (secret, path71) => isRedactedSecret(secret) ? valueAtConfigPath(stored, path71) : secret
10915
+ );
10916
+ }
10917
+
10918
+ // src/commands/config/restoreConfigWriteSecrets.ts
10919
+ function restoreConfigWriteSecrets(key, value, cwd) {
10920
+ const node = configEntryNode(describeConfigNode(assistConfigSchema), key);
10921
+ if (!node) return value;
10922
+ const stored = loadConfigFrom(cwd);
10923
+ return restoreConfigSecrets(value, getNestedValue(stored, key), node);
10924
+ }
10925
+
10811
10926
  // src/commands/config/setNestedValue.ts
10812
10927
  function isPlainObject2(val) {
10813
10928
  return val !== null && typeof val === "object" && !Array.isArray(val);
@@ -11015,7 +11130,10 @@ async function handleConfigWrite(req, res, apply) {
11015
11130
  // src/commands/sessions/web/setConfig.ts
11016
11131
  function setConfig(req, res) {
11017
11132
  return handleConfigWrite(req, res, (request) => {
11018
- const coerced = coerceConfigValue(request.key, request.value);
11133
+ const coerced = coerceConfigValue(
11134
+ request.key,
11135
+ restoreConfigWriteSecrets(request.key, request.value, request.cwd)
11136
+ );
11019
11137
  if (!coerced.ok) return { ok: false, errors: [coerced.error] };
11020
11138
  return applyScopedConfigSet(
11021
11139
  request.key,
@@ -12810,18 +12928,18 @@ ${issues}`);
12810
12928
  }
12811
12929
 
12812
12930
  // src/commands/backlog/propose/proposedItemSchema.ts
12813
- import { z as z5 } from "zod";
12814
- var proposedPhaseSchema = z5.strictObject({
12815
- name: z5.string().trim().min(1, "phase name is required"),
12816
- tasks: z5.array(z5.string().trim().min(1)).min(1, "a phase needs at least one task"),
12817
- manualChecks: z5.array(z5.string().trim().min(1)).default([])
12931
+ import { z as z6 } from "zod";
12932
+ var proposedPhaseSchema = z6.strictObject({
12933
+ name: z6.string().trim().min(1, "phase name is required"),
12934
+ tasks: z6.array(z6.string().trim().min(1)).min(1, "a phase needs at least one task"),
12935
+ manualChecks: z6.array(z6.string().trim().min(1)).default([])
12818
12936
  });
12819
- var proposedItemSchema = z5.strictObject({
12820
- name: z5.string().trim().min(1, "name is required"),
12821
- type: z5.enum(["story", "bug"]),
12822
- description: z5.string().optional(),
12823
- acceptanceCriteria: z5.array(z5.string().trim().min(1)).default([]),
12824
- phases: z5.array(proposedPhaseSchema).default([])
12937
+ var proposedItemSchema = z6.strictObject({
12938
+ name: z6.string().trim().min(1, "name is required"),
12939
+ type: z6.enum(["story", "bug"]),
12940
+ description: z6.string().optional(),
12941
+ acceptanceCriteria: z6.array(z6.string().trim().min(1)).default([]),
12942
+ phases: z6.array(proposedPhaseSchema).default([])
12825
12943
  });
12826
12944
 
12827
12945
  // src/commands/backlog/propose/readProposedItem.ts
@@ -14219,9 +14337,9 @@ async function update(id, options2) {
14219
14337
  import chalk115 from "chalk";
14220
14338
 
14221
14339
  // src/commands/backlog/updatePlan/planUpdateSchema.ts
14222
- import { z as z6 } from "zod";
14223
- var planUpdateSchema = z6.strictObject({
14224
- phases: z6.array(proposedPhaseSchema).min(1, "a plan needs at least one phase")
14340
+ import { z as z7 } from "zod";
14341
+ var planUpdateSchema = z7.strictObject({
14342
+ phases: z7.array(proposedPhaseSchema).min(1, "a plan needs at least one phase")
14225
14343
  });
14226
14344
 
14227
14345
  // src/commands/backlog/updatePlan/readPlanUpdate.ts
@@ -15939,7 +16057,7 @@ function applyIgnoreGlobs(files, extraIgnore = []) {
15939
16057
  const ignore3 = [...complexity.ignore, ...extraIgnore];
15940
16058
  return files.filter((f) => !ignore3.some((glob) => minimatch5(f, glob)));
15941
16059
  }
15942
- function walk(dir, results) {
16060
+ function walk2(dir, results) {
15943
16061
  if (!fs19.existsSync(dir)) {
15944
16062
  return;
15945
16063
  }
@@ -15949,7 +16067,7 @@ function walk(dir, results) {
15949
16067
  const fullPath = path26.join(dir, entry.name);
15950
16068
  if (entry.isDirectory()) {
15951
16069
  if (entry.name !== "node_modules" && entry.name !== ".git") {
15952
- walk(fullPath, results);
16070
+ walk2(fullPath, results);
15953
16071
  }
15954
16072
  } else if (entry.isFile() && extensions.some((ext) => entry.name.endsWith(ext))) {
15955
16073
  results.push(fullPath);
@@ -15959,7 +16077,7 @@ function walk(dir, results) {
15959
16077
  function findSourceFiles2(pattern2, baseDir = ".", extraIgnore = []) {
15960
16078
  const results = [];
15961
16079
  if (pattern2.includes("*")) {
15962
- walk(baseDir, results);
16080
+ walk2(baseDir, results);
15963
16081
  return applyIgnoreGlobs(
15964
16082
  results.filter((f) => minimatch5(f, pattern2)),
15965
16083
  extraIgnore
@@ -15969,10 +16087,10 @@ function findSourceFiles2(pattern2, baseDir = ".", extraIgnore = []) {
15969
16087
  return [pattern2];
15970
16088
  }
15971
16089
  if (fs19.existsSync(pattern2) && fs19.statSync(pattern2).isDirectory()) {
15972
- walk(pattern2, results);
16090
+ walk2(pattern2, results);
15973
16091
  return applyIgnoreGlobs(results, extraIgnore);
15974
16092
  }
15975
- walk(baseDir, results);
16093
+ walk2(baseDir, results);
15976
16094
  return applyIgnoreGlobs(
15977
16095
  results.filter((f) => minimatch5(f, pattern2)),
15978
16096
  extraIgnore
@@ -16553,19 +16671,34 @@ function registerComplexity(program2) {
16553
16671
 
16554
16672
  // src/commands/config/index.ts
16555
16673
  import { stringify as stringifyYaml2 } from "yaml";
16674
+
16675
+ // src/shared/maskConfigSecrets.ts
16676
+ var SECRET_MASK = "<hidden>";
16677
+ function maskConfigSecrets(value, node) {
16678
+ return mapConfigSecrets(value, node, () => SECRET_MASK);
16679
+ }
16680
+
16681
+ // src/commands/config/index.ts
16556
16682
  function configList() {
16557
- const config = loadConfig();
16683
+ const config = maskConfigSecrets(
16684
+ loadConfig(),
16685
+ describeConfigNode(assistConfigSchema)
16686
+ );
16558
16687
  console.log(stringifyYaml2(config, { lineWidth: 0 }).trimEnd());
16559
16688
  }
16560
16689
 
16561
16690
  // src/commands/config/configGet.ts
16562
16691
  import chalk131 from "chalk";
16563
- function configGet(key) {
16564
- console.log(
16565
- formatOutput(
16566
- requireNestedValue(loadConfig(), key)
16567
- )
16692
+ function configGet(key, options2 = {}) {
16693
+ const value = requireNestedValue(
16694
+ loadConfig(),
16695
+ key
16568
16696
  );
16697
+ console.log(formatOutput(options2.reveal ? value : maskSecretsAt(value, key)));
16698
+ }
16699
+ function maskSecretsAt(value, key) {
16700
+ const node = configEntryNode(describeConfigNode(assistConfigSchema), key);
16701
+ return maskConfigSecrets(value, node);
16569
16702
  }
16570
16703
  function formatOutput(value) {
16571
16704
  return typeof value === "object" && value !== null ? JSON.stringify(value, null, 2) : String(value);
@@ -16708,8 +16841,8 @@ function registerConfig(program2) {
16708
16841
  "-r, --repo [name]",
16709
16842
  "Requires -g: remove the key from a repo's identity block (defaults to the current repo)"
16710
16843
  ).action((key, options2) => configUnset(key, options2));
16711
- configCommand.command("get <key>").description("Get a config value").action(configGet);
16712
- configCommand.command("list").description("List all config values").action(configList);
16844
+ configCommand.command("get <key>").description("Get a config value (secrets print as <hidden>)").option("--reveal", "Print the raw value of a secret, undecorated").action((key, options2) => configGet(key, options2));
16845
+ configCommand.command("list").description("List all config values (secrets print as <hidden>)").action(configList);
16713
16846
  }
16714
16847
 
16715
16848
  // src/commands/db/reportMigrationStatus.ts
@@ -17576,13 +17709,13 @@ function buildTree(csprojPath, repoRoot, visited = /* @__PURE__ */ new Set()) {
17576
17709
  }
17577
17710
  function collectAllDeps(node) {
17578
17711
  const result = /* @__PURE__ */ new Set();
17579
- function walk2(n) {
17712
+ function walk3(n) {
17580
17713
  for (const child of n.children) {
17581
17714
  result.add(child.path);
17582
- walk2(child);
17715
+ walk3(child);
17583
17716
  }
17584
17717
  }
17585
- walk2(node);
17718
+ walk3(node);
17586
17719
  return result;
17587
17720
  }
17588
17721
 
@@ -19227,30 +19360,30 @@ function stringOrUndefined(value) {
19227
19360
  }
19228
19361
 
19229
19362
  // src/commands/sessions/daemon/persistedSessionSchema.ts
19230
- import { z as z7 } from "zod";
19231
- var persistedSessionSchema = z7.object({
19232
- id: z7.string().optional(),
19233
- name: z7.string(),
19234
- title: z7.string().optional(),
19235
- generatedTitle: z7.string().optional(),
19236
- subtitle: z7.string().optional(),
19237
- commandType: z7.enum(["claude", "run", "assist"]),
19238
- harness: z7.enum(["claude", "codex", "pi"]).optional(),
19239
- status: z7.enum(["running", "waiting", "done", "error", "stopped"]).optional(),
19240
- cwd: z7.string(),
19241
- startedAt: z7.number(),
19242
- runningMs: z7.number().optional(),
19243
- claudeSessionId: z7.string().optional(),
19244
- initialPrompt: z7.string().optional(),
19245
- runName: z7.string().optional(),
19246
- runArgs: z7.array(z7.string()).optional(),
19247
- assistArgs: z7.array(z7.string()).optional(),
19363
+ import { z as z8 } from "zod";
19364
+ var persistedSessionSchema = z8.object({
19365
+ id: z8.string().optional(),
19366
+ name: z8.string(),
19367
+ title: z8.string().optional(),
19368
+ generatedTitle: z8.string().optional(),
19369
+ subtitle: z8.string().optional(),
19370
+ commandType: z8.enum(["claude", "run", "assist"]),
19371
+ harness: z8.enum(["claude", "codex", "pi"]).optional(),
19372
+ status: z8.enum(["running", "waiting", "done", "error", "stopped"]).optional(),
19373
+ cwd: z8.string(),
19374
+ startedAt: z8.number(),
19375
+ runningMs: z8.number().optional(),
19376
+ claudeSessionId: z8.string().optional(),
19377
+ initialPrompt: z8.string().optional(),
19378
+ runName: z8.string().optional(),
19379
+ runArgs: z8.array(z8.string()).optional(),
19380
+ assistArgs: z8.array(z8.string()).optional(),
19248
19381
  activity: activitySchema.optional(),
19249
- starred: z7.boolean().optional(),
19250
- autoRun: z7.boolean().optional(),
19251
- autoAdvance: z7.boolean().optional(),
19252
- reviewStarted: z7.boolean().optional(),
19253
- undurable: z7.object({ reason: z7.string(), removesTree: z7.boolean().optional() }).optional()
19382
+ starred: z8.boolean().optional(),
19383
+ autoRun: z8.boolean().optional(),
19384
+ autoAdvance: z8.boolean().optional(),
19385
+ reviewStarted: z8.boolean().optional(),
19386
+ undurable: z8.object({ reason: z8.string(), removesTree: z8.boolean().optional() }).optional()
19254
19387
  });
19255
19388
 
19256
19389
  // src/commands/sessions/daemon/toPersistedSession.ts
@@ -28631,9 +28764,9 @@ function createAutoExit(exit, graceMs = DEFAULT_GRACE_MS) {
28631
28764
  }
28632
28765
 
28633
28766
  // src/commands/sessions/daemon/loadActiveSelection.ts
28634
- import { z as z8 } from "zod";
28767
+ import { z as z9 } from "zod";
28635
28768
  var ACTIVE_FILE = "active.json";
28636
- var activeSelectionSchema = z8.record(z8.string(), z8.string());
28769
+ var activeSelectionSchema = z9.record(z9.string(), z9.string());
28637
28770
  function loadActiveSelection() {
28638
28771
  const parsed = activeSelectionSchema.safeParse(
28639
28772
  loadJson(ACTIVE_FILE)
@@ -30256,17 +30389,29 @@ function registerSpawnedSession(session, sessions, clients, onStatusChange, noti
30256
30389
  return session.id;
30257
30390
  }
30258
30391
 
30392
+ // src/commands/sessions/daemon/maxLiveSessions.ts
30393
+ var DEFAULT_MAX_LIVE = 24;
30394
+ function maxLiveSessions() {
30395
+ return loadConfig().sessions?.maxLive ?? DEFAULT_MAX_LIVE;
30396
+ }
30397
+
30259
30398
  // src/commands/sessions/daemon/sessionLimits.ts
30260
- var MAX_LIVE = 12;
30261
30399
  var sessionLimits = {
30262
- maxRestore: MAX_LIVE,
30400
+ maxRestore() {
30401
+ return maxLiveSessions();
30402
+ },
30263
30403
  /** Allocate the next session id from counter, refusing past the absolute
30264
30404
  * ceiling regardless of caller (restore, web create, retry) so no trigger
30265
30405
  * can fan out without bound. The counter advances only when allowed. */
30266
30406
  nextId(liveCount, counter) {
30267
- if (liveCount >= MAX_LIVE) {
30268
- daemonLog(`refusing to spawn: at ceiling of ${MAX_LIVE} live sessions`);
30269
- throw new Error(`session ceiling of ${MAX_LIVE} reached`);
30407
+ const ceiling = maxLiveSessions();
30408
+ if (liveCount >= ceiling) {
30409
+ daemonLog(
30410
+ `refusing to spawn: at ceiling of ${ceiling} live sessions (sessions.maxLive)`
30411
+ );
30412
+ throw new Error(
30413
+ `session ceiling of ${ceiling} reached \u2014 raise it with: assist config set sessions.maxLive <n> -g`
30414
+ );
30270
30415
  }
30271
30416
  return String(counter.next++);
30272
30417
  },
@@ -30787,7 +30932,7 @@ function deferredSession(id, persisted, cap) {
30787
30932
  function deferralNotice(persisted, cap) {
30788
30933
  return [
30789
30934
  `\r
30790
- \x1B[33mNot resumed: restore was already at its cap of ${cap} session(s)\x1B[0m\r
30935
+ \x1B[33mNot resumed: restore was already at its cap of ${cap} session(s) (raise it with: assist config set sessions.maxLive <n> -g)\x1B[0m\r
30791
30936
  `,
30792
30937
  `This card is the handle for it. Its command, working directory (${persisted.cwd})\r
30793
30938
  `,
@@ -31006,21 +31151,20 @@ function logRestoreError(persisted, error) {
31006
31151
  // src/commands/sessions/daemon/restoreAll.ts
31007
31152
  function restoreAll(spawner, sessions) {
31008
31153
  const persisted = loadPersistedSessions();
31009
- const names = persisted.slice(0, sessionLimits.maxRestore).map((entry) => {
31154
+ const cap = sessionLimits.maxRestore();
31155
+ const names = persisted.slice(0, cap).map((entry) => {
31010
31156
  restoreOne(entry, spawner, sessions);
31011
31157
  return entry.name;
31012
31158
  });
31013
- for (const over of persisted.slice(sessionLimits.maxRestore))
31014
- deferOne(over, spawner.recoveryCard);
31159
+ for (const over of persisted.slice(cap))
31160
+ deferOne(over, spawner.recoveryCard, cap);
31015
31161
  return names;
31016
31162
  }
31017
- function deferOne(persisted, spawnRecoveryCard) {
31163
+ function deferOne(persisted, spawnRecoveryCard, cap) {
31018
31164
  try {
31019
- const id = spawnRecoveryCard(
31020
- (sid) => deferredSession(sid, persisted, sessionLimits.maxRestore)
31021
- );
31165
+ const id = spawnRecoveryCard((sid) => deferredSession(sid, persisted, cap));
31022
31166
  daemonLog(
31023
- `restore capped at ${sessionLimits.maxRestore}: ${describePersistedSession(persisted)} deferred to stopped card ${id}`
31167
+ `restore capped at ${cap} (sessions.maxLive): ${describePersistedSession(persisted)} deferred to stopped card ${id}`
31024
31168
  );
31025
31169
  } catch (error) {
31026
31170
  logDroppedSession(persisted, error);
@@ -33126,6 +33270,11 @@ var sessionsConfigHelp = [
33126
33270
  setter: "assist config set sessions.floatWaitingAfterMs 15000 -g",
33127
33271
  note: "how long a session must have been waiting on input before it floats (default: 5000ms)"
33128
33272
  },
33273
+ {
33274
+ key: "sessions.maxLive",
33275
+ setter: "assist config set sessions.maxLive 24 -g",
33276
+ note: "ceiling on concurrent live sessions one daemon holds; spawning past it is refused, and restore respawns at most this many persisted sessions (default: 24)"
33277
+ },
33129
33278
  {
33130
33279
  key: "worktree.enabled",
33131
33280
  setter: "assist config set worktree.enabled true -g --repo",