@paigy/harness 0.3.31 → 0.3.33

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 (4) hide show
  1. package/README.md +10 -4
  2. package/dist/cli.js +966 -464
  3. package/dist/main.js +733 -271
  4. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -24,9 +24,9 @@ var __export = (target, all) => {
24
24
  };
25
25
  var __copyProps = (to, from, except, desc) => {
26
26
  if (from && typeof from === "object" || typeof from === "function") {
27
- for (let key of __getOwnPropNames(from))
28
- if (!__hasOwnProp.call(to, key) && key !== except)
29
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
27
+ for (let key3 of __getOwnPropNames(from))
28
+ if (!__hasOwnProp.call(to, key3) && key3 !== except)
29
+ __defProp(to, key3, { get: () => from[key3], enumerable: !(desc = __getOwnPropDesc(from, key3)) || desc.enumerable });
30
30
  }
31
31
  return to;
32
32
  };
@@ -172,9 +172,9 @@ var init_util = __esm({
172
172
  };
173
173
  util2.objectKeys = typeof Object.keys === "function" ? (obj) => Object.keys(obj) : (object) => {
174
174
  const keys = [];
175
- for (const key in object) {
176
- if (Object.prototype.hasOwnProperty.call(object, key)) {
177
- keys.push(key);
175
+ for (const key3 in object) {
176
+ if (Object.prototype.hasOwnProperty.call(object, key3)) {
177
+ keys.push(key3);
178
178
  }
179
179
  }
180
180
  return keys;
@@ -603,10 +603,10 @@ var init_parseUtil = __esm({
603
603
  static async mergeObjectAsync(status, pairs) {
604
604
  const syncPairs = [];
605
605
  for (const pair of pairs) {
606
- const key = await pair.key;
606
+ const key3 = await pair.key;
607
607
  const value = await pair.value;
608
608
  syncPairs.push({
609
- key,
609
+ key: key3,
610
610
  value
611
611
  });
612
612
  }
@@ -615,17 +615,17 @@ var init_parseUtil = __esm({
615
615
  static mergeObjectSync(status, pairs) {
616
616
  const finalObject = {};
617
617
  for (const pair of pairs) {
618
- const { key, value } = pair;
619
- if (key.status === "aborted")
618
+ const { key: key3, value } = pair;
619
+ if (key3.status === "aborted")
620
620
  return INVALID;
621
621
  if (value.status === "aborted")
622
622
  return INVALID;
623
- if (key.status === "dirty")
623
+ if (key3.status === "dirty")
624
624
  status.dirty();
625
625
  if (value.status === "dirty")
626
626
  status.dirty();
627
- if (key.value !== "__proto__" && (typeof value.value !== "undefined" || pair.alwaysSet)) {
628
- finalObject[key.value] = value.value;
627
+ if (key3.value !== "__proto__" && (typeof value.value !== "undefined" || pair.alwaysSet)) {
628
+ finalObject[key3.value] = value.value;
629
629
  }
630
630
  }
631
631
  return { status: status.value, value: finalObject };
@@ -759,9 +759,9 @@ function floatSafeRemainder(val, step2) {
759
759
  function deepPartialify(schema) {
760
760
  if (schema instanceof ZodObject) {
761
761
  const newShape = {};
762
- for (const key in schema.shape) {
763
- const fieldSchema = schema.shape[key];
764
- newShape[key] = ZodOptional.create(deepPartialify(fieldSchema));
762
+ for (const key3 in schema.shape) {
763
+ const fieldSchema = schema.shape[key3];
764
+ newShape[key3] = ZodOptional.create(deepPartialify(fieldSchema));
765
765
  }
766
766
  return new ZodObject({
767
767
  ...schema._def,
@@ -789,14 +789,14 @@ function mergeValues(a, b) {
789
789
  return { valid: true, data: a };
790
790
  } else if (aType === ZodParsedType.object && bType === ZodParsedType.object) {
791
791
  const bKeys = util.objectKeys(b);
792
- const sharedKeys = util.objectKeys(a).filter((key) => bKeys.indexOf(key) !== -1);
792
+ const sharedKeys = util.objectKeys(a).filter((key3) => bKeys.indexOf(key3) !== -1);
793
793
  const newObj = { ...a, ...b };
794
- for (const key of sharedKeys) {
795
- const sharedValue = mergeValues(a[key], b[key]);
794
+ for (const key3 of sharedKeys) {
795
+ const sharedValue = mergeValues(a[key3], b[key3]);
796
796
  if (!sharedValue.valid) {
797
797
  return { valid: false };
798
798
  }
799
- newObj[key] = sharedValue.data;
799
+ newObj[key3] = sharedValue.data;
800
800
  }
801
801
  return { valid: true, data: newObj };
802
802
  } else if (aType === ZodParsedType.array && bType === ZodParsedType.array) {
@@ -864,12 +864,12 @@ var init_types = __esm({
864
864
  init_parseUtil();
865
865
  init_util();
866
866
  ParseInputLazyPath = class {
867
- constructor(parent, value, path, key) {
867
+ constructor(parent, value, path, key3) {
868
868
  this._cachedPath = [];
869
869
  this.parent = parent;
870
870
  this.data = value;
871
871
  this._path = path;
872
- this._key = key;
872
+ this._key = key3;
873
873
  }
874
874
  get path() {
875
875
  if (!this._cachedPath.length) {
@@ -1125,8 +1125,8 @@ var init_types = __esm({
1125
1125
  promise() {
1126
1126
  return ZodPromise.create(this, this._def);
1127
1127
  }
1128
- or(option) {
1129
- return ZodUnion.create([this, option], this._def);
1128
+ or(option3) {
1129
+ return ZodUnion.create([this, option3], this._def);
1130
1130
  }
1131
1131
  and(incoming) {
1132
1132
  return ZodIntersection.create(this, incoming, this._def);
@@ -2547,29 +2547,29 @@ var init_types = __esm({
2547
2547
  const { shape, keys: shapeKeys } = this._getCached();
2548
2548
  const extraKeys = [];
2549
2549
  if (!(this._def.catchall instanceof ZodNever && this._def.unknownKeys === "strip")) {
2550
- for (const key in ctx.data) {
2551
- if (!shapeKeys.includes(key)) {
2552
- extraKeys.push(key);
2550
+ for (const key3 in ctx.data) {
2551
+ if (!shapeKeys.includes(key3)) {
2552
+ extraKeys.push(key3);
2553
2553
  }
2554
2554
  }
2555
2555
  }
2556
2556
  const pairs = [];
2557
- for (const key of shapeKeys) {
2558
- const keyValidator = shape[key];
2559
- const value = ctx.data[key];
2557
+ for (const key3 of shapeKeys) {
2558
+ const keyValidator = shape[key3];
2559
+ const value = ctx.data[key3];
2560
2560
  pairs.push({
2561
- key: { status: "valid", value: key },
2562
- value: keyValidator._parse(new ParseInputLazyPath(ctx, value, ctx.path, key)),
2563
- alwaysSet: key in ctx.data
2561
+ key: { status: "valid", value: key3 },
2562
+ value: keyValidator._parse(new ParseInputLazyPath(ctx, value, ctx.path, key3)),
2563
+ alwaysSet: key3 in ctx.data
2564
2564
  });
2565
2565
  }
2566
2566
  if (this._def.catchall instanceof ZodNever) {
2567
2567
  const unknownKeys = this._def.unknownKeys;
2568
2568
  if (unknownKeys === "passthrough") {
2569
- for (const key of extraKeys) {
2569
+ for (const key3 of extraKeys) {
2570
2570
  pairs.push({
2571
- key: { status: "valid", value: key },
2572
- value: { status: "valid", value: ctx.data[key] }
2571
+ key: { status: "valid", value: key3 },
2572
+ value: { status: "valid", value: ctx.data[key3] }
2573
2573
  });
2574
2574
  }
2575
2575
  } else if (unknownKeys === "strict") {
@@ -2586,15 +2586,15 @@ var init_types = __esm({
2586
2586
  }
2587
2587
  } else {
2588
2588
  const catchall = this._def.catchall;
2589
- for (const key of extraKeys) {
2590
- const value = ctx.data[key];
2589
+ for (const key3 of extraKeys) {
2590
+ const value = ctx.data[key3];
2591
2591
  pairs.push({
2592
- key: { status: "valid", value: key },
2592
+ key: { status: "valid", value: key3 },
2593
2593
  value: catchall._parse(
2594
- new ParseInputLazyPath(ctx, value, ctx.path, key)
2594
+ new ParseInputLazyPath(ctx, value, ctx.path, key3)
2595
2595
  //, ctx.child(key), value, getParsedType(value)
2596
2596
  ),
2597
- alwaysSet: key in ctx.data
2597
+ alwaysSet: key3 in ctx.data
2598
2598
  });
2599
2599
  }
2600
2600
  }
@@ -2602,10 +2602,10 @@ var init_types = __esm({
2602
2602
  return Promise.resolve().then(async () => {
2603
2603
  const syncPairs = [];
2604
2604
  for (const pair of pairs) {
2605
- const key = await pair.key;
2605
+ const key3 = await pair.key;
2606
2606
  const value = await pair.value;
2607
2607
  syncPairs.push({
2608
- key,
2608
+ key: key3,
2609
2609
  value,
2610
2610
  alwaysSet: pair.alwaysSet
2611
2611
  });
@@ -2730,8 +2730,8 @@ var init_types = __esm({
2730
2730
  // }) as any;
2731
2731
  // return merged;
2732
2732
  // }
2733
- setKey(key, schema) {
2734
- return this.augment({ [key]: schema });
2733
+ setKey(key3, schema) {
2734
+ return this.augment({ [key3]: schema });
2735
2735
  }
2736
2736
  // merge<Incoming extends AnyZodObject>(
2737
2737
  // merging: Incoming
@@ -2762,9 +2762,9 @@ var init_types = __esm({
2762
2762
  }
2763
2763
  pick(mask) {
2764
2764
  const shape = {};
2765
- for (const key of util.objectKeys(mask)) {
2766
- if (mask[key] && this.shape[key]) {
2767
- shape[key] = this.shape[key];
2765
+ for (const key3 of util.objectKeys(mask)) {
2766
+ if (mask[key3] && this.shape[key3]) {
2767
+ shape[key3] = this.shape[key3];
2768
2768
  }
2769
2769
  }
2770
2770
  return new _ZodObject({
@@ -2774,9 +2774,9 @@ var init_types = __esm({
2774
2774
  }
2775
2775
  omit(mask) {
2776
2776
  const shape = {};
2777
- for (const key of util.objectKeys(this.shape)) {
2778
- if (!mask[key]) {
2779
- shape[key] = this.shape[key];
2777
+ for (const key3 of util.objectKeys(this.shape)) {
2778
+ if (!mask[key3]) {
2779
+ shape[key3] = this.shape[key3];
2780
2780
  }
2781
2781
  }
2782
2782
  return new _ZodObject({
@@ -2792,12 +2792,12 @@ var init_types = __esm({
2792
2792
  }
2793
2793
  partial(mask) {
2794
2794
  const newShape = {};
2795
- for (const key of util.objectKeys(this.shape)) {
2796
- const fieldSchema = this.shape[key];
2797
- if (mask && !mask[key]) {
2798
- newShape[key] = fieldSchema;
2795
+ for (const key3 of util.objectKeys(this.shape)) {
2796
+ const fieldSchema = this.shape[key3];
2797
+ if (mask && !mask[key3]) {
2798
+ newShape[key3] = fieldSchema;
2799
2799
  } else {
2800
- newShape[key] = fieldSchema.optional();
2800
+ newShape[key3] = fieldSchema.optional();
2801
2801
  }
2802
2802
  }
2803
2803
  return new _ZodObject({
@@ -2807,16 +2807,16 @@ var init_types = __esm({
2807
2807
  }
2808
2808
  required(mask) {
2809
2809
  const newShape = {};
2810
- for (const key of util.objectKeys(this.shape)) {
2811
- if (mask && !mask[key]) {
2812
- newShape[key] = this.shape[key];
2810
+ for (const key3 of util.objectKeys(this.shape)) {
2811
+ if (mask && !mask[key3]) {
2812
+ newShape[key3] = this.shape[key3];
2813
2813
  } else {
2814
- const fieldSchema = this.shape[key];
2814
+ const fieldSchema = this.shape[key3];
2815
2815
  let newField = fieldSchema;
2816
2816
  while (newField instanceof ZodOptional) {
2817
2817
  newField = newField._def.innerType;
2818
2818
  }
2819
- newShape[key] = newField;
2819
+ newShape[key3] = newField;
2820
2820
  }
2821
2821
  }
2822
2822
  return new _ZodObject({
@@ -2879,7 +2879,7 @@ var init_types = __esm({
2879
2879
  return INVALID;
2880
2880
  }
2881
2881
  if (ctx.common.async) {
2882
- return Promise.all(options.map(async (option) => {
2882
+ return Promise.all(options.map(async (option3) => {
2883
2883
  const childCtx = {
2884
2884
  ...ctx,
2885
2885
  common: {
@@ -2889,7 +2889,7 @@ var init_types = __esm({
2889
2889
  parent: null
2890
2890
  };
2891
2891
  return {
2892
- result: await option._parseAsync({
2892
+ result: await option3._parseAsync({
2893
2893
  data: ctx.data,
2894
2894
  path: ctx.path,
2895
2895
  parent: childCtx
@@ -2900,7 +2900,7 @@ var init_types = __esm({
2900
2900
  } else {
2901
2901
  let dirty = void 0;
2902
2902
  const issues = [];
2903
- for (const option of options) {
2903
+ for (const option3 of options) {
2904
2904
  const childCtx = {
2905
2905
  ...ctx,
2906
2906
  common: {
@@ -2909,7 +2909,7 @@ var init_types = __esm({
2909
2909
  },
2910
2910
  parent: null
2911
2911
  };
2912
- const result = option._parseSync({
2912
+ const result = option3._parseSync({
2913
2913
  data: ctx.data,
2914
2914
  path: ctx.path,
2915
2915
  parent: childCtx
@@ -2990,8 +2990,8 @@ var init_types = __esm({
2990
2990
  }
2991
2991
  const discriminator = this.discriminator;
2992
2992
  const discriminatorValue = ctx.data[discriminator];
2993
- const option = this.optionsMap.get(discriminatorValue);
2994
- if (!option) {
2993
+ const option3 = this.optionsMap.get(discriminatorValue);
2994
+ if (!option3) {
2995
2995
  addIssueToContext(ctx, {
2996
2996
  code: ZodIssueCode.invalid_union_discriminator,
2997
2997
  options: Array.from(this.optionsMap.keys()),
@@ -3000,13 +3000,13 @@ var init_types = __esm({
3000
3000
  return INVALID;
3001
3001
  }
3002
3002
  if (ctx.common.async) {
3003
- return option._parseAsync({
3003
+ return option3._parseAsync({
3004
3004
  data: ctx.data,
3005
3005
  path: ctx.path,
3006
3006
  parent: ctx
3007
3007
  });
3008
3008
  } else {
3009
- return option._parseSync({
3009
+ return option3._parseSync({
3010
3010
  data: ctx.data,
3011
3011
  path: ctx.path,
3012
3012
  parent: ctx
@@ -3193,11 +3193,11 @@ var init_types = __esm({
3193
3193
  const pairs = [];
3194
3194
  const keyType = this._def.keyType;
3195
3195
  const valueType = this._def.valueType;
3196
- for (const key in ctx.data) {
3196
+ for (const key3 in ctx.data) {
3197
3197
  pairs.push({
3198
- key: keyType._parse(new ParseInputLazyPath(ctx, key, ctx.path, key)),
3199
- value: valueType._parse(new ParseInputLazyPath(ctx, ctx.data[key], ctx.path, key)),
3200
- alwaysSet: key in ctx.data
3198
+ key: keyType._parse(new ParseInputLazyPath(ctx, key3, ctx.path, key3)),
3199
+ value: valueType._parse(new ParseInputLazyPath(ctx, ctx.data[key3], ctx.path, key3)),
3200
+ alwaysSet: key3 in ctx.data
3201
3201
  });
3202
3202
  }
3203
3203
  if (ctx.common.async) {
@@ -3245,9 +3245,9 @@ var init_types = __esm({
3245
3245
  }
3246
3246
  const keyType = this._def.keyType;
3247
3247
  const valueType = this._def.valueType;
3248
- const pairs = [...ctx.data.entries()].map(([key, value], index) => {
3248
+ const pairs = [...ctx.data.entries()].map(([key3, value], index) => {
3249
3249
  return {
3250
- key: keyType._parse(new ParseInputLazyPath(ctx, key, ctx.path, [index, "key"])),
3250
+ key: keyType._parse(new ParseInputLazyPath(ctx, key3, ctx.path, [index, "key"])),
3251
3251
  value: valueType._parse(new ParseInputLazyPath(ctx, value, ctx.path, [index, "value"]))
3252
3252
  };
3253
3253
  });
@@ -3255,30 +3255,30 @@ var init_types = __esm({
3255
3255
  const finalMap = /* @__PURE__ */ new Map();
3256
3256
  return Promise.resolve().then(async () => {
3257
3257
  for (const pair of pairs) {
3258
- const key = await pair.key;
3258
+ const key3 = await pair.key;
3259
3259
  const value = await pair.value;
3260
- if (key.status === "aborted" || value.status === "aborted") {
3260
+ if (key3.status === "aborted" || value.status === "aborted") {
3261
3261
  return INVALID;
3262
3262
  }
3263
- if (key.status === "dirty" || value.status === "dirty") {
3263
+ if (key3.status === "dirty" || value.status === "dirty") {
3264
3264
  status.dirty();
3265
3265
  }
3266
- finalMap.set(key.value, value.value);
3266
+ finalMap.set(key3.value, value.value);
3267
3267
  }
3268
3268
  return { status: status.value, value: finalMap };
3269
3269
  });
3270
3270
  } else {
3271
3271
  const finalMap = /* @__PURE__ */ new Map();
3272
3272
  for (const pair of pairs) {
3273
- const key = pair.key;
3273
+ const key3 = pair.key;
3274
3274
  const value = pair.value;
3275
- if (key.status === "aborted" || value.status === "aborted") {
3275
+ if (key3.status === "aborted" || value.status === "aborted") {
3276
3276
  return INVALID;
3277
3277
  }
3278
- if (key.status === "dirty" || value.status === "dirty") {
3278
+ if (key3.status === "dirty" || value.status === "dirty") {
3279
3279
  status.dirty();
3280
3280
  }
3281
- finalMap.set(key.value, value.value);
3281
+ finalMap.set(key3.value, value.value);
3282
3282
  }
3283
3283
  return { status: status.value, value: finalMap };
3284
3284
  }
@@ -4794,9 +4794,9 @@ var require_constants = __commonJS({
4794
4794
  "X-XSS-Protection"
4795
4795
  ];
4796
4796
  for (let i = 0; i < wellknownHeaderNames.length; ++i) {
4797
- const key = wellknownHeaderNames[i];
4798
- const lowerCasedKey = key.toLowerCase();
4799
- headerNameLowerCasedRecord[key] = headerNameLowerCasedRecord[lowerCasedKey] = lowerCasedKey;
4797
+ const key3 = wellknownHeaderNames[i];
4798
+ const lowerCasedKey = key3.toLowerCase();
4799
+ headerNameLowerCasedRecord[key3] = headerNameLowerCasedRecord[lowerCasedKey] = lowerCasedKey;
4800
4800
  }
4801
4801
  Object.setPrototypeOf(headerNameLowerCasedRecord, null);
4802
4802
  module.exports = {
@@ -4830,16 +4830,16 @@ var require_tree = __commonJS({
4830
4830
  * @param {any} value
4831
4831
  * @param {number} index
4832
4832
  */
4833
- constructor(key, value, index) {
4834
- if (index === void 0 || index >= key.length) {
4833
+ constructor(key3, value, index) {
4834
+ if (index === void 0 || index >= key3.length) {
4835
4835
  throw new TypeError("Unreachable");
4836
4836
  }
4837
- const code = this.code = key.charCodeAt(index);
4837
+ const code = this.code = key3.charCodeAt(index);
4838
4838
  if (code > 127) {
4839
4839
  throw new TypeError("key must be ascii string");
4840
4840
  }
4841
- if (key.length !== ++index) {
4842
- this.middle = new _TstNode(key, value, index);
4841
+ if (key3.length !== ++index) {
4842
+ this.middle = new _TstNode(key3, value, index);
4843
4843
  } else {
4844
4844
  this.value = value;
4845
4845
  }
@@ -4848,15 +4848,15 @@ var require_tree = __commonJS({
4848
4848
  * @param {string} key
4849
4849
  * @param {any} value
4850
4850
  */
4851
- add(key, value) {
4852
- const length = key.length;
4851
+ add(key3, value) {
4852
+ const length = key3.length;
4853
4853
  if (length === 0) {
4854
4854
  throw new TypeError("Unreachable");
4855
4855
  }
4856
4856
  let index = 0;
4857
4857
  let node = this;
4858
4858
  while (true) {
4859
- const code = key.charCodeAt(index);
4859
+ const code = key3.charCodeAt(index);
4860
4860
  if (code > 127) {
4861
4861
  throw new TypeError("key must be ascii string");
4862
4862
  }
@@ -4867,20 +4867,20 @@ var require_tree = __commonJS({
4867
4867
  } else if (node.middle !== null) {
4868
4868
  node = node.middle;
4869
4869
  } else {
4870
- node.middle = new _TstNode(key, value, index);
4870
+ node.middle = new _TstNode(key3, value, index);
4871
4871
  break;
4872
4872
  }
4873
4873
  } else if (node.code < code) {
4874
4874
  if (node.left !== null) {
4875
4875
  node = node.left;
4876
4876
  } else {
4877
- node.left = new _TstNode(key, value, index);
4877
+ node.left = new _TstNode(key3, value, index);
4878
4878
  break;
4879
4879
  }
4880
4880
  } else if (node.right !== null) {
4881
4881
  node = node.right;
4882
4882
  } else {
4883
- node.right = new _TstNode(key, value, index);
4883
+ node.right = new _TstNode(key3, value, index);
4884
4884
  break;
4885
4885
  }
4886
4886
  }
@@ -4889,12 +4889,12 @@ var require_tree = __commonJS({
4889
4889
  * @param {Uint8Array} key
4890
4890
  * @return {TstNode | null}
4891
4891
  */
4892
- search(key) {
4893
- const keylength = key.length;
4892
+ search(key3) {
4893
+ const keylength = key3.length;
4894
4894
  let index = 0;
4895
4895
  let node = this;
4896
4896
  while (node !== null && index < keylength) {
4897
- let code = key[index];
4897
+ let code = key3[index];
4898
4898
  if (code <= 90 && code >= 65) {
4899
4899
  code |= 32;
4900
4900
  }
@@ -4919,25 +4919,25 @@ var require_tree = __commonJS({
4919
4919
  * @param {string} key
4920
4920
  * @param {any} value
4921
4921
  * */
4922
- insert(key, value) {
4922
+ insert(key3, value) {
4923
4923
  if (this.node === null) {
4924
- this.node = new TstNode(key, value, 0);
4924
+ this.node = new TstNode(key3, value, 0);
4925
4925
  } else {
4926
- this.node.add(key, value);
4926
+ this.node.add(key3, value);
4927
4927
  }
4928
4928
  }
4929
4929
  /**
4930
4930
  * @param {Uint8Array} key
4931
4931
  * @return {any}
4932
4932
  */
4933
- lookup(key) {
4934
- return this.node?.search(key)?.value ?? null;
4933
+ lookup(key3) {
4934
+ return this.node?.search(key3)?.value ?? null;
4935
4935
  }
4936
4936
  };
4937
4937
  var tree = new TernarySearchTree();
4938
4938
  for (let i = 0; i < wellknownHeaderNames.length; ++i) {
4939
- const key = headerNameLowerCasedRecord[wellknownHeaderNames[i]];
4940
- tree.insert(key, key);
4939
+ const key3 = headerNameLowerCasedRecord[wellknownHeaderNames[i]];
4940
+ tree.insert(key3, key3);
4941
4941
  }
4942
4942
  module.exports = {
4943
4943
  TernarySearchTree,
@@ -5161,20 +5161,20 @@ var require_util = __commonJS({
5161
5161
  function parseHeaders(headers, obj) {
5162
5162
  if (obj === void 0) obj = {};
5163
5163
  for (let i = 0; i < headers.length; i += 2) {
5164
- const key = headerNameToString(headers[i]);
5165
- let val = obj[key];
5164
+ const key3 = headerNameToString(headers[i]);
5165
+ let val = obj[key3];
5166
5166
  if (val) {
5167
5167
  if (typeof val === "string") {
5168
5168
  val = [val];
5169
- obj[key] = val;
5169
+ obj[key3] = val;
5170
5170
  }
5171
5171
  val.push(headers[i + 1].toString("utf8"));
5172
5172
  } else {
5173
5173
  const headersValue = headers[i + 1];
5174
5174
  if (typeof headersValue === "string") {
5175
- obj[key] = headersValue;
5175
+ obj[key3] = headersValue;
5176
5176
  } else {
5177
- obj[key] = Array.isArray(headersValue) ? headersValue.map((x) => x.toString("utf8")) : headersValue.toString("utf8");
5177
+ obj[key3] = Array.isArray(headersValue) ? headersValue.map((x) => x.toString("utf8")) : headersValue.toString("utf8");
5178
5178
  }
5179
5179
  }
5180
5180
  }
@@ -5188,21 +5188,21 @@ var require_util = __commonJS({
5188
5188
  const ret = new Array(len);
5189
5189
  let hasContentLength = false;
5190
5190
  let contentDispositionIdx = -1;
5191
- let key;
5191
+ let key3;
5192
5192
  let val;
5193
5193
  let kLen = 0;
5194
5194
  for (let n = 0; n < headers.length; n += 2) {
5195
- key = headers[n];
5195
+ key3 = headers[n];
5196
5196
  val = headers[n + 1];
5197
- typeof key !== "string" && (key = key.toString());
5197
+ typeof key3 !== "string" && (key3 = key3.toString());
5198
5198
  typeof val !== "string" && (val = val.toString("utf8"));
5199
- kLen = key.length;
5200
- if (kLen === 14 && key[7] === "-" && (key === "content-length" || key.toLowerCase() === "content-length")) {
5199
+ kLen = key3.length;
5200
+ if (kLen === 14 && key3[7] === "-" && (key3 === "content-length" || key3.toLowerCase() === "content-length")) {
5201
5201
  hasContentLength = true;
5202
- } else if (kLen === 19 && key[7] === "-" && (key === "content-disposition" || key.toLowerCase() === "content-disposition")) {
5202
+ } else if (kLen === 19 && key3[7] === "-" && (key3 === "content-disposition" || key3.toLowerCase() === "content-disposition")) {
5203
5203
  contentDispositionIdx = n + 1;
5204
5204
  }
5205
- ret[n] = key;
5205
+ ret[n] = key3;
5206
5206
  ret[n + 1] = val;
5207
5207
  }
5208
5208
  if (hasContentLength && contentDispositionIdx !== -1) {
@@ -5887,20 +5887,20 @@ var require_request = __commonJS({
5887
5887
  this.endHandler = null;
5888
5888
  }
5889
5889
  }
5890
- addHeader(key, value) {
5891
- processHeader(this, key, value);
5890
+ addHeader(key3, value) {
5891
+ processHeader(this, key3, value);
5892
5892
  return this;
5893
5893
  }
5894
5894
  };
5895
- function processHeader(request, key, val) {
5895
+ function processHeader(request, key3, val) {
5896
5896
  if (val && (typeof val === "object" && !Array.isArray(val))) {
5897
- throw new InvalidArgumentError(`invalid ${key} header`);
5897
+ throw new InvalidArgumentError(`invalid ${key3} header`);
5898
5898
  } else if (val === void 0) {
5899
5899
  return;
5900
5900
  }
5901
- let headerName = headerNameLowerCasedRecord[key];
5901
+ let headerName = headerNameLowerCasedRecord[key3];
5902
5902
  if (headerName === void 0) {
5903
- headerName = key.toLowerCase();
5903
+ headerName = key3.toLowerCase();
5904
5904
  if (headerNameLowerCasedRecord[headerName] === void 0 && !isValidHTTPToken(headerName)) {
5905
5905
  throw new InvalidArgumentError("invalid header key");
5906
5906
  }
@@ -5910,13 +5910,13 @@ var require_request = __commonJS({
5910
5910
  for (let i = 0; i < val.length; i++) {
5911
5911
  if (typeof val[i] === "string") {
5912
5912
  if (!isValidHeaderValue(val[i])) {
5913
- throw new InvalidArgumentError(`invalid ${key} header`);
5913
+ throw new InvalidArgumentError(`invalid ${key3} header`);
5914
5914
  }
5915
5915
  arr.push(val[i]);
5916
5916
  } else if (val[i] === null) {
5917
5917
  arr.push("");
5918
5918
  } else if (typeof val[i] === "object") {
5919
- throw new InvalidArgumentError(`invalid ${key} header`);
5919
+ throw new InvalidArgumentError(`invalid ${key3} header`);
5920
5920
  } else {
5921
5921
  arr.push(`${val[i]}`);
5922
5922
  }
@@ -5924,7 +5924,7 @@ var require_request = __commonJS({
5924
5924
  val = arr;
5925
5925
  } else if (typeof val === "string") {
5926
5926
  if (!isValidHeaderValue(val)) {
5927
- throw new InvalidArgumentError(`invalid ${key} header`);
5927
+ throw new InvalidArgumentError(`invalid ${key3} header`);
5928
5928
  }
5929
5929
  } else if (val === null) {
5930
5930
  val = "";
@@ -5949,7 +5949,7 @@ var require_request = __commonJS({
5949
5949
  }
5950
5950
  } else if (request.contentType === null && headerName === "content-type") {
5951
5951
  request.contentType = val;
5952
- request.headers.push(key, val);
5952
+ request.headers.push(key3, val);
5953
5953
  } else if (headerName === "transfer-encoding" || headerName === "keep-alive" || headerName === "upgrade") {
5954
5954
  throw new InvalidArgumentError(`invalid ${headerName} header`);
5955
5955
  } else if (headerName === "connection") {
@@ -5963,7 +5963,7 @@ var require_request = __commonJS({
5963
5963
  } else if (headerName === "expect") {
5964
5964
  throw new NotSupportedError("expect header not supported");
5965
5965
  } else {
5966
- request.headers.push(key, val);
5966
+ request.headers.push(key3, val);
5967
5967
  }
5968
5968
  }
5969
5969
  module.exports = Request;
@@ -6443,13 +6443,13 @@ var require_connect = __commonJS({
6443
6443
  constructor(maxCachedSessions) {
6444
6444
  this._maxCachedSessions = maxCachedSessions;
6445
6445
  this._sessionCache = /* @__PURE__ */ new Map();
6446
- this._sessionRegistry = new global.FinalizationRegistry((key) => {
6446
+ this._sessionRegistry = new global.FinalizationRegistry((key3) => {
6447
6447
  if (this._sessionCache.size < this._maxCachedSessions) {
6448
6448
  return;
6449
6449
  }
6450
- const ref = this._sessionCache.get(key);
6450
+ const ref = this._sessionCache.get(key3);
6451
6451
  if (ref !== void 0 && ref.deref() === void 0) {
6452
- this._sessionCache.delete(key);
6452
+ this._sessionCache.delete(key3);
6453
6453
  }
6454
6454
  });
6455
6455
  }
@@ -6613,10 +6613,10 @@ var require_utils = __commonJS({
6613
6613
  exports.enumToMap = void 0;
6614
6614
  function enumToMap(obj) {
6615
6615
  const res = {};
6616
- Object.keys(obj).forEach((key) => {
6617
- const value = obj[key];
6616
+ Object.keys(obj).forEach((key3) => {
6617
+ const value = obj[key3];
6618
6618
  if (typeof value === "number") {
6619
- res[key] = value;
6619
+ res[key3] = value;
6620
6620
  }
6621
6621
  });
6622
6622
  return res;
@@ -6793,9 +6793,9 @@ var require_constants2 = __commonJS({
6793
6793
  ];
6794
6794
  exports.METHOD_MAP = utils_1.enumToMap(METHODS);
6795
6795
  exports.H_METHOD_MAP = {};
6796
- Object.keys(exports.METHOD_MAP).forEach((key) => {
6797
- if (/^H/.test(key)) {
6798
- exports.H_METHOD_MAP[key] = exports.METHOD_MAP[key];
6796
+ Object.keys(exports.METHOD_MAP).forEach((key3) => {
6797
+ if (/^H/.test(key3)) {
6798
+ exports.H_METHOD_MAP[key3] = exports.METHOD_MAP[key3];
6799
6799
  }
6800
6800
  });
6801
6801
  var FINISH;
@@ -7480,25 +7480,25 @@ var require_data_url = __commonJS({
7480
7480
  function isHTTPWhiteSpace(char) {
7481
7481
  return char === 13 || char === 10 || char === 9 || char === 32;
7482
7482
  }
7483
- function removeHTTPWhitespace(str, leading = true, trailing = true) {
7484
- return removeChars(str, leading, trailing, isHTTPWhiteSpace);
7483
+ function removeHTTPWhitespace(str3, leading = true, trailing = true) {
7484
+ return removeChars(str3, leading, trailing, isHTTPWhiteSpace);
7485
7485
  }
7486
7486
  function isASCIIWhitespace(char) {
7487
7487
  return char === 13 || char === 10 || char === 9 || char === 12 || char === 32;
7488
7488
  }
7489
- function removeASCIIWhitespace(str, leading = true, trailing = true) {
7490
- return removeChars(str, leading, trailing, isASCIIWhitespace);
7489
+ function removeASCIIWhitespace(str3, leading = true, trailing = true) {
7490
+ return removeChars(str3, leading, trailing, isASCIIWhitespace);
7491
7491
  }
7492
- function removeChars(str, leading, trailing, predicate) {
7492
+ function removeChars(str3, leading, trailing, predicate) {
7493
7493
  let lead = 0;
7494
- let trail = str.length - 1;
7494
+ let trail = str3.length - 1;
7495
7495
  if (leading) {
7496
- while (lead < str.length && predicate(str.charCodeAt(lead))) lead++;
7496
+ while (lead < str3.length && predicate(str3.charCodeAt(lead))) lead++;
7497
7497
  }
7498
7498
  if (trailing) {
7499
- while (trail > 0 && predicate(str.charCodeAt(trail))) trail--;
7499
+ while (trail > 0 && predicate(str3.charCodeAt(trail))) trail--;
7500
7500
  }
7501
- return lead === 0 && trail === str.length - 1 ? str : str.slice(lead, trail + 1);
7501
+ return lead === 0 && trail === str3.length - 1 ? str3 : str3.slice(lead, trail + 1);
7502
7502
  }
7503
7503
  function isomorphicDecode(input) {
7504
7504
  const length = input.length;
@@ -7766,19 +7766,19 @@ var require_webidl = __commonJS({
7766
7766
  const result = {};
7767
7767
  if (!types.isProxy(O)) {
7768
7768
  const keys2 = [...Object.getOwnPropertyNames(O), ...Object.getOwnPropertySymbols(O)];
7769
- for (const key of keys2) {
7770
- const typedKey = keyConverter(key, prefix, argument);
7771
- const typedValue = valueConverter(O[key], prefix, argument);
7769
+ for (const key3 of keys2) {
7770
+ const typedKey = keyConverter(key3, prefix, argument);
7771
+ const typedValue = valueConverter(O[key3], prefix, argument);
7772
7772
  result[typedKey] = typedValue;
7773
7773
  }
7774
7774
  return result;
7775
7775
  }
7776
7776
  const keys = Reflect.ownKeys(O);
7777
- for (const key of keys) {
7778
- const desc = Reflect.getOwnPropertyDescriptor(O, key);
7777
+ for (const key3 of keys) {
7778
+ const desc = Reflect.getOwnPropertyDescriptor(O, key3);
7779
7779
  if (desc?.enumerable) {
7780
- const typedKey = keyConverter(key, prefix, argument);
7781
- const typedValue = valueConverter(O[key], prefix, argument);
7780
+ const typedKey = keyConverter(key3, prefix, argument);
7781
+ const typedValue = valueConverter(O[key3], prefix, argument);
7782
7782
  result[typedKey] = typedValue;
7783
7783
  }
7784
7784
  }
@@ -7809,29 +7809,29 @@ var require_webidl = __commonJS({
7809
7809
  });
7810
7810
  }
7811
7811
  for (const options of converters) {
7812
- const { key, defaultValue, required, converter } = options;
7812
+ const { key: key3, defaultValue, required, converter } = options;
7813
7813
  if (required === true) {
7814
- if (!Object.hasOwn(dictionary, key)) {
7814
+ if (!Object.hasOwn(dictionary, key3)) {
7815
7815
  throw webidl.errors.exception({
7816
7816
  header: prefix,
7817
- message: `Missing required key "${key}".`
7817
+ message: `Missing required key "${key3}".`
7818
7818
  });
7819
7819
  }
7820
7820
  }
7821
- let value = dictionary[key];
7821
+ let value = dictionary[key3];
7822
7822
  const hasDefault = Object.hasOwn(options, "defaultValue");
7823
7823
  if (hasDefault && value !== null) {
7824
7824
  value ??= defaultValue();
7825
7825
  }
7826
7826
  if (required || hasDefault || value !== void 0) {
7827
- value = converter(value, prefix, `${argument}.${key}`);
7827
+ value = converter(value, prefix, `${argument}.${key3}`);
7828
7828
  if (options.allowedValues && !options.allowedValues.includes(value)) {
7829
7829
  throw webidl.errors.exception({
7830
7830
  header: prefix,
7831
7831
  message: `${value} is not an accepted type. Expected one of ${options.allowedValues.join(", ")}.`
7832
7832
  });
7833
7833
  }
7834
- dict[key] = value;
7834
+ dict[key3] = value;
7835
7835
  }
7836
7836
  }
7837
7837
  return dict;
@@ -8446,18 +8446,18 @@ var require_util2 = __commonJS({
8446
8446
  done: true
8447
8447
  };
8448
8448
  }
8449
- const { [keyIndex]: key, [valueIndex]: value } = values[index];
8449
+ const { [keyIndex]: key3, [valueIndex]: value } = values[index];
8450
8450
  this.#index = index + 1;
8451
8451
  let result;
8452
8452
  switch (this.#kind) {
8453
8453
  case "key":
8454
- result = key;
8454
+ result = key3;
8455
8455
  break;
8456
8456
  case "value":
8457
8457
  result = value;
8458
8458
  break;
8459
8459
  case "key+value":
8460
- result = [key, value];
8460
+ result = [key3, value];
8461
8461
  break;
8462
8462
  }
8463
8463
  return {
@@ -8523,8 +8523,8 @@ var require_util2 = __commonJS({
8523
8523
  `Failed to execute 'forEach' on '${name}': parameter 1 is not of type 'Function'.`
8524
8524
  );
8525
8525
  }
8526
- for (const { 0: key, 1: value } of makeIterator(this, "key+value")) {
8527
- callbackfn.call(thisArg, value, key, this);
8526
+ for (const { 0: key3, 1: value } of makeIterator(this, "key+value")) {
8527
+ callbackfn.call(thisArg, value, key3, this);
8528
8528
  }
8529
8529
  }
8530
8530
  }
@@ -9417,7 +9417,7 @@ var require_body = __commonJS({
9417
9417
  const boundary = `----formdata-undici-0${`${random(1e11)}`.padStart(11, "0")}`;
9418
9418
  const prefix = `--${boundary}\r
9419
9419
  Content-Disposition: form-data`;
9420
- const escape = (str) => str.replace(/\n/g, "%0A").replace(/\r/g, "%0D").replace(/"/g, "%22");
9420
+ const escape = (str3) => str3.replace(/\n/g, "%0A").replace(/\r/g, "%0D").replace(/"/g, "%22");
9421
9421
  const normalizeLinefeeds = (value) => value.replace(/\r?\n|\r/g, "\r\n");
9422
9422
  const blobParts = [];
9423
9423
  const rn = new Uint8Array([13, 10]);
@@ -9966,15 +9966,15 @@ var require_client_h1 = __commonJS({
9966
9966
  } else {
9967
9967
  this.headers[len - 1] = Buffer.concat([this.headers[len - 1], buf]);
9968
9968
  }
9969
- const key = this.headers[len - 2];
9970
- if (key.length === 10) {
9971
- const headerName = util2.bufferToLowerCasedHeaderName(key);
9969
+ const key3 = this.headers[len - 2];
9970
+ if (key3.length === 10) {
9971
+ const headerName = util2.bufferToLowerCasedHeaderName(key3);
9972
9972
  if (headerName === "keep-alive") {
9973
9973
  this.keepAlive += buf.toString();
9974
9974
  } else if (headerName === "connection") {
9975
9975
  this.connection += buf.toString();
9976
9976
  }
9977
- } else if (key.length === 14 && util2.bufferToLowerCasedHeaderName(key) === "content-length") {
9977
+ } else if (key3.length === 14 && util2.bufferToLowerCasedHeaderName(key3) === "content-length") {
9978
9978
  this.contentLength += buf.toString();
9979
9979
  }
9980
9980
  this.trackHeader(buf.length);
@@ -10459,15 +10459,15 @@ upgrade: ${upgrade}\r
10459
10459
  }
10460
10460
  if (Array.isArray(headers)) {
10461
10461
  for (let n = 0; n < headers.length; n += 2) {
10462
- const key = headers[n + 0];
10462
+ const key3 = headers[n + 0];
10463
10463
  const val = headers[n + 1];
10464
10464
  if (Array.isArray(val)) {
10465
10465
  for (let i = 0; i < val.length; i++) {
10466
- header += `${key}: ${val[i]}\r
10466
+ header += `${key3}: ${val[i]}\r
10467
10467
  `;
10468
10468
  }
10469
10469
  } else {
10470
- header += `${key}: ${val}\r
10470
+ header += `${key3}: ${val}\r
10471
10471
  `;
10472
10472
  }
10473
10473
  }
@@ -10929,8 +10929,8 @@ var require_client_h2 = __commonJS({
10929
10929
  this[kSocket][kError] = err;
10930
10930
  this[kClient][kOnError](err);
10931
10931
  }
10932
- function onHttp2FrameError(type, code, id) {
10933
- if (id === 0) {
10932
+ function onHttp2FrameError(type, code, id3) {
10933
+ if (id3 === 0) {
10934
10934
  const err = new InformationalError(`HTTP/2: "frameError" received - type ${type}, code ${code}`);
10935
10935
  this[kSocket][kError] = err;
10936
10936
  this[kClient][kOnError](err);
@@ -10974,18 +10974,18 @@ var require_client_h2 = __commonJS({
10974
10974
  }
10975
10975
  const headers = {};
10976
10976
  for (let n = 0; n < reqHeaders.length; n += 2) {
10977
- const key = reqHeaders[n + 0];
10977
+ const key3 = reqHeaders[n + 0];
10978
10978
  const val = reqHeaders[n + 1];
10979
10979
  if (Array.isArray(val)) {
10980
10980
  for (let i = 0; i < val.length; i++) {
10981
- if (headers[key]) {
10982
- headers[key] += `,${val[i]}`;
10981
+ if (headers[key3]) {
10982
+ headers[key3] += `,${val[i]}`;
10983
10983
  } else {
10984
- headers[key] = val[i];
10984
+ headers[key3] = val[i];
10985
10985
  }
10986
10986
  }
10987
10987
  } else {
10988
- headers[key] = val;
10988
+ headers[key3] = val;
10989
10989
  }
10990
10990
  }
10991
10991
  let stream;
@@ -11450,9 +11450,9 @@ var require_redirect_handler = __commonJS({
11450
11450
  }
11451
11451
  }
11452
11452
  } else if (headers && typeof headers === "object") {
11453
- for (const key of Object.keys(headers)) {
11454
- if (!shouldRemoveHeader(key, removeContent, unknownOrigin)) {
11455
- ret.push(key, headers[key]);
11453
+ for (const key3 of Object.keys(headers)) {
11454
+ if (!shouldRemoveHeader(key3, removeContent, unknownOrigin)) {
11455
+ ret.push(key3, headers[key3]);
11456
11456
  }
11457
11457
  }
11458
11458
  } else {
@@ -12530,16 +12530,16 @@ var require_agent = __commonJS({
12530
12530
  return ret;
12531
12531
  }
12532
12532
  [kDispatch](opts, handler) {
12533
- let key;
12533
+ let key3;
12534
12534
  if (opts.origin && (typeof opts.origin === "string" || opts.origin instanceof URL)) {
12535
- key = String(opts.origin);
12535
+ key3 = String(opts.origin);
12536
12536
  } else {
12537
12537
  throw new InvalidArgumentError("opts.origin must be a non-empty string or URL.");
12538
12538
  }
12539
- let dispatcher = this[kClients].get(key);
12539
+ let dispatcher = this[kClients].get(key3);
12540
12540
  if (!dispatcher) {
12541
12541
  dispatcher = this[kFactory](opts.origin, this[kOptions]).on("drain", this[kOnDrain]).on("connect", this[kOnConnect]).on("disconnect", this[kOnDisconnect]).on("connectionError", this[kOnConnectionError]);
12542
- this[kClients].set(key, dispatcher);
12542
+ this[kClients].set(key3, dispatcher);
12543
12543
  }
12544
12544
  return dispatcher.dispatch(opts, handler);
12545
12545
  }
@@ -12778,7 +12778,7 @@ var require_proxy_agent = __commonJS({
12778
12778
  return headers;
12779
12779
  }
12780
12780
  function throwIfProxyAuthIsSent(headers) {
12781
- const existProxyAuth = headers && Object.keys(headers).find((key) => key.toLowerCase() === "proxy-authorization");
12781
+ const existProxyAuth = headers && Object.keys(headers).find((key3) => key3.toLowerCase() === "proxy-authorization");
12782
12782
  if (existProxyAuth) {
12783
12783
  throw new InvalidArgumentError("Proxy-Authorization should be sent in ProxyAgent constructor");
12784
12784
  }
@@ -14507,18 +14507,18 @@ var require_mock_utils = __commonJS({
14507
14507
  })
14508
14508
  );
14509
14509
  }
14510
- function getHeaderByName(headers, key) {
14510
+ function getHeaderByName(headers, key3) {
14511
14511
  if (Array.isArray(headers)) {
14512
14512
  for (let i = 0; i < headers.length; i += 2) {
14513
- if (headers[i].toLocaleLowerCase() === key.toLocaleLowerCase()) {
14513
+ if (headers[i].toLocaleLowerCase() === key3.toLocaleLowerCase()) {
14514
14514
  return headers[i + 1];
14515
14515
  }
14516
14516
  }
14517
14517
  return void 0;
14518
14518
  } else if (typeof headers.get === "function") {
14519
- return headers.get(key);
14519
+ return headers.get(key3);
14520
14520
  } else {
14521
- return lowerCaseEntries(headers)[key.toLocaleLowerCase()];
14521
+ return lowerCaseEntries(headers)[key3.toLocaleLowerCase()];
14522
14522
  }
14523
14523
  }
14524
14524
  function buildHeadersFromArray(headers) {
@@ -14582,41 +14582,41 @@ var require_mock_utils = __commonJS({
14582
14582
  return data.toString();
14583
14583
  }
14584
14584
  }
14585
- function getMockDispatch(mockDispatches, key) {
14586
- const basePath = key.query ? buildURL(key.path, key.query) : key.path;
14585
+ function getMockDispatch(mockDispatches, key3) {
14586
+ const basePath = key3.query ? buildURL(key3.path, key3.query) : key3.path;
14587
14587
  const resolvedPath = typeof basePath === "string" ? safeUrl(basePath) : basePath;
14588
14588
  let matchedMockDispatches = mockDispatches.filter(({ consumed }) => !consumed).filter(({ path }) => matchValue(safeUrl(path), resolvedPath));
14589
14589
  if (matchedMockDispatches.length === 0) {
14590
14590
  throw new MockNotMatchedError(`Mock dispatch not matched for path '${resolvedPath}'`);
14591
14591
  }
14592
- matchedMockDispatches = matchedMockDispatches.filter(({ method }) => matchValue(method, key.method));
14592
+ matchedMockDispatches = matchedMockDispatches.filter(({ method }) => matchValue(method, key3.method));
14593
14593
  if (matchedMockDispatches.length === 0) {
14594
- throw new MockNotMatchedError(`Mock dispatch not matched for method '${key.method}' on path '${resolvedPath}'`);
14594
+ throw new MockNotMatchedError(`Mock dispatch not matched for method '${key3.method}' on path '${resolvedPath}'`);
14595
14595
  }
14596
- matchedMockDispatches = matchedMockDispatches.filter(({ body }) => typeof body !== "undefined" ? matchValue(body, key.body) : true);
14596
+ matchedMockDispatches = matchedMockDispatches.filter(({ body }) => typeof body !== "undefined" ? matchValue(body, key3.body) : true);
14597
14597
  if (matchedMockDispatches.length === 0) {
14598
- throw new MockNotMatchedError(`Mock dispatch not matched for body '${key.body}' on path '${resolvedPath}'`);
14598
+ throw new MockNotMatchedError(`Mock dispatch not matched for body '${key3.body}' on path '${resolvedPath}'`);
14599
14599
  }
14600
- matchedMockDispatches = matchedMockDispatches.filter((mockDispatch2) => matchHeaders(mockDispatch2, key.headers));
14600
+ matchedMockDispatches = matchedMockDispatches.filter((mockDispatch2) => matchHeaders(mockDispatch2, key3.headers));
14601
14601
  if (matchedMockDispatches.length === 0) {
14602
- const headers = typeof key.headers === "object" ? JSON.stringify(key.headers) : key.headers;
14602
+ const headers = typeof key3.headers === "object" ? JSON.stringify(key3.headers) : key3.headers;
14603
14603
  throw new MockNotMatchedError(`Mock dispatch not matched for headers '${headers}' on path '${resolvedPath}'`);
14604
14604
  }
14605
14605
  return matchedMockDispatches[0];
14606
14606
  }
14607
- function addMockDispatch(mockDispatches, key, data) {
14607
+ function addMockDispatch(mockDispatches, key3, data) {
14608
14608
  const baseData = { timesInvoked: 0, times: 1, persist: false, consumed: false };
14609
14609
  const replyData = typeof data === "function" ? { callback: data } : { ...data };
14610
- const newMockDispatch = { ...baseData, ...key, pending: true, data: { error: null, ...replyData } };
14610
+ const newMockDispatch = { ...baseData, ...key3, pending: true, data: { error: null, ...replyData } };
14611
14611
  mockDispatches.push(newMockDispatch);
14612
14612
  return newMockDispatch;
14613
14613
  }
14614
- function deleteMockDispatch(mockDispatches, key) {
14614
+ function deleteMockDispatch(mockDispatches, key3) {
14615
14615
  const index = mockDispatches.findIndex((dispatch) => {
14616
14616
  if (!dispatch.consumed) {
14617
14617
  return false;
14618
14618
  }
14619
- return matchKey(dispatch, key);
14619
+ return matchKey(dispatch, key3);
14620
14620
  });
14621
14621
  if (index !== -1) {
14622
14622
  mockDispatches.splice(index, 1);
@@ -14636,9 +14636,9 @@ var require_mock_utils = __commonJS({
14636
14636
  const keys = Object.keys(data);
14637
14637
  const result = [];
14638
14638
  for (let i = 0; i < keys.length; ++i) {
14639
- const key = keys[i];
14640
- const value = data[key];
14641
- const name = Buffer.from(`${key}`);
14639
+ const key3 = keys[i];
14640
+ const value = data[key3];
14641
+ const name = Buffer.from(`${key3}`);
14642
14642
  if (Array.isArray(value)) {
14643
14643
  for (let j = 0; j < value.length; ++j) {
14644
14644
  result.push(name, Buffer.from(`${value[j]}`));
@@ -14660,8 +14660,8 @@ var require_mock_utils = __commonJS({
14660
14660
  return Buffer.concat(buffers).toString("utf8");
14661
14661
  }
14662
14662
  function mockDispatch(opts, handler) {
14663
- const key = buildKey(opts);
14664
- const mockDispatch2 = getMockDispatch(this[kDispatches], key);
14663
+ const key3 = buildKey(opts);
14664
+ const mockDispatch2 = getMockDispatch(this[kDispatches], key3);
14665
14665
  mockDispatch2.timesInvoked++;
14666
14666
  if (mockDispatch2.data.callback) {
14667
14667
  mockDispatch2.data = { ...mockDispatch2.data, ...mockDispatch2.data.callback(opts) };
@@ -14671,7 +14671,7 @@ var require_mock_utils = __commonJS({
14671
14671
  mockDispatch2.consumed = !persist && timesInvoked >= times;
14672
14672
  mockDispatch2.pending = timesInvoked < times;
14673
14673
  if (error !== null) {
14674
- deleteMockDispatch(this[kDispatches], key);
14674
+ deleteMockDispatch(this[kDispatches], key3);
14675
14675
  handler.onError(error);
14676
14676
  return true;
14677
14677
  }
@@ -14696,7 +14696,7 @@ var require_mock_utils = __commonJS({
14696
14696
  handler.onHeaders?.(statusCode, responseHeaders, resume, getStatusText(statusCode));
14697
14697
  handler.onData?.(Buffer.from(responseData));
14698
14698
  handler.onComplete?.(responseTrailers);
14699
- deleteMockDispatch(mockDispatches, key);
14699
+ deleteMockDispatch(mockDispatches, key3);
14700
14700
  }
14701
14701
  function resume() {
14702
14702
  }
@@ -16603,16 +16603,16 @@ var require_dispatcher_weakref = __commonJS({
16603
16603
  constructor(finalizer) {
16604
16604
  this.finalizer = finalizer;
16605
16605
  }
16606
- register(dispatcher, key) {
16606
+ register(dispatcher, key3) {
16607
16607
  if (dispatcher.on) {
16608
16608
  dispatcher.on("disconnect", () => {
16609
16609
  if (dispatcher[kConnected] === 0 && dispatcher[kSize] === 0) {
16610
- this.finalizer(key);
16610
+ this.finalizer(key3);
16611
16611
  }
16612
16612
  });
16613
16613
  }
16614
16614
  }
16615
- unregister(key) {
16615
+ unregister(key3) {
16616
16616
  }
16617
16617
  };
16618
16618
  module.exports = function() {
@@ -20065,8 +20065,8 @@ var require_util6 = __commonJS({
20065
20065
  if (!part.includes("=")) {
20066
20066
  throw new Error("Invalid unparsed");
20067
20067
  }
20068
- const [key, ...value] = part.split("=");
20069
- out.push(`${key.trim()}=${value.join("=")}`);
20068
+ const [key3, ...value] = part.split("=");
20069
+ out.push(`${key3.trim()}=${value.join("=")}`);
20070
20070
  }
20071
20071
  return out.join("; ");
20072
20072
  }
@@ -20265,9 +20265,9 @@ var require_cookies = __commonJS({
20265
20265
  webidl.argumentLengthCheck(arguments, 2, "setCookie");
20266
20266
  webidl.brandCheck(headers, Headers, { strict: false });
20267
20267
  cookie = webidl.converters.Cookie(cookie);
20268
- const str = stringify(cookie);
20269
- if (str) {
20270
- headers.append("Set-Cookie", str);
20268
+ const str3 = stringify(cookie);
20269
+ if (str3) {
20270
+ headers.append("Set-Cookie", str3);
20271
20271
  }
20272
20272
  }
20273
20273
  webidl.converters.DeleteCookieAttributes = webidl.dictionaryConverter([
@@ -22793,34 +22793,38 @@ function sessionId() {
22793
22793
  async function reach(url, init) {
22794
22794
  return send(url, init, sessionId());
22795
22795
  }
22796
- function reachAs(session) {
22797
- return (url, init) => send(url, init, session);
22796
+ function reachAs(session, instance) {
22797
+ return (url, init) => send(url, init, session, instance);
22798
22798
  }
22799
- async function send(url, init, session) {
22799
+ function setClient(name) {
22800
+ CLIENT = name;
22801
+ }
22802
+ async function send(url, init, session, instance = envSession("PAIGY_INSTANCE_ID") ?? INSTANCE_ID) {
22800
22803
  try {
22801
22804
  const headers = {
22802
22805
  ...init?.headers,
22803
- "x-paigy-instance": INSTANCE_ID,
22804
- "x-paigy-session": session
22806
+ "x-paigy-instance": instance,
22807
+ "x-paigy-session": session,
22808
+ ...CLIENT ? { "x-paigy-client": CLIENT } : {}
22805
22809
  };
22806
22810
  return await fetch(url, { ...init, headers, dispatcher: await proxy() });
22807
22811
  } catch (e) {
22808
22812
  throw new Error(`${NETWORK_MSG} (${e?.message ?? String(e)})`);
22809
22813
  }
22810
22814
  }
22811
- function addErrorMessage(res, key, errorMessage, refs) {
22815
+ function addErrorMessage(res, key22, errorMessage, refs) {
22812
22816
  if (!refs?.errorMessages)
22813
22817
  return;
22814
22818
  if (errorMessage) {
22815
22819
  res.errorMessage = {
22816
22820
  ...res.errorMessage,
22817
- [key]: errorMessage
22821
+ [key22]: errorMessage
22818
22822
  };
22819
22823
  }
22820
22824
  }
22821
- function setResponseValueAndErrors(res, key, value, errorMessage, refs) {
22822
- res[key] = value;
22823
- addErrorMessage(res, key, errorMessage, refs);
22825
+ function setResponseValueAndErrors(res, key22, value, errorMessage, refs) {
22826
+ res[key22] = value;
22827
+ addErrorMessage(res, key22, errorMessage, refs);
22824
22828
  }
22825
22829
  function parseAnyDef(refs) {
22826
22830
  if (refs.target !== "openAi") {
@@ -23283,11 +23287,11 @@ function parseRecordDef(def, refs) {
23283
23287
  return {
23284
23288
  type: "object",
23285
23289
  required: def.keyType._def.values,
23286
- properties: def.keyType._def.values.reduce((acc, key) => ({
23290
+ properties: def.keyType._def.values.reduce((acc, key22) => ({
23287
23291
  ...acc,
23288
- [key]: parseDef(def.valueType._def, {
23292
+ [key22]: parseDef(def.valueType._def, {
23289
23293
  ...refs,
23290
- currentPath: [...refs.currentPath, "properties", key]
23294
+ currentPath: [...refs.currentPath, "properties", key22]
23291
23295
  }) ?? parseAnyDef(refs)
23292
23296
  }), {}),
23293
23297
  additionalProperties: refs.rejectedAdditionalProperties
@@ -23350,10 +23354,10 @@ function parseMapDef(def, refs) {
23350
23354
  }
23351
23355
  function parseNativeEnumDef(def) {
23352
23356
  const object = def.values;
23353
- const actualKeys = Object.keys(def.values).filter((key) => {
23354
- return typeof object[object[key]] !== "number";
23357
+ const actualKeys = Object.keys(def.values).filter((key22) => {
23358
+ return typeof object[object[key22]] !== "number";
23355
23359
  });
23356
- const actualValues = actualKeys.map((key) => object[key]);
23360
+ const actualValues = actualKeys.map((key22) => object[key22]);
23357
23361
  const parsedTypes = Array.from(new Set(actualValues.map((values) => typeof values)));
23358
23362
  return {
23359
23363
  type: parsedTypes.length === 1 ? parsedTypes[0] === "string" ? "string" : "number" : ["string", "number"],
@@ -23687,8 +23691,8 @@ function mcpInputSchema(s) {
23687
23691
  return draft2020(schema);
23688
23692
  }
23689
23693
  function sessionSlot(sessionId2) {
23690
- const id = sessionId2 ?? sessionId();
23691
- return `session:${id.slice(0, 8)}`;
23694
+ const id22 = sessionId2 ?? sessionId();
23695
+ return `session:${id22.slice(0, 8)}`;
23692
23696
  }
23693
23697
  function agentName() {
23694
23698
  return process.env.PAIGY_AGENT || sessionSlot();
@@ -23743,12 +23747,15 @@ function updateSlot(agent2, patch) {
23743
23747
  }
23744
23748
  function slotIdentity(agent2) {
23745
23749
  const t = readTokenFile()[agent2];
23746
- return { name: t?.name ?? null, voice: t?.voice ?? null, tokenId: t?.token_id ?? null, workspace: t?.workspace ?? null, harness: t?.harness ?? null, sessionId: t?.session_id ?? null };
23750
+ return { name: t?.name ?? null, voice: t?.voice ?? null, tokenId: t?.token_id ?? null, workspace: t?.workspace ?? null, harness: t?.harness ?? null, sessionId: t?.session_id ?? null, fullSession: t?.full_session ?? null };
23747
23751
  }
23748
23752
  function readToken(agent2 = agentName()) {
23749
23753
  if (process.env.PAIGY_TOKEN) return process.env.PAIGY_TOKEN;
23750
23754
  return readTokenFile()[agent2]?.access_token ?? "";
23751
23755
  }
23756
+ function readSlot(agent2) {
23757
+ return readTokenFile()[agent2]?.access_token ?? "";
23758
+ }
23752
23759
  function listSlots() {
23753
23760
  return Object.keys(readTokenFile());
23754
23761
  }
@@ -23831,11 +23838,16 @@ async function updateGoal(goalId, input, opts = {}) {
23831
23838
  if (!res.ok) await fail("update_goal", res);
23832
23839
  return await res.json();
23833
23840
  }
23834
- async function hatch(name, voice = null) {
23835
- const res = await ensureAuthed(await reach(`${BACKEND_URL}/api/hatch`, {
23841
+ async function hatch(name, voice = null, opts = {}) {
23842
+ const res = await ensureAuthed(await (opts.reach ?? reach)(`${BACKEND_URL}/api/hatch`, {
23836
23843
  method: "POST",
23837
23844
  headers: { "content-type": "application/json", authorization: `Bearer ${authToken()}` },
23838
- body: JSON.stringify({ name, voice })
23845
+ body: JSON.stringify({
23846
+ name,
23847
+ voice,
23848
+ ...opts.brief ? { brief: opts.brief } : {},
23849
+ ...opts.parentGoalId ? { parentGoalId: opts.parentGoalId } : {}
23850
+ })
23839
23851
  }));
23840
23852
  if (!res.ok) throw new Error(`hatch failed: ${res.status} ${await res.text()}`);
23841
23853
  return await res.json();
@@ -23885,7 +23897,9 @@ async function recordDecision(decision, opts = {}) {
23885
23897
  async function heartbeat(runtime, opts = {}) {
23886
23898
  const body = {
23887
23899
  ...runtime !== void 0 ? { runtime } : {},
23888
- ...opts.activity !== void 0 ? { activity: opts.activity } : {}
23900
+ ...opts.activity !== void 0 ? { activity: opts.activity } : {},
23901
+ // A listener's beat (`paigy-listen`): stamps when it last swept, and is not presence.
23902
+ ...opts.listening ? { listening: true } : {}
23889
23903
  };
23890
23904
  const res = await ensureAuthed(await reach(`${BACKEND_URL}/api/presence`, {
23891
23905
  method: "POST",
@@ -23968,6 +23982,7 @@ async function contact(input, opts = {}) {
23968
23982
  let deliveryId;
23969
23983
  let deliveries = [];
23970
23984
  let recorded = [];
23985
+ let demoted;
23971
23986
  if ("deliveryId" in parsed) {
23972
23987
  deliveryId = parsed.deliveryId;
23973
23988
  } else {
@@ -23998,13 +24013,14 @@ async function contact(input, opts = {}) {
23998
24013
  if (!res.ok) await fail("batch contact", res);
23999
24014
  const receipt = await res.json();
24000
24015
  deliveries = receipt.deliveries ?? [];
24016
+ if (parsed.channel === "call" && receipt.channel && receipt.channel !== "call") demoted = DEMOTED;
24001
24017
  recorded = receipt.recorded ?? [];
24002
24018
  if (deliveries.length === 0 && recorded.length) return { sent: false, recorded, message: NOT_SENT };
24003
24019
  if (deliveries.length === 0) throw new Error("Goal contact returned no Delivery identities");
24004
24020
  deliveryId = deliveries[0]?.deliveryId ?? "";
24005
24021
  if (!deliveryId) throw new Error("Goal contact returned no valid Delivery identity");
24006
24022
  }
24007
- const all = deliveries.filter((d) => !!d.deliveryId && !!d.goalId).map(({ id, deliveryId: deliveryId2, goalId }) => ({ ...id ? { id } : {}, deliveryId: deliveryId2, goalId }));
24023
+ const all = deliveries.filter((d) => !!d.deliveryId && !!d.goalId).map(({ id: id22, deliveryId: deliveryId2, goalId }) => ({ ...id22 ? { id: id22 } : {}, deliveryId: deliveryId2, goalId }));
24008
24024
  const joinedCard = deliveries[0]?.joinedCard === true;
24009
24025
  const joinedCall = deliveries[0]?.joinedCall === true;
24010
24026
  const read = async (signal2) => {
@@ -24016,7 +24032,8 @@ async function contact(input, opts = {}) {
24016
24032
  ...all.length > 1 ? { deliveries: all } : {},
24017
24033
  ...recorded.length ? { recorded, notSent: NOT_SENT } : {},
24018
24034
  ...joinedCard ? { joinedCard: true } : {},
24019
- ...joinedCall ? { joinedCall: true } : {}
24035
+ ...joinedCall ? { joinedCall: true } : {},
24036
+ ...demoted ? { demoted } : {}
24020
24037
  };
24021
24038
  };
24022
24039
  const settled = (d) => d.kind === "notification" || d.state === "closed" || d.answers.length > 0 || d.entries.some((e) => e.kind === "contribution");
@@ -24148,9 +24165,9 @@ function connect(line) {
24148
24165
  ws.addEventListener("error", again);
24149
24166
  }
24150
24167
  function subscribeRealtime(args) {
24151
- const key = `${args.url} ${args.anonKey}`;
24152
- let line = lines.get(key);
24153
- if (!line) lines.set(key, line = { url: args.url, anonKey: args.anonKey, open: false, attempt: 0, ref: 0, topics: /* @__PURE__ */ new Map() });
24168
+ const key22 = `${args.url} ${args.anonKey}`;
24169
+ let line = lines.get(key22);
24170
+ if (!line) lines.set(key22, line = { url: args.url, anonKey: args.anonKey, open: false, attempt: 0, ref: 0, topics: /* @__PURE__ */ new Map() });
24154
24171
  let t = line.topics.get(args.topic);
24155
24172
  if (!t) {
24156
24173
  line.topics.set(args.topic, t = { listeners: /* @__PURE__ */ new Set(), joined: false, attempt: 0 });
@@ -24172,7 +24189,7 @@ function subscribeRealtime(args) {
24172
24189
  if (line.open) frame(line, `realtime:${args.topic}`, "phx_leave", {});
24173
24190
  return;
24174
24191
  }
24175
- lines.delete(key);
24192
+ lines.delete(key22);
24176
24193
  stop(line);
24177
24194
  try {
24178
24195
  line.ws?.close();
@@ -24204,7 +24221,29 @@ async function subscribeWake(onNudge, opts = {}) {
24204
24221
  }
24205
24222
  };
24206
24223
  }
24207
- var import_undici, require2, BACKEND_URL, NETWORK_MSG, PROXY_ENV, agent, INSTANCE_ID, WORKSPACE_ID, envSession, lineage, ignoreOverride, defaultOptions, getDefaultOptions, getRefs, getRelativePath, parseCatchDef, integerDateParser, isJsonSchema7AllOfType, emojiRegex2, zodPatterns, ALPHA_NUMERIC, primitiveMappings, asAnyOf, parseOptionalDef, parsePipelineDef, parseReadonlyDef, selectParser, get$ref, addMeta, zodToJsonSchema, OPTIONS_MIN, OPTIONS_MAX, OptionSchema, OptionInputSchema, NIGHT, AskInputSchema, StartContactSchema, ContactSchema, CONTACT_SCHEMA, CONTACT_DESCRIPTION, CreateGoalSchema, CreateGoalToolSchema, CREATE_GOAL_DESCRIPTION, UpdateGoalSchema, UpdateGoalToolSchema, ClaimGoalSchema, GetGoalSchema, GET_GOAL_DESCRIPTION, UPDATE_GOAL_DESCRIPTION, CLAIM_GOAL_DESCRIPTION, CHECK_REPLIES_DESCRIPTION, CheckRepliesSchema, AGENT_TOOLS, AGENT_TOOL_NAMES, LIVE_MS, WORKING_MS, ContextSchema, ParticipantSchema, TransformSchema, VisualSchema, NotifyLevelSchema, SelectShapeSchema, ReceiptEventSchema, AttentionSchema, NotifyRequestFields, NotifyRequestSchema, NotifyStatusSchema, AgentStateSchema, TurnSchema, UserAnswerSchema, IntentSchema, RideAlongSchema, AwaitItemSchema, VoiceKeySchema, AgendaTurnSchema, CLAIM_STALE_MS, InboxItemSchema, APNS_TOKEN_RE, PushTokenSchema, MissedCallSchema, clock, QUIET, BrokerTuningSchema, UserSettingsSchema, HistoryWorkSchema, HistoryEntrySchema, HistoryPageSchema, ACTIVITY_LINES, ACTIVITY_LINE_MAX, AgentActivitySchema, ConnectionSummarySchema, LedgerItemSchema, AgentLedgerSchema, ReassignResultSchema, MoveRingSchema, MoveSchema, QueueQuestionSchema, QueueReplySchema, QueueItemSchema, COLD_AFTER_MS, NoteSourceSchema, NoteStatusSchema, NoteRepeatSchema, DecisionSchema, NoteSchema, TriageItemSchema, TriageAssignmentSchema, TriageStatusSchema, SubmitTriageSchema, TriageProposalSchema, AcceptTriageSchema, AcceptTriageResultSchema, DeliveryModeSchema, WAKE_EVENT, wakeChannel, RegisterDeliverySchema, OAuthStartSchema, DeliveryConfigSchema, HostDecisionSchema, WakeNudgeSchema, PairingStatusSchema, DeviceCodeSchema, DeviceInfoSchema, DeviceTokenSchema, SupportRequestSchema, NotificationFeedbackKindSchema, SlimOptionSchema, QuestionRowSchema, WorkStateSchema, WorkRowSchema, ComputerRowSchema, AgentRowSchema, SnapshotSchema, CallRecapSchema, TOKEN_PATH, KEY_PATH, sleep, UnpairedError, RevokedError, ApiError, tokenOverride, authToken, AWAIT_WINDOW_MS, asked, NOT_SENT, HEARTBEAT_MS, RETRY_MS, JOIN, JOIN_TIMEOUT_MS, lines;
24224
+ function withCodexEnv(text) {
24225
+ const head = /^\[mcp_servers\.paigy\][ \t]*(?:#[^\n]*)?\r?\n/m.exec(text);
24226
+ if (!head) return null;
24227
+ const start = head.index + head[0].length;
24228
+ const next = /^\[/m.exec(text.slice(start));
24229
+ const end = next ? start + next.index : text.length;
24230
+ const block2 = text.slice(start, end);
24231
+ const assignment = /^[ \t]*env_vars[ \t]*=/m.exec(block2);
24232
+ let updated;
24233
+ if (!assignment) updated = `env_vars = [${CODEX_ENV.map((v) => JSON.stringify(v)).join(", ")}]
24234
+ ${block2}`;
24235
+ else {
24236
+ const array = /^[ \t]*env_vars[ \t]*=[ \t]*\[((?:#[^\n]*|[^\]"'#]|"[^"\n]*"|'[^'\n]*')*)\]/m.exec(block2);
24237
+ if (!array) return null;
24238
+ const existing = [...array[1].matchAll(/"([^"\n]*)"|'([^'\n]*)'|#[^\n]*/g)].flatMap((m) => m[0].startsWith("#") ? [] : [m[1] ?? m[2]]);
24239
+ const missing2 = CODEX_ENV.filter((v) => !existing.includes(v));
24240
+ if (!missing2.length) return text;
24241
+ const opening = array.index + array[0].indexOf("[") + 1;
24242
+ updated = block2.slice(0, opening) + missing2.map((v) => JSON.stringify(v)).join(", ") + (existing.length ? ", " : "") + block2.slice(opening);
24243
+ }
24244
+ return text.slice(0, start) + updated + text.slice(end);
24245
+ }
24246
+ var import_undici, require2, CODEX_ENV, BACKEND_URL, NETWORK_MSG, PROXY_ENV, agent, INSTANCE_ID, WORKSPACE_ID, envSession, lineage, CLIENT, ignoreOverride, defaultOptions, getDefaultOptions, getRefs, getRelativePath, parseCatchDef, integerDateParser, isJsonSchema7AllOfType, emojiRegex2, zodPatterns, ALPHA_NUMERIC, primitiveMappings, asAnyOf, parseOptionalDef, parsePipelineDef, parseReadonlyDef, selectParser, get$ref, addMeta, zodToJsonSchema, OPTIONS_MIN, OPTIONS_MAX, OptionSchema, OptionInputSchema, NIGHT, AskInputSchema, StartContactSchema, ContactSchema, CONTACT_SCHEMA, CONTACT_DESCRIPTION, CreateGoalSchema, CreateGoalToolSchema, CREATE_GOAL_DESCRIPTION, UpdateGoalSchema, UpdateGoalToolSchema, ClaimGoalSchema, GetGoalSchema, GET_GOAL_DESCRIPTION, UPDATE_GOAL_DESCRIPTION, CLAIM_GOAL_DESCRIPTION, CHECK_REPLIES_DESCRIPTION, CheckRepliesSchema, AGENT_TOOLS, AGENT_TOOL_NAMES, id, key, participant, SourceSchema, ResultRefSchema, NodeRefSchema, DependencySchema, goalState, existingGoalChanges, GoalChangeSchema, BrainGoalChangeSchema, option, QuestionChangeSchema, lessonScope, LessonChangeSchema, BrainNextSchema, messageBase, BrainMessageSchema, BrainSearchSchema, BrainResultSchema, str, strs, CompactResultSchema, COMPACT_RESULT_JSON_SCHEMA, LIVE_MS, WORKING_MS, ContextSchema, ParticipantSchema, TransformSchema, VisualSchema, NotifyLevelSchema, SelectShapeSchema, ReceiptEventSchema, AttentionSchema, NotifyRequestFields, NotifyRequestSchema, NotifyStatusSchema, AgentStateSchema, TurnSchema, UserAnswerSchema, IntentSchema, RideAlongSchema, AwaitItemSchema, VoiceKeySchema, AgendaTurnSchema, CLAIM_STALE_MS, InboxItemSchema, APNS_TOKEN_RE, PushTokenSchema, MissedCallSchema, clock, QUIET, BrokerTuningSchema, UserSettingsSchema, HistoryWorkSchema, HistoryEntrySchema, HistoryPageSchema, ACTIVITY_LINES, ACTIVITY_LINE_MAX, AgentActivitySchema, ConnectionSummarySchema, LedgerItemSchema, AgentLedgerSchema, ReassignResultSchema, MoveRingSchema, MoveSchema, QueueQuestionSchema, QueueReplySchema, QueueItemSchema, QueueDeltaSchema, COLD_AFTER_MS, NoteSourceSchema, NoteStatusSchema, NoteRepeatSchema, DecisionSchema, NoteSchema, TriageItemSchema, TriageAssignmentSchema, TriageStatusSchema, SubmitTriageSchema, TriageProposalSchema, AcceptTriageSchema, AcceptTriageResultSchema, DeliveryModeSchema, WAKE_EVENT, wakeChannel, RegisterDeliverySchema, OAuthStartSchema, DeliveryConfigSchema, HostDecisionSchema, WakeNudgeSchema, PairingStatusSchema, DeviceCodeSchema, DeviceInfoSchema, DeviceTokenSchema, SupportRequestSchema, NotificationFeedbackKindSchema, SlimOptionSchema, QuestionRowSchema, WorkStateSchema, WorkRowSchema, ComputerRowSchema, AgentRowSchema, SnapshotSchema, CallRecapSchema, TOKEN_PATH, KEY_PATH, sleep, UnpairedError, RevokedError, ApiError, tokenOverride, authToken, AWAIT_WINDOW_MS, asked, NOT_SENT, DEMOTED, HEARTBEAT_MS, RETRY_MS, JOIN, JOIN_TIMEOUT_MS, lines;
24208
24247
  var init_dist = __esm({
24209
24248
  "../../packages/sdk/dist/index.js"() {
24210
24249
  "use strict";
@@ -24215,8 +24254,10 @@ var init_dist = __esm({
24215
24254
  init_v3();
24216
24255
  init_v3();
24217
24256
  init_zod();
24257
+ init_zod();
24218
24258
  import_undici = __toESM(require_undici(), 1);
24219
24259
  require2 = __sdkCreateRequire(import.meta.url);
24260
+ CODEX_ENV = ["CODEX_THREAD_ID", "CODEX_SESSION_ID", "CODEX_HOME", "PAIGY_TOKEN", "PAIGY_SESSION_ID", "PAIGY_HARNESS", "PAIGY_INSTANCE_ID", "PAIGY_ON_WAKE"];
24220
24261
  BACKEND_URL = process.env.PAIGY_BACKEND_URL ?? "https://paigy.ai";
24221
24262
  NETWORK_MSG = `Can't reach ${BACKEND_URL} \u2014 the connection was blocked or dropped before an HTTP response. If this agent runs in a sandboxed environment with a network allowlist (e.g. Claude Code on the web, CI), ask the user to add the Paigy domain (paigy.ai) to the environment's allowed domains, then retry.`;
24222
24263
  PROXY_ENV = ["HTTPS_PROXY", "https_proxy", "HTTP_PROXY", "http_proxy"];
@@ -24228,8 +24269,8 @@ var init_dist = __esm({
24228
24269
  return INSTANCE_ID;
24229
24270
  }
24230
24271
  })();
24231
- envSession = (key) => {
24232
- const v = process.env[key];
24272
+ envSession = (key22) => {
24273
+ const v = process.env[key22];
24233
24274
  return v && v.trim() ? v : void 0;
24234
24275
  };
24235
24276
  ignoreOverride = /* @__PURE__ */ Symbol("Let zodToJsonSchema decide on which parser to use");
@@ -24614,34 +24655,31 @@ var init_dist = __esm({
24614
24655
  NIGHT = { from: 23, to: 7 };
24615
24656
  AskInputSchema = external_exports.object({
24616
24657
  id: external_exports.string().optional().describe("Optional idempotency key or client-side ID for this specific ask."),
24617
- parentId: external_exports.string().uuid().optional().describe("The Goal this question is about \u2014 usually the one you are working on. The question goes onto that Goal and its answer comes back there. Omit it and Paigy places the question in the tree itself."),
24658
+ parentId: external_exports.string().uuid().optional().describe("The Goal this question is about \u2014 usually the one you are working on. The question goes onto that Goal and its answer comes back there. Omit it and the question starts a new Goal of yours."),
24618
24659
  repo: external_exports.string().optional().describe("Optional repository context."),
24619
24660
  ask: external_exports.string().trim().min(1).max(1e4).describe(
24620
- "ONE question, and only what is needed to answer it. Several questions are several asks in the array, one each: an answer settles the one ask it was given in the shape that ask declares, so a person who answers the part of a bundled ask that interested them settles nothing and is asked again. Paigy reads every ask once and takes a bundled one apart into its own cards anyway \u2014 each question a Question on the one Goal the ask lands on, never a Goal of its own \u2014 but the words it splits are its reading, not yours. News, progress and findings are their own contact; ANY contact for a person already on a call JOINS that call, whatever channel you asked for, so several arrive as one call."
24661
+ "ONE question, and only what is needed to answer it. Several questions are several asks in the array, one each: an answer settles the one ask it was given in the shape that ask declares, so a person who answers the part of a bundled ask that interested them settles nothing and is asked again. Paigy sends each ask exactly as you wrote it: a bundled ask arrives as one card. News, progress and findings are their own contact; ANY contact for a person already on a call JOINS that call, whatever channel you asked for, so several arrive as one call."
24621
24662
  ),
24622
24663
  options: external_exports.array(OptionInputSchema).min(1).max(6).optional(),
24623
- // A CHECKLIST WHEN THE CHOICES ARE INDEPENDENT (owner, 2026-10-02 01:44 UTC: "bring back the
24624
- // checklist mode of answering"). The answer shape was taken off this surface with the wire form
24625
- // (#575) on the promise that Paigy would derive it, and the Goal-scoped contact that replaced it
24626
- // only ever sends pick-one or words (`goal/intake.ts` `answerOf`): three independent fixes went out
24627
- // as "All three / 1 and 3 only / Just log it", which the person could not read without the text and
24628
- // could not answer as the ticks he wanted. "many" is the one shape an agent knows and the read does
24629
- // not: whether its own options exclude each other.
24664
+ // HOW THE OPTIONS ARE ANSWERED, SAID BY THE AGENT (owner, 2026-10-02: "one and many makes sense";
24665
+ // brain_prompts.md §1: structured agent questions need no model). Every card was pick-one while no
24666
+ // agent sent this; no read reshapes cards any more, so this is the card's shape, and the
24667
+ // description says so plainly.
24630
24668
  select: external_exports.enum(["one", "many"]).optional().describe(
24631
- 'How the options are answered: "one" (default) to pick one, "many" to tick any number of them. Use "many" when the options are independent things they may want several of \u2014 never combinations of them like "all three" or "1 and 3". Ignored without options.'
24669
+ 'How the options are answered: "many" makes a checklist (they may want several, e.g. independent fixes), "one" (the default) a pick (choosing one rules out the others). Send "many" whenever more than one option could be wanted at once. The person can always answer in their own words as well. Ignored without options.'
24632
24670
  ),
24633
24671
  answers: external_exports.string().trim().regex(/^[0-9a-fA-F-]{8,36}$/).optional().describe(
24634
24672
  "Your reply answers a question the person asked you: the id the conversation shows for it (8 characters or whole). Their question closes with this reply as its answer, and any decision of yours it was holding back goes back to them. Needs parentId: the Goal the question is on. The reply is sent to them as it is; to also ask something new, send that as its own ask."
24635
24673
  )
24636
24674
  }).strict();
24637
24675
  StartContactSchema = external_exports.object({
24638
- asks: external_exports.array(AskInputSchema).min(1).describe("The questions to pose, one per object. An ask with a parentId is filed on that Goal as it is; only an ask naming no Goal is placed in the tree by Paigy."),
24676
+ asks: external_exports.array(AskInputSchema).min(1).describe("The questions to pose, one per object. An ask with a parentId is filed on that Goal as it is; an ask naming no Goal starts a new Goal of yours."),
24639
24677
  waiting: external_exports.enum(["none", "hard"]).default("none").describe("hard requests a call even when channel is notification; user permissions and ring cooldowns still apply."),
24640
24678
  channel: external_exports.enum(["notification", "call"]).default("notification")
24641
24679
  }).strict();
24642
24680
  ContactSchema = external_exports.union([StartContactSchema, external_exports.object({ deliveryId: external_exports.string().uuid() }).strict()]);
24643
24681
  CONTACT_SCHEMA = { type: "object", ...mcpInputSchema(ContactSchema) };
24644
- CONTACT_DESCRIPTION = "Contact the user with one or more asks/questions. Pass an array of asks (each with 'ask', optional 'options', 'select', 'id', 'parentId', 'repo'), plus channel:'notification'|'call', and waiting:'none'|'hard'. An ask that names a Goal (parentId) goes onto that Goal; one that names none is placed in the person's tree by Paigy. Notification returns immediately; collect durable answers with check_replies. On stdio, a Call holds one cancellable ~45s window; continue with ONLY {deliveryId}. One question per 'ask'; several questions are several objects in 'asks'. A bundled ask is taken apart into its own cards by Paigy's one intake read, every one on the Goal the ask lands on; separate pieces of work are separate asks. An ask with no options that is not blocking is a report, and a report is an UPDATE, never a claim on them: it reaches them and is listed apart from what waits on them, so no answer is owed and none should be awaited. On a Goal whose report card is still open it is added to that card, with no new push; one that only says where your work stands while under way is recorded as the Goal's progress, not sent (the result says so). Send options (or waiting:'hard') when you actually need an answer. Each option's label must stand on its own \u2014 the person may see only the labels \u2014 so never a label that points into your text ('All three', 'Option 2', '1 and 3 only'); when the options are independent and they may want several, pass select:'many' and they get a checklist. If the person is already on a call, your contact joins that call automatically \u2014 whatever channel you asked for, with no ring \u2014 and the Delivery it returns IS that call: reread it with contact({deliveryId}) to see everything answered on it so far, and contact again while it is live to add information or a further question to the same call.";
24682
+ CONTACT_DESCRIPTION = "Contact the user with one or more asks/questions. Pass an array of asks (each with 'ask', optional 'options', 'select', 'id', 'parentId', 'repo'), plus channel:'notification'|'call', and waiting:'none'|'hard'. An ask that names a Goal (parentId) goes onto that Goal; one that names none starts a new Goal of yours. Notification returns immediately; collect durable answers with check_replies. On stdio, a Call holds one cancellable ~45s window; continue with ONLY {deliveryId}. One question per 'ask'; several questions are several objects in 'asks'. Each ask is sent exactly as written, with no reading in between: a bundled ask arrives as one card, so separate questions are separate asks. An ask with no options that is not blocking is a report, and a report is an UPDATE, never a claim on them: it reaches them and is listed apart from what waits on them, so no answer is owed and none should be awaited. On a Goal whose report card is still open it is added to that card, with no new push; Where your work stands while under way is progress: report it with update_goal, not contact. Send options (or waiting:'hard') when you actually need an answer. Each option's label must stand on its own \u2014 the person may see only the labels \u2014 so never a label that points into your text ('All three', 'Option 2', '1 and 3 only'). select:'many' makes the card a checklist, for independent options they may want several of; select:'one' (the default) a pick, for alternatives. The person can always answer in their own words, so never add an 'Other' option. If the person is already on a call, your contact joins that call automatically \u2014 whatever channel you asked for, with no ring \u2014 and the Delivery it returns IS that call: reread it with contact({deliveryId}) to see everything answered on it so far, and contact again while it is live to add information or a further question to the same call.";
24645
24683
  CreateGoalSchema = external_exports.object({
24646
24684
  outcome: external_exports.string().trim().min(1).max(1e4),
24647
24685
  /** The work's NAME (#2115) — one to five words, how a person refers to it out loud ("the night
@@ -24664,7 +24702,7 @@ var init_dist = __esm({
24664
24702
  CreateGoalToolSchema = CreateGoalSchema.extend({
24665
24703
  idempotencyKey: CreateGoalSchema.shape.idempotencyKey.optional().describe("Optional. One is minted per call; pass your own only so a retry lands on the same Goal.")
24666
24704
  }).strict();
24667
- CREATE_GOAL_DESCRIPTION = 'Create a durable Goal for an outcome. Without parentGoalId it is placed against your open Goals: if one already IS this work, that Goal comes back (existing: true) and nothing new is created \u2014 continue it; if the work belongs under one, it is created there (parentGoalId in the receipt); otherwise it is a root. Pass parentGoalId yourself to put it under a specific Goal. Pass repo to anchor the work to a specific repository ("owner/repo" or repo name); delegated children inherit it. Pass title to name it in one to five words, as a person would refer to it out loud ("the night rings") \u2014 it heads every list and is spoken on a call; without one the brain writes it. Admission only: the owner must claim it before doing work, then update it as it advances. Returns an admission receipt with goalId, current state, revision, ownerParticipant, and the next step; no Goal content or execution lease.';
24705
+ CREATE_GOAL_DESCRIPTION = 'Create a durable Goal for an outcome. Without parentGoalId it is placed against your open Goals: if one already IS this work, that Goal comes back (existing: true) and nothing new is created \u2014 continue it; if the work belongs under one, it is created there (parentGoalId in the receipt); otherwise it is a root. Pass parentGoalId yourself to put it under a specific Goal. Pass repo to anchor the work to a specific repository ("owner/repo" or repo name); delegated children inherit it. Pass title to name it in one to five words, as a person would refer to it out loud ("the night rings") \u2014 it heads every list and is spoken on a call; without one the brain writes it. Admission only: claim it before doing work, then update it as it advances. Returns an admission receipt with goalId, current state, revision, ownerParticipant, and the next step; no Goal content or execution lease.';
24668
24706
  UpdateGoalSchema = external_exports.object({
24669
24707
  revision: external_exports.number().int().positive(),
24670
24708
  changes: external_exports.object({
@@ -24700,12 +24738,13 @@ var init_dist = __esm({
24700
24738
  * between two of them named. Off by default; `docs/model/goal/diagnose-design.md`. */
24701
24739
  diagnose: external_exports.boolean().optional()
24702
24740
  }).strict();
24703
- GET_GOAL_DESCRIPTION = "Read one Goal without claiming it: its outcome, state, revision, progress, blockers, the conversation on it (each question with its options and what was decided), `next`, the one step to take, and `more`, where to read further. A question in that conversation reads `open` (nothing yet), `answered` (a choice was made, and `answer` carries it), `replied` (they said something and the read settled the question on their words \u2014 NO option of yours was chosen, and the words are the reply line beside it, so read that before you act), or `closed`. The conversation carries everything the person said, every open question and your newest entry; your older entries are left out and counted \u2014 history: true reads every entry in full. Another account's Goals, and another agent's Goal that is not below one of yours, are not disclosed.\n\ndiagnose: true is for when a read has CONFUSED you \u2014 not for the working loop. It adds `diagnosis`, which asks every reader that already answers a question about your work and NAMES the reader behind every value, so you never guess which of two places to look: what state your work is really in (the stored `goals.state` beside the derived `goal_execution_state`, which can differ); whether anything is armed to ring and when (`ladder_candidates`, with the ladder's own last decision); whether a wake fired for you and what it did (durable `wake.*` events, beside when your process was last heard from); and what has reached you (`list_waiting` \u2014 review flags, unstarted work, open questions, the person's newest words). Read `diagnosis.disagreements` FIRST: each one is two readers giving different values for the same fact, with both values and both sources, and it never chooses between them \u2014 that is yours to do, from the Goal's own history. `diagnosis.looked` names every reader asked, including any that could not answer, so an empty answer is never confused with a broken one.";
24704
- UPDATE_GOAL_DESCRIPTION = `Update an owned Goal at an exact revision. State, ownership, dependencies, children, progress, title, and review acknowledgement are explicit; stale revisions are rejected. A CONTACT ON THIS GOAL MOVES ITS REVISION: a question filed on a Goal is a change to it, so an update prepared before a contact and sent after it is refused as stale (409 goal_revision_conflict) \u2014 re-read the Goal, then write. title is the work's name in one to five words, as a person would refer to it out loud (it is spoken on a call and heads every list); null clears it. reviewed: true acknowledges new evidence and closes the Deliveries addressed to you on that Goal, never over an open decision. dueAt (an ISO instant, or null) makes the Goal wait until then; when it passes you are woken for it \u2014 use it for a promise to follow up later. withdraw: [questionId] takes back a question YOU asked on this Goal that is still open \u2014 because you acted on it yourself, it no longer matters, or you asked it wrongly (e.g. waiting: hard when nothing was blocked): it is cancelled, not answered, its card closes and it stops ringing; the id is the one the conversation shows. state: done means the work was accomplished, and it can be reopened: when the person says it is not done ("it's not working"), set state: active on that same Goal instead of starting a new one; its parent reopens with it. state: done while children are still open records your part as done: the Goal waits and closes by itself when its last open child closes. cancelled is final. Returns the Goal as get_goal reads it, at its new revision.`;
24705
- CLAIM_GOAL_DESCRIPTION = "Claim the oldest runnable or review-pending Goal you own, or pass goalId to claim that Goal. Another agent's Goal that has gone quiet for 3 days (check_replies lists them as stalledOthers) is taken over when you claim it, and becomes yours to finish or cancel. Returns the Goal as get_goal reads it, and creates or renews the execution lease.";
24741
+ GET_GOAL_DESCRIPTION = "Read one Goal without claiming it, including others (the ten most recent other contributors, with names, latest entry headlines and times): its outcome, state, revision, progress, blockers, the conversation on it (each question with its options and what was decided), `next`, the one step to take, and `more`, where to read further. A question in that conversation reads `open` (nothing yet), `answered` (a choice was made, and `answer` carries it), `replied` (they said something and the read settled the question on their words \u2014 NO option of yours was chosen, and the words are the reply line beside it, so read that before you act), or `closed`. The conversation carries everything the person said, every open question and your newest entry; your older entries are left out and counted \u2014 history: true reads every entry in full. Every Goal of your person is readable, whichever of their agents owns it; another account's Goals are not disclosed.\n\ndiagnose: true is for when a read has CONFUSED you \u2014 not for the working loop. It adds `diagnosis`, which asks every reader that already answers a question about your work and NAMES the reader behind every value, so you never guess which of two places to look: what state your work is really in (the stored `goals.state` beside the derived `goal_execution_state`, which can differ); whether anything is armed to ring and when (`ladder_candidates`, with the ladder's own last decision); whether a wake fired for you and what it did (durable `wake.*` events, beside when your process was last heard from); and what has reached you (`list_waiting` \u2014 review flags, unstarted work, open questions, the person's newest words). Read `diagnosis.disagreements` FIRST: each one is two readers giving different values for the same fact, with both values and both sources, and it never chooses between them \u2014 that is yours to do, from the Goal's own history. `diagnosis.looked` names every reader asked, including any that could not answer, so an empty answer is never confused with a broken one.";
24742
+ UPDATE_GOAL_DESCRIPTION = `Update a Goal you are on at an exact revision. You are on a Goal you own, or one you have written on (an update with progress, or a contact on it); any of your person's agents may write on any of their Goals, and one that never touched a Goal is refused (409 goal_not_joined). State, ownership, dependencies, children, progress, title, and review acknowledgement are explicit; stale revisions are rejected. A CONTACT ON THIS GOAL MOVES ITS REVISION: a question filed on a Goal is a change to it, so an update prepared before a contact and sent after it is refused as stale (409 goal_revision_conflict) \u2014 re-read the Goal, then write. title is the work's name in one to five words, as a person would refer to it out loud (it is spoken on a call and heads every list); null clears it. reviewed: true acknowledges new evidence and closes the Deliveries addressed to you on that Goal, never over an open decision. dueAt (an ISO instant, or null) makes the Goal wait until then; when it passes you are woken for it \u2014 use it for a promise to follow up later. withdraw: [questionId] takes back a question YOU asked on this Goal that is still open \u2014 because you acted on it yourself, it no longer matters, or you asked it wrongly (e.g. waiting: hard when nothing was blocked): it is cancelled, not answered, its card closes and it stops ringing; the id is the one the conversation shows. state: done means the work was accomplished, and it can be reopened: when the person says it is not done ("it's not working"), set state: active on that same Goal instead of starting a new one; its parent reopens with it. state: done while children are still open records your part as done: the Goal waits and closes by itself when its last open child closes. cancelled is final. Returns the Goal as get_goal reads it, at its new revision.`;
24743
+ CLAIM_GOAL_DESCRIPTION = "Claim a pending answer to your question or the oldest runnable or review-pending Goal you own. Pass goalId to join any Goal of your person; its assignment stays unchanged. Read others before overlapping another agent\u2019s work. Joining lets you contribute and change its state; use update_goal with ownerParticipant when the assignment itself should change. Returns the Goal as get_goal reads it, and marks you as on it, which never shuts another agent out: other agents of your person may write on it and change it too, and two changes at once are told apart by revision (409 goal_revision_conflict).";
24706
24744
  CHECK_REPLIES_DESCRIPTION = "What is waiting for you: your open Deliveries (a request the user started toward you, a handoff), one row each with its Goals, how many decisions are still open, and the newest words in brief; `assigned`, your Goals nobody has started yet, however they became yours (claim_goal({goalId}) starts one); and `review`, your Goals with something new on them \u2014 the user's answers and notes are Entries on the Goal, not Deliveries. A pure read with no arguments: nothing is consumed, acknowledged or claimed by reading it, so call it on startup, after a long wait, or whenever you want to know what is outstanding. To act on one, claim its Goal (claim_goal) or reread a Delivery in full with contact({deliveryId}). Once you have acted on what arrived, update_goal with reviewed: true clears the Goal from `review` and closes the Deliveries addressed to you on it.";
24707
24745
  CheckRepliesSchema = external_exports.object({}).strict();
24708
24746
  AGENT_TOOLS = [
24747
+ { name: "who_is_working", description: "Read your person's agents that contributed in the last 24 hours, newest first: at most 30 agents and their five most recently touched Goals, with their latest entry headline and time. Use get_goal to read a Goal and its other contributors before starting overlapping work. Read-only; no arguments.", inputSchema: mcpInputSchema(CheckRepliesSchema) },
24709
24748
  { name: "contact", description: CONTACT_DESCRIPTION, inputSchema: CONTACT_SCHEMA },
24710
24749
  { name: "check_replies", description: CHECK_REPLIES_DESCRIPTION, inputSchema: mcpInputSchema(CheckRepliesSchema) },
24711
24750
  { name: "create_goal", description: CREATE_GOAL_DESCRIPTION, inputSchema: mcpInputSchema(CreateGoalToolSchema) },
@@ -24714,8 +24753,158 @@ var init_dist = __esm({
24714
24753
  { name: "update_goal", description: UPDATE_GOAL_DESCRIPTION, inputSchema: mcpInputSchema(UpdateGoalToolSchema) }
24715
24754
  ];
24716
24755
  AGENT_TOOL_NAMES = AGENT_TOOLS.map((t) => t.name);
24756
+ id = external_exports.string().uuid();
24757
+ key = external_exports.string().min(1).max(40);
24758
+ participant = external_exports.string().regex(/^(human|agent):.+$/, "a participant ID such as agent:<uuid>");
24759
+ SourceSchema = external_exports.object({
24760
+ entryId: id,
24761
+ span: external_exports.object({ start: external_exports.number().int().min(0), end: external_exports.number().int().min(1) }).strict().refine((s) => s.end > s.start, "a span ends after it starts").optional()
24762
+ }).strict();
24763
+ ResultRefSchema = external_exports.union([external_exports.object({ id }).strict(), external_exports.object({ local: key }).strict()]);
24764
+ NodeRefSchema = external_exports.object({ type: external_exports.enum(["goal", "question"]), id }).strict();
24765
+ DependencySchema = external_exports.object({
24766
+ blocker: NodeRefSchema,
24767
+ blocked: NodeRefSchema,
24768
+ action: external_exports.enum(["start", "complete", "answer"]),
24769
+ reason: external_exports.string().max(500).optional()
24770
+ }).strict();
24771
+ goalState = external_exports.enum(["open", "completed", "canceled"]);
24772
+ existingGoalChanges = [
24773
+ external_exports.object({ kind: external_exports.literal("edit"), goalId: id, title: external_exports.string().min(1).max(120).optional(), outcome: external_exports.string().min(1).optional() }).strict().refine((c) => c.title !== void 0 || c.outcome !== void 0, "an edit changes the title or the outcome"),
24774
+ external_exports.object({ kind: external_exports.literal("state"), goalId: id, state: goalState }).strict(),
24775
+ external_exports.object({ kind: external_exports.literal("assign"), goalId: id, ownerId: participant }).strict(),
24776
+ external_exports.object({ kind: external_exports.literal("defer"), goalId: id, until: external_exports.string().datetime().nullable() }).strict(),
24777
+ external_exports.object({ kind: external_exports.literal("move"), goalId: id, parentGoalId: id.nullable() }).strict(),
24778
+ external_exports.object({
24779
+ kind: external_exports.literal("dependency"),
24780
+ change: external_exports.enum(["add", "remove"]),
24781
+ goalId: id,
24782
+ dependsOnGoalId: id,
24783
+ action: external_exports.enum(["start", "complete"]),
24784
+ reason: external_exports.string().max(500).optional()
24785
+ }).strict()
24786
+ ];
24787
+ GoalChangeSchema = external_exports.union([
24788
+ external_exports.object({
24789
+ kind: external_exports.literal("create"),
24790
+ title: external_exports.string().min(1).max(120),
24791
+ outcome: external_exports.string().min(1),
24792
+ ownerId: participant,
24793
+ parentGoalId: id.optional(),
24794
+ sourceEntryIds: external_exports.array(id)
24795
+ }).strict(),
24796
+ ...existingGoalChanges
24797
+ ]);
24798
+ BrainGoalChangeSchema = external_exports.union([
24799
+ // newSession: Paigy starts a session to own it (owner, 2026-10-06); until it has, the person owns it.
24800
+ external_exports.object({
24801
+ kind: external_exports.literal("create"),
24802
+ outcome: external_exports.string().min(1),
24803
+ title: external_exports.string().min(1).max(120),
24804
+ ownerId: participant,
24805
+ parentGoal: ResultRefSchema.nullable(),
24806
+ newSession: external_exports.literal(true).optional()
24807
+ }).strict(),
24808
+ ...existingGoalChanges
24809
+ ]);
24810
+ option = external_exports.object({ id: external_exports.string().min(1).max(40), label: external_exports.string().min(1), hint: external_exports.string().optional() }).strict();
24811
+ QuestionChangeSchema = external_exports.union([
24812
+ external_exports.object({
24813
+ kind: external_exports.literal("create"),
24814
+ text: external_exports.string().min(1),
24815
+ answererId: participant,
24816
+ goal: ResultRefSchema.optional(),
24817
+ blocks: external_exports.array(external_exports.object({ question: ResultRefSchema }).strict()),
24818
+ options: external_exports.array(option).min(2).optional(),
24819
+ pickMode: external_exports.enum(["one", "many", "rank"]).optional()
24820
+ }).strict().refine((c) => c.options === void 0 === (c.pickMode === void 0), "options and pickMode come together"),
24821
+ external_exports.object({ kind: external_exports.literal("edit"), questionId: id, text: external_exports.string().min(1) }).strict(),
24822
+ external_exports.object({ kind: external_exports.literal("assign"), questionId: id, answererId: participant }).strict(),
24823
+ external_exports.object({ kind: external_exports.literal("withdraw"), questionId: id }).strict(),
24824
+ external_exports.object({ kind: external_exports.literal("dependency"), change: external_exports.enum(["add", "remove"]), edge: DependencySchema }).strict()
24825
+ ]);
24826
+ lessonScope = external_exports.union([
24827
+ external_exports.object({ kind: external_exports.literal("user") }).strict(),
24828
+ external_exports.object({ kind: external_exports.literal("goal"), goal: ResultRefSchema }).strict()
24829
+ ]);
24830
+ LessonChangeSchema = external_exports.union([
24831
+ external_exports.object({ kind: external_exports.literal("remember"), text: external_exports.string().min(1), scope: lessonScope }).strict(),
24832
+ external_exports.object({ kind: external_exports.literal("revise"), lessonId: id, text: external_exports.string().min(1), scope: lessonScope }).strict(),
24833
+ external_exports.object({ kind: external_exports.literal("withdraw"), lessonId: id }).strict()
24834
+ ]);
24835
+ BrainNextSchema = external_exports.object({
24836
+ instructions: external_exports.array(external_exports.object({ entryKeys: external_exports.array(key).min(1) }).strict()),
24837
+ say: external_exports.array(key),
24838
+ then: external_exports.enum(["listen", "hold", "end", "none"]),
24839
+ waitFor: external_exports.array(ResultRefSchema),
24840
+ reason: external_exports.string()
24841
+ }).strict();
24842
+ messageBase = {
24843
+ key,
24844
+ text: external_exports.string().min(1),
24845
+ goals: external_exports.array(ResultRefSchema),
24846
+ questions: external_exports.array(ResultRefSchema),
24847
+ entryKeys: external_exports.array(key),
24848
+ obligationIds: external_exports.array(id)
24849
+ };
24850
+ BrainMessageSchema = external_exports.union([
24851
+ external_exports.object({ ...messageBase, to: external_exports.object({ kind: external_exports.literal("user") }).strict() }).strict(),
24852
+ external_exports.object({
24853
+ ...messageBase,
24854
+ to: external_exports.object({ kind: external_exports.literal("session"), sessionId: id }).strict(),
24855
+ call: external_exports.object({ callId: id, listen: external_exports.literal(true) }).strict().optional()
24856
+ }).strict()
24857
+ ]);
24858
+ BrainSearchSchema = external_exports.object({
24859
+ query: external_exports.string().min(1).max(500),
24860
+ within: external_exports.array(external_exports.enum(["entries", "goals", "answers"])).min(1),
24861
+ goalId: id.optional()
24862
+ }).strict();
24863
+ BrainResultSchema = external_exports.object({
24864
+ messages: external_exports.array(BrainMessageSchema),
24865
+ entries: external_exports.array(external_exports.object({ key, sources: external_exports.array(SourceSchema).min(1), goals: external_exports.array(ResultRefSchema) }).strict()),
24866
+ questions: external_exports.array(external_exports.object({ key, entryKeys: external_exports.array(key), change: QuestionChangeSchema }).strict()),
24867
+ answers: external_exports.array(external_exports.object({
24868
+ question: ResultRefSchema,
24869
+ entryKeys: external_exports.array(key).min(1),
24870
+ summary: external_exports.string().min(1),
24871
+ selectedOptionIds: external_exports.array(external_exports.string().min(1)).optional()
24872
+ }).strict()),
24873
+ goals: external_exports.array(external_exports.object({ key, entryKeys: external_exports.array(key), change: BrainGoalChangeSchema }).strict()),
24874
+ feedback: external_exports.array(external_exports.object({ entryKeys: external_exports.array(key).min(1) }).strict()),
24875
+ lessons: external_exports.array(external_exports.object({ entryKeys: external_exports.array(key).min(1), change: LessonChangeSchema }).strict()),
24876
+ next: BrainNextSchema,
24877
+ search: BrainSearchSchema.optional()
24878
+ }).strict();
24879
+ str = external_exports.string();
24880
+ strs = external_exports.array(external_exports.string());
24881
+ CompactResultSchema = external_exports.object({
24882
+ next: external_exports.object({ say: strs, then: external_exports.enum(["listen", "hold", "end", "none"]), waitFor: strs, reason: str, instructions: strs }).strict(),
24883
+ messages: external_exports.array(external_exports.object({ key: str, to: str, text: str, about: strs, entries: strs, owed: strs, inviteToCall: external_exports.boolean() }).strict()),
24884
+ entries: external_exports.array(external_exports.object({ key: str, from: str, start: external_exports.number().int(), end: external_exports.number().int(), on: strs }).strict()),
24885
+ answers: external_exports.array(external_exports.object({ question: str, entries: strs, summary: str, picked: strs }).strict()),
24886
+ changes: external_exports.array(external_exports.object({
24887
+ key: str,
24888
+ what: external_exports.enum(["goal", "question", "lesson"]),
24889
+ op: external_exports.enum(["create", "edit", "assign", "open", "complete", "cancel", "defer", "move", "block", "unblock", "withdraw", "remember", "revise"]),
24890
+ id: str,
24891
+ text: str,
24892
+ title: str,
24893
+ who: str,
24894
+ under: str,
24895
+ gate: external_exports.enum(["start", "complete", "answer", "none"]),
24896
+ options: external_exports.array(external_exports.object({ id: str, label: str }).strict()),
24897
+ pick: external_exports.enum(["one", "many", "rank", "words"]),
24898
+ entries: strs
24899
+ }).strict()),
24900
+ feedback: external_exports.array(strs),
24901
+ search: external_exports.object({ query: str, within: strs, goal: str }).strict()
24902
+ }).strict();
24903
+ COMPACT_RESULT_JSON_SCHEMA = (({ $schema: _, ...rest }) => rest)(
24904
+ zodToJsonSchema(CompactResultSchema, { $refStrategy: "none" })
24905
+ );
24717
24906
  LIVE_MS = 3 * 6e4;
24718
- WORKING_MS = 30 * 6e4;
24907
+ WORKING_MS = 60 * 6e4;
24719
24908
  ContextSchema = external_exports.object({
24720
24909
  title: external_exports.string().min(1).describe("One-line headline of what you need (required, non-empty)."),
24721
24910
  description: external_exports.array(external_exports.string().min(1)).describe(
@@ -24933,7 +25122,7 @@ var init_dist = __esm({
24933
25122
  * (`parseDelay`, #1292), and a value here simply wins over that reading. */
24934
25123
  dueInSeconds: external_exports.number().int().positive().optional(),
24935
25124
  /** Feedback only (#812): WHICH failure the complaint names — typed by the mapper that
24936
- * already read the utterance, so `feedback_from_call.kind` stops defaulting to
25125
+ * already read the utterance, so `signals.kind` stops defaulting to
24937
25126
  * 'other' on every row. A table that records that something was wrong and nothing
24938
25127
  * about what cannot answer "is the bot looping less this week?". */
24939
25128
  fault: external_exports.enum(["loop", "unanswered", "overridden", "misheard", "slow", "other"]).optional()
@@ -25067,7 +25256,13 @@ var init_dist = __esm({
25067
25256
  /** Whether the walk WAITS for an answer before moving on. Absent = derived as today
25068
25257
  * (a question blocks, context flows). blocking:false on a question = ask and move
25069
25258
  * on, the claim stays pending; blocking:true on context = hold for a reply. */
25070
- blocking: external_exports.boolean().optional()
25259
+ blocking: external_exports.boolean().optional(),
25260
+ /** SPOKEN ONLY IF THEY SAY NOTHING (owner, 2026-10-01, call 812de935: "you're gonna re-ask, but it
25261
+ * shouldn't be the same words … more like, hey, are you still there, or are you able to answer, or
25262
+ * would you need more information"). The walk holds this turn out of its queue; at the queue's end it
25263
+ * listens for the last word, and only if that listen is silent is this turn said and asked. If they
25264
+ * speak, it is dropped and their words are taken like any reply. */
25265
+ ifSilent: external_exports.boolean().optional()
25071
25266
  });
25072
25267
  CLAIM_STALE_MS = 30 * 6e4;
25073
25268
  InboxItemSchema = external_exports.object({
@@ -25211,7 +25406,18 @@ var init_dist = __esm({
25211
25406
  /** THAT GOAL'S NAME (#2416) — what Activity's row is headed by, since a row there is one Goal
25212
25407
  * and the cards it holds sit behind it. Stamped by the same read as `goalState`. */
25213
25408
  goalTitle: external_exports.string().optional()
25214
- }).optional()
25409
+ }).optional(),
25410
+ /** WHAT THIS CARD IS, IN TWELVE CHARACTERS (#3019) — the hash of every other field on it, stamped
25411
+ * by the one read that serves the open list (`apps/api/src/inbox/project.ts` `inboxFor`). It is
25412
+ * how the incremental read knows a card has not moved: the phone echoes back the revs it holds
25413
+ * (`POST /api/inbox/changes`) and is sent only the cards whose rev differs.
25414
+ *
25415
+ * THE PAYLOAD'S OWN HASH, NEVER A STAMP ON THE WORK — the same mechanism as `QueueItem.rev`
25416
+ * (#2928) and an entry's (#3018), for the same reason: a card shows facts no `updated_at` of its
25417
+ * own moves (its Goal's state and name, how cold the work behind it has gone, whether a ring is
25418
+ * live). Optional, so a fixture, the demo and the archive lens need not spell one, and a card
25419
+ * with no rev is simply always re-sent. */
25420
+ rev: external_exports.string().optional()
25215
25421
  });
25216
25422
  APNS_TOKEN_RE = /^[0-9a-fA-F]{64}$/;
25217
25423
  PushTokenSchema = external_exports.object({
@@ -25583,7 +25789,22 @@ var init_dist = __esm({
25583
25789
  * minute after the person speaks erases their instant from it, and the durable traces the client
25584
25790
  * can see (`replies`, `questions[].answeredAt`) miss a spontaneous note entirely — a `request`
25585
25791
  * Entry with no `about_id` is in neither. */
25586
- lastPersonAt: external_exports.string().nullable().optional()
25792
+ lastPersonAt: external_exports.string().nullable().optional(),
25793
+ /** WHAT THIS ROW IS, IN TWELVE CHARACTERS (#2928) — the hash of every other field on it, stamped
25794
+ * by the one projection that builds the row (`apps/api/src/goal/queue.ts`). It is how the
25795
+ * incremental read knows a row has not moved: the phone echoes back the revs it holds
25796
+ * (`POST /api/goals/changes`) and is sent only the rows whose rev differs.
25797
+ *
25798
+ * IT IS THE PAYLOAD'S OWN HASH, NEVER A STAMP ON THE WORK. Nothing here reasons about which
25799
+ * writes change which field — the comparison is over the bytes the phone is holding, so a fact
25800
+ * the row shows that no `updated_at` moves for (a lease lapsing, a dependency's state, a
25801
+ * sibling appearing in `childGoalIds`) cannot go unnoticed. Optional because a hand-built
25802
+ * queue (a fixture, the demo) spells none, and a row with no rev is simply always re-sent. */
25803
+ rev: external_exports.string().optional()
25804
+ });
25805
+ QueueDeltaSchema = external_exports.object({
25806
+ ids: external_exports.array(external_exports.string()),
25807
+ items: external_exports.array(QueueItemSchema)
25587
25808
  });
25588
25809
  COLD_AFTER_MS = 3 * 24 * 60 * 60 * 1e3;
25589
25810
  NoteSourceSchema = external_exports.enum(["app", "call"]);
@@ -25756,6 +25977,11 @@ var init_dist = __esm({
25756
25977
  /** Local host recovery must preserve the launch's runtime and Paigy identity. */
25757
25978
  harness: external_exports.enum(["claude", "codex", "agy"]).optional(),
25758
25979
  session_id: external_exports.string().uuid().optional(),
25980
+ /** A conversation the host must not resume: its context is full, so every turn fails
25981
+ * ("Prompt is too long"). Written when a run hits it (`run.ts` `onFull`); the host skips a slot
25982
+ * whose resumable session is this one, so its Goals reach the dead-agent handoff instead of a
25983
+ * copy that types the person's words into a turn that cannot run (Calls, 2026-10-06). */
25984
+ full_session: external_exports.string().optional(),
25759
25985
  uik_pub: external_exports.string().nullable().optional()
25760
25986
  });
25761
25987
  SupportRequestSchema = external_exports.object({
@@ -25935,6 +26161,7 @@ var init_dist = __esm({
25935
26161
  authToken = (explicit) => explicit ?? tokenOverride ?? readToken();
25936
26162
  AWAIT_WINDOW_MS = 45e3;
25937
26163
  NOT_SENT = "Recorded as progress, not sent: nobody was notified. If the person should see it (a result, something to try or check, a finding), contact again and say so; report progress with update_goal.";
26164
+ DEMOTED = "Delivered as a card, not a call: the person's settings do not allow a call right now (silent, quiet hours, or a mode). It has reached them; do not send it again, with or without a Goal.";
25938
26165
  HEARTBEAT_MS = 25e3;
25939
26166
  RETRY_MS = [1e3, 2e3, 5e3, 1e4, 3e4];
25940
26167
  JOIN = { config: { broadcast: { self: false } } };
@@ -26837,14 +27064,14 @@ var require_regex = __commonJS({
26837
27064
  var TEST_KANJI = new RegExp("^" + kanji + "$");
26838
27065
  var TEST_NUMERIC = new RegExp("^" + numeric + "$");
26839
27066
  var TEST_ALPHANUMERIC = new RegExp("^[A-Z0-9 $%*+\\-./:]+$");
26840
- exports.testKanji = function testKanji(str) {
26841
- return TEST_KANJI.test(str);
27067
+ exports.testKanji = function testKanji(str3) {
27068
+ return TEST_KANJI.test(str3);
26842
27069
  };
26843
- exports.testNumeric = function testNumeric(str) {
26844
- return TEST_NUMERIC.test(str);
27070
+ exports.testNumeric = function testNumeric(str3) {
27071
+ return TEST_NUMERIC.test(str3);
26845
27072
  };
26846
- exports.testAlphanumeric = function testAlphanumeric(str) {
26847
- return TEST_ALPHANUMERIC.test(str);
27073
+ exports.testAlphanumeric = function testAlphanumeric(str3) {
27074
+ return TEST_ALPHANUMERIC.test(str3);
26848
27075
  };
26849
27076
  }
26850
27077
  });
@@ -27294,11 +27521,11 @@ var require_dijkstra = __commonJS({
27294
27521
  */
27295
27522
  PriorityQueue: {
27296
27523
  make: function(opts) {
27297
- var T = dijkstra.PriorityQueue, t = {}, key;
27524
+ var T = dijkstra.PriorityQueue, t = {}, key3;
27298
27525
  opts = opts || {};
27299
- for (key in T) {
27300
- if (T.hasOwnProperty(key)) {
27301
- t[key] = T[key];
27526
+ for (key3 in T) {
27527
+ if (T.hasOwnProperty(key3)) {
27528
+ t[key3] = T[key3];
27302
27529
  }
27303
27530
  }
27304
27531
  t.queue = [];
@@ -27346,13 +27573,13 @@ var require_segments = __commonJS({
27346
27573
  var Regex = require_regex();
27347
27574
  var Utils = require_utils2();
27348
27575
  var dijkstra = require_dijkstra();
27349
- function getStringByteLength(str) {
27350
- return unescape(encodeURIComponent(str)).length;
27576
+ function getStringByteLength(str3) {
27577
+ return unescape(encodeURIComponent(str3)).length;
27351
27578
  }
27352
- function getSegments(regex, mode, str) {
27579
+ function getSegments(regex, mode, str3) {
27353
27580
  const segments = [];
27354
27581
  let result;
27355
- while ((result = regex.exec(str)) !== null) {
27582
+ while ((result = regex.exec(str3)) !== null) {
27356
27583
  segments.push({
27357
27584
  data: result[0],
27358
27585
  index: result.index,
@@ -27449,18 +27676,18 @@ var require_segments = __commonJS({
27449
27676
  const currentNodeIds = [];
27450
27677
  for (let j = 0; j < nodeGroup.length; j++) {
27451
27678
  const node = nodeGroup[j];
27452
- const key = "" + i + j;
27453
- currentNodeIds.push(key);
27454
- table[key] = { node, lastCount: 0 };
27455
- graph[key] = {};
27679
+ const key3 = "" + i + j;
27680
+ currentNodeIds.push(key3);
27681
+ table[key3] = { node, lastCount: 0 };
27682
+ graph[key3] = {};
27456
27683
  for (let n = 0; n < prevNodeIds.length; n++) {
27457
27684
  const prevNodeId = prevNodeIds[n];
27458
27685
  if (table[prevNodeId] && table[prevNodeId].node.mode === node.mode) {
27459
- graph[prevNodeId][key] = getSegmentBitsLength(table[prevNodeId].lastCount + node.length, node.mode) - getSegmentBitsLength(table[prevNodeId].lastCount, node.mode);
27686
+ graph[prevNodeId][key3] = getSegmentBitsLength(table[prevNodeId].lastCount + node.length, node.mode) - getSegmentBitsLength(table[prevNodeId].lastCount, node.mode);
27460
27687
  table[prevNodeId].lastCount += node.length;
27461
27688
  } else {
27462
27689
  if (table[prevNodeId]) table[prevNodeId].lastCount = node.length;
27463
- graph[prevNodeId][key] = getSegmentBitsLength(node.length, node.mode) + 4 + Mode.getCharCountIndicator(node.mode, version);
27690
+ graph[prevNodeId][key3] = getSegmentBitsLength(node.length, node.mode) + 4 + Mode.getCharCountIndicator(node.mode, version);
27464
27691
  }
27465
27692
  }
27466
27693
  }
@@ -30186,13 +30413,13 @@ var require_svg_tag = __commonJS({
30186
30413
  var Utils = require_utils3();
30187
30414
  function getColorAttrib(color, attrib) {
30188
30415
  const alpha = color.a / 255;
30189
- const str = attrib + '="' + color.hex + '"';
30190
- return alpha < 1 ? str + " " + attrib + '-opacity="' + alpha.toFixed(2).slice(1) + '"' : str;
30416
+ const str3 = attrib + '="' + color.hex + '"';
30417
+ return alpha < 1 ? str3 + " " + attrib + '-opacity="' + alpha.toFixed(2).slice(1) + '"' : str3;
30191
30418
  }
30192
30419
  function svgCmd(cmd, x, y) {
30193
- let str = cmd + x;
30194
- if (typeof y !== "undefined") str += " " + y;
30195
- return str;
30420
+ let str3 = cmd + x;
30421
+ if (typeof y !== "undefined") str3 += " " + y;
30422
+ return str3;
30196
30423
  }
30197
30424
  function qrToPath(data, size, margin) {
30198
30425
  let path = "";
@@ -30840,16 +31067,16 @@ function parseVerdicts(raw, knownIds, knownAgents) {
30840
31067
  const seen = /* @__PURE__ */ new Set();
30841
31068
  for (const row of rows) {
30842
31069
  const r = row;
30843
- const id = typeof r?.id === "string" ? r.id : "";
30844
- if (!id) {
31070
+ const id3 = typeof r?.id === "string" ? r.id : "";
31071
+ if (!id3) {
30845
31072
  dropped.push({ row, reason: "no id" });
30846
31073
  continue;
30847
31074
  }
30848
- if (!knownIds.has(id)) {
31075
+ if (!knownIds.has(id3)) {
30849
31076
  dropped.push({ row, reason: "id is not a note in this queue" });
30850
31077
  continue;
30851
31078
  }
30852
- if (seen.has(id)) {
31079
+ if (seen.has(id3)) {
30853
31080
  dropped.push({ row, reason: "duplicate verdict for this note" });
30854
31081
  continue;
30855
31082
  }
@@ -30864,12 +31091,12 @@ function parseVerdicts(raw, knownIds, knownAgents) {
30864
31091
  continue;
30865
31092
  }
30866
31093
  verdicts.push({
30867
- id,
31094
+ id: id3,
30868
31095
  verdict,
30869
31096
  agent: verdict === "assign" ? agent2 : null,
30870
31097
  why: typeof r?.why === "string" ? r.why.trim().slice(0, 200) : null
30871
31098
  });
30872
- seen.add(id);
31099
+ seen.add(id3);
30873
31100
  }
30874
31101
  return { ok: true, verdicts, dropped };
30875
31102
  }
@@ -31037,7 +31264,7 @@ async function runTriage(opts, deps = {}) {
31037
31264
  const acted = suggested(run);
31038
31265
  log(acted === 0 ? "Nothing to suggest \u2014 sent, so your phone shows the queue as clean." : `Sent to your phone \u2014 accept it there (${plural(acted, "suggestion")}).`);
31039
31266
  if (!opts.apply) return 0;
31040
- const accept = deps.accept ?? ((id, body) => acceptTriage(id, body));
31267
+ const accept = deps.accept ?? ((id3, body) => acceptTriage(id3, body));
31041
31268
  const groups = [
31042
31269
  { body: { group: "close" }, label: `close ${plural(run.close.length, "note")}`, count: run.close.length, preapproved: opts.yes.close },
31043
31270
  { body: { group: "stale" }, label: `close ${plural(run.stale.length, "stale note")}`, count: run.stale.length, preapproved: opts.yes.stale },
@@ -31076,9 +31303,9 @@ init_catalog();
31076
31303
 
31077
31304
  // src/cli-args.ts
31078
31305
  var TRIAGE_VIA = ["ollama", "claude", "codex", "agy"];
31079
- var USAGE = "usage: paigy-harness setup | pair | host [--grant DIR]\u2026 | service | enable-tools [--scope user|project] | hatch NAME [--voice KEY] [--slot SLOT] | handoff | triage [--via ollama|claude|codex|agy] [--json] [--apply [--yes-close] [--yes-stale] [--yes-assign]] | [--harness claude|codex|agy] [--mode bypass|ask] [--cwd DIR] [--identity NAME] [--grace SECONDS] [--doctor] PROMPT\u2026";
31306
+ var USAGE = "usage: paigy-harness setup | pair | host [--grant DIR]\u2026 | service | enable-tools [--scope user|project] | hatch NAME [--voice KEY] [--slot SLOT] | launch NAME [--under GOAL] [--voice KEY] [--harness \u2026] [--mode \u2026] [--cwd DIR] BRIEF\u2026 | handoff | triage [--via ollama|claude|codex|agy] [--json] [--apply [--yes-close] [--yes-stale] [--yes-assign]] | [--harness claude|codex|agy] [--mode bypass|ask] [--cwd DIR] [--grace SECONDS] [--doctor] PROMPT\u2026";
31080
31307
  function parseArgs(argv) {
31081
- const args = { harness: "claude", mode: "bypass", cwd: process.cwd(), doctor: false, help: false, host: false, pair: false, service: false, setup: false, enableTools: false, scope: "user", grant: [], hatch: null, voice: null, slot: null, identity: null, graceSeconds: 90, prompt: "", handoff: false, triage: false, via: null, json: false, apply: false, yesClose: false, yesStale: false, yesAssign: false };
31308
+ const args = { harness: "claude", mode: "bypass", cwd: process.cwd(), doctor: false, help: false, host: false, pair: false, service: false, setup: false, enableTools: false, scope: "user", grant: [], hatch: null, voice: null, slot: null, launch: null, under: null, graceSeconds: 90, prompt: "", handoff: false, triage: false, via: null, json: false, apply: false, yesClose: false, yesStale: false, yesAssign: false };
31082
31309
  const words2 = [];
31083
31310
  for (let i = 0; i < argv.length; i++) {
31084
31311
  const arg = argv[i];
@@ -31149,9 +31376,13 @@ function parseArgs(argv) {
31149
31376
  } else if (arg === "--slot") {
31150
31377
  args.slot = next() ?? null;
31151
31378
  } else if (arg === "--identity") {
31379
+ return { error: '--identity is gone: start a helper with `paigy-harness launch NAME "brief"`, which gives it its own session' };
31380
+ } else if (arg === "launch") {
31152
31381
  const v = next();
31153
- if (!v) return { error: "--identity needs a hatched agent's name" };
31154
- args.identity = v;
31382
+ if (!v) return { error: 'launch needs a name: paigy-harness launch "Deploy check" "brief"' };
31383
+ args.launch = v;
31384
+ } else if (arg === "--under") {
31385
+ args.under = next() ?? null;
31155
31386
  } else if (arg?.startsWith("--")) {
31156
31387
  return { error: `unknown flag ${arg}` };
31157
31388
  } else if (arg) {
@@ -31160,6 +31391,7 @@ function parseArgs(argv) {
31160
31391
  }
31161
31392
  args.prompt = words2.join(" ");
31162
31393
  if (args.help) return args;
31394
+ if (args.launch && !args.prompt) return { error: 'launch needs a brief: paigy-harness launch "Deploy check" "brief"' };
31163
31395
  if (!args.doctor && !args.handoff && !args.hatch && !args.host && !args.pair && !args.service && !args.setup && !args.enableTools && !args.triage && !args.prompt) return { error: "a prompt is required (or setup / --doctor / pair / host / service / enable-tools / hatch NAME / handoff / triage)" };
31164
31396
  if ((args.yesClose || args.yesStale || args.yesAssign) && !args.apply)
31165
31397
  return { error: "--yes-close/--yes-stale/--yes-assign only apply with --apply" };
@@ -31192,20 +31424,23 @@ function onEnter(input, onLine) {
31192
31424
  // src/cli.ts
31193
31425
  init_dist();
31194
31426
  var import_qrcode = __toESM(require_lib(), 1);
31427
+ import { randomUUID as randomUUID7 } from "crypto";
31195
31428
  import { hostname } from "os";
31196
- import { existsSync as existsSync5, mkdirSync as mkdirSync4, readFileSync as readFileSync6, writeFileSync as writeFileSync5 } from "fs";
31429
+ import { existsSync as existsSync5, mkdirSync as mkdirSync4, readFileSync as readFileSync7, writeFileSync as writeFileSync5 } from "fs";
31197
31430
  import { execFile as execFile2, execSync } from "child_process";
31198
31431
  import { homedir as homedir10 } from "os";
31199
- import { join as join10 } from "path";
31432
+ import { join as join11 } from "path";
31200
31433
 
31201
31434
  // src/run.ts
31202
31435
  init_dist();
31436
+ import { randomUUID as randomUUID6 } from "crypto";
31203
31437
 
31204
31438
  // src/harness/session.ts
31439
+ init_dist();
31205
31440
  import { spawn } from "child_process";
31206
- import { existsSync as existsSync3 } from "fs";
31441
+ import { existsSync as existsSync3, readFileSync as readFileSync3 } from "fs";
31207
31442
  import { homedir as homedir4 } from "os";
31208
- import { resolve, delimiter as delimiter2 } from "path";
31443
+ import { resolve, delimiter as delimiter2, join as join5 } from "path";
31209
31444
 
31210
31445
  // src/harness/acp.ts
31211
31446
  var none = { events: [], writes: [] };
@@ -31278,10 +31513,10 @@ var AcpDriver = class {
31278
31513
  return this.flush();
31279
31514
  }
31280
31515
  /** Answer a PermissionEvent (ask mode). The id is the request's JSON-RPC id as a string. */
31281
- respond(id, decision) {
31282
- const request = this.pending.get(id);
31516
+ respond(id3, decision) {
31517
+ const request = this.pending.get(id3);
31283
31518
  if (!request) return [];
31284
- this.pending.delete(id);
31519
+ this.pending.delete(id3);
31285
31520
  const optionId = optionFor(request.options, decision);
31286
31521
  return [
31287
31522
  optionId ? frame2({ id: request.id, result: { outcome: { outcome: "selected", optionId } } }) : frame2({ id: request.id, result: { outcome: { outcome: "cancelled" } } })
@@ -31435,7 +31670,7 @@ var AcpDriver = class {
31435
31670
  writes: [frame2({ id: msg.id, error: { code: -32601, message: `Method not found: ${msg.method}` } })]
31436
31671
  };
31437
31672
  }
31438
- const id = msg.id;
31673
+ const id3 = msg.id;
31439
31674
  const options = msg.params?.options ?? [];
31440
31675
  const title = msg.params?.toolCall?.title?.trim() || "a tool call";
31441
31676
  const tool = msg.params?.toolCall?.kind ?? "tool";
@@ -31446,21 +31681,21 @@ var AcpDriver = class {
31446
31681
  // means "don't stall the agent", never "don't tell the user".
31447
31682
  events: [{ kind: "turn", role: "agent", text: `auto-approved: ${title}`, tools: [tool] }],
31448
31683
  writes: [
31449
- optionId ? frame2({ id, result: { outcome: { outcome: "selected", optionId } } }) : frame2({ id, result: { outcome: { outcome: "cancelled" } } })
31684
+ optionId ? frame2({ id: id3, result: { outcome: { outcome: "selected", optionId } } }) : frame2({ id: id3, result: { outcome: { outcome: "cancelled" } } })
31450
31685
  ]
31451
31686
  };
31452
31687
  }
31453
- this.pending.set(String(id), { id, options });
31688
+ this.pending.set(String(id3), { id: id3, options });
31454
31689
  return {
31455
- events: [{ kind: "permission", id: String(id), tool, summary: title }],
31690
+ events: [{ kind: "permission", id: String(id3), tool, summary: title }],
31456
31691
  writes: []
31457
31692
  };
31458
31693
  }
31459
31694
  /** The frame that opens the conversation: a resume of `resume` while there is one to try,
31460
31695
  * else a new session. */
31461
- opening(id) {
31696
+ opening(id3) {
31462
31697
  const params = { cwd: this.cwd, mcpServers: [], ...this.meta ? { _meta: this.meta } : {} };
31463
- return this.resume ? { id, method: "session/resume", params: { sessionId: this.resume, ...params } } : { id, method: "session/new", params };
31698
+ return this.resume ? { id: id3, method: "session/resume", params: { sessionId: this.resume, ...params } } : { id: id3, method: "session/new", params };
31464
31699
  }
31465
31700
  /** Send the queued prompts as one turn, if the agent can take one right now. */
31466
31701
  flush() {
@@ -31579,6 +31814,21 @@ function startSession(opts) {
31579
31814
  if (!existsSync3(cwd)) {
31580
31815
  queueMicrotask(() => opts.onEvent({ kind: "error", message: `workspace does not exist: ${cwd}` }));
31581
31816
  }
31817
+ const codexConfig = opts.harness === "codex" ? JSON.parse(process.env.CODEX_CONFIG || "{}") : null;
31818
+ if (codexConfig) {
31819
+ const key3 = "mcp_servers.paigy.env_vars";
31820
+ const configPath = join5(process.env.CODEX_HOME || join5(homedir4(), ".codex"), "config.toml");
31821
+ const saved = existsSync3(configPath) ? readFileSync3(configPath, "utf8") : "";
31822
+ const registered = /\[mcp_servers\.paigy\][\s\S]*?(?=\n\[|$)/.exec(saved)?.[0];
31823
+ const configured = codexConfig["mcp_servers.paigy.command"] || codexConfig["mcp_servers.paigy.url"] || codexConfig.mcp_servers?.paigy?.command || codexConfig.mcp_servers?.paigy?.url;
31824
+ if (!configured && !registered) {
31825
+ codexConfig["mcp_servers.paigy.command"] = "npx";
31826
+ codexConfig["mcp_servers.paigy.args"] = ["-y", "@paigy/mcp@latest"];
31827
+ }
31828
+ const savedVars = registered?.match(/env_vars\s*=\s*\[([\s\S]*?)\]/)?.[1] ?? "";
31829
+ const inherited = [...savedVars.matchAll(/["']([A-Za-z_][A-Za-z0-9_]*)["']/g)].map((match) => match[1]);
31830
+ codexConfig[key3] = [.../* @__PURE__ */ new Set([...inherited, ...codexConfig[key3] ?? codexConfig.mcp_servers?.paigy?.env_vars ?? [], ...CODEX_ENV])];
31831
+ }
31582
31832
  const child = (opts.spawnFn ?? spawn)(opts.bin ?? ADAPTER_BIN[opts.harness], [], {
31583
31833
  cwd,
31584
31834
  // The adapter shells out to its vendor CLI (`claude`, `codex`), and a GUI- or
@@ -31589,7 +31839,9 @@ function startSession(opts) {
31589
31839
  ...process.env,
31590
31840
  PATH: [process.env.PATH, ...probeDirs()].filter(Boolean).join(delimiter2),
31591
31841
  ...opts.token ? { PAIGY_TOKEN: opts.token } : {},
31592
- ...opts.resume ?? opts.session ? { PAIGY_SESSION_ID: opts.resume ?? opts.session } : {},
31842
+ ...opts.instance ? { PAIGY_INSTANCE_ID: opts.instance } : {},
31843
+ ...codexConfig ? { CODEX_CONFIG: JSON.stringify(codexConfig) } : {},
31844
+ ...opts.session ?? opts.resume ? { PAIGY_SESSION_ID: opts.session ?? opts.resume } : {},
31593
31845
  // A PUMP DRIVES THIS PROCESS (2026-09-22, #2265): every run `runHarness` starts has the
31594
31846
  // bridge's pump typing answers in, so nothing inside it may start a second delivery path.
31595
31847
  // Exported on EVERY spawn — `PAIGY_SESSION_ID` above is the conversation to resume, and a
@@ -31651,8 +31903,8 @@ function startSession(opts) {
31651
31903
  send(text) {
31652
31904
  write(driver.send(text));
31653
31905
  },
31654
- respond(id, decision) {
31655
- write(driver.respond(id, decision));
31906
+ respond(id3, decision) {
31907
+ write(driver.respond(id3, decision));
31656
31908
  },
31657
31909
  stop() {
31658
31910
  write(driver.close());
@@ -31724,19 +31976,19 @@ var getRefs2 = (options) => {
31724
31976
  };
31725
31977
 
31726
31978
  // ../../node_modules/.pnpm/zod-to-json-schema@3.25.2_zod@3.25.76/node_modules/zod-to-json-schema/dist/esm/errorMessages.js
31727
- function addErrorMessage2(res, key, errorMessage, refs) {
31979
+ function addErrorMessage2(res, key3, errorMessage, refs) {
31728
31980
  if (!refs?.errorMessages)
31729
31981
  return;
31730
31982
  if (errorMessage) {
31731
31983
  res.errorMessage = {
31732
31984
  ...res.errorMessage,
31733
- [key]: errorMessage
31985
+ [key3]: errorMessage
31734
31986
  };
31735
31987
  }
31736
31988
  }
31737
- function setResponseValueAndErrors2(res, key, value, errorMessage, refs) {
31738
- res[key] = value;
31739
- addErrorMessage2(res, key, errorMessage, refs);
31989
+ function setResponseValueAndErrors2(res, key3, value, errorMessage, refs) {
31990
+ res[key3] = value;
31991
+ addErrorMessage2(res, key3, errorMessage, refs);
31740
31992
  }
31741
31993
 
31742
31994
  // ../../node_modules/.pnpm/zod-to-json-schema@3.25.2_zod@3.25.76/node_modules/zod-to-json-schema/dist/esm/getRelativePath.js
@@ -32335,11 +32587,11 @@ function parseRecordDef2(def, refs) {
32335
32587
  return {
32336
32588
  type: "object",
32337
32589
  required: def.keyType._def.values,
32338
- properties: def.keyType._def.values.reduce((acc, key) => ({
32590
+ properties: def.keyType._def.values.reduce((acc, key3) => ({
32339
32591
  ...acc,
32340
- [key]: parseDef2(def.valueType._def, {
32592
+ [key3]: parseDef2(def.valueType._def, {
32341
32593
  ...refs,
32342
- currentPath: [...refs.currentPath, "properties", key]
32594
+ currentPath: [...refs.currentPath, "properties", key3]
32343
32595
  }) ?? parseAnyDef2(refs)
32344
32596
  }), {}),
32345
32597
  additionalProperties: refs.rejectedAdditionalProperties
@@ -32406,10 +32658,10 @@ function parseMapDef2(def, refs) {
32406
32658
  // ../../node_modules/.pnpm/zod-to-json-schema@3.25.2_zod@3.25.76/node_modules/zod-to-json-schema/dist/esm/parsers/nativeEnum.js
32407
32659
  function parseNativeEnumDef2(def) {
32408
32660
  const object = def.values;
32409
- const actualKeys = Object.keys(def.values).filter((key) => {
32410
- return typeof object[object[key]] !== "number";
32661
+ const actualKeys = Object.keys(def.values).filter((key3) => {
32662
+ return typeof object[object[key3]] !== "number";
32411
32663
  });
32412
- const actualValues = actualKeys.map((key) => object[key]);
32664
+ const actualValues = actualKeys.map((key3) => object[key3]);
32413
32665
  const parsedTypes = Array.from(new Set(actualValues.map((values) => typeof values)));
32414
32666
  return {
32415
32667
  type: parsedTypes.length === 1 ? parsedTypes[0] === "string" ? "string" : "number" : ["string", "number"],
@@ -32961,6 +33213,7 @@ var zodToJsonSchema2 = (schema, options) => {
32961
33213
 
32962
33214
  // ../../packages/schema/dist/index.js
32963
33215
  init_zod();
33216
+ init_zod();
32964
33217
  var OPTIONS_MIN2 = 2;
32965
33218
  var OPTIONS_MAX2 = 6;
32966
33219
  var OptionSchema2 = external_exports.object({
@@ -33011,34 +33264,31 @@ function mcpInputSchema2(s) {
33011
33264
  }
33012
33265
  var AskInputSchema2 = external_exports.object({
33013
33266
  id: external_exports.string().optional().describe("Optional idempotency key or client-side ID for this specific ask."),
33014
- parentId: external_exports.string().uuid().optional().describe("The Goal this question is about \u2014 usually the one you are working on. The question goes onto that Goal and its answer comes back there. Omit it and Paigy places the question in the tree itself."),
33267
+ parentId: external_exports.string().uuid().optional().describe("The Goal this question is about \u2014 usually the one you are working on. The question goes onto that Goal and its answer comes back there. Omit it and the question starts a new Goal of yours."),
33015
33268
  repo: external_exports.string().optional().describe("Optional repository context."),
33016
33269
  ask: external_exports.string().trim().min(1).max(1e4).describe(
33017
- "ONE question, and only what is needed to answer it. Several questions are several asks in the array, one each: an answer settles the one ask it was given in the shape that ask declares, so a person who answers the part of a bundled ask that interested them settles nothing and is asked again. Paigy reads every ask once and takes a bundled one apart into its own cards anyway \u2014 each question a Question on the one Goal the ask lands on, never a Goal of its own \u2014 but the words it splits are its reading, not yours. News, progress and findings are their own contact; ANY contact for a person already on a call JOINS that call, whatever channel you asked for, so several arrive as one call."
33270
+ "ONE question, and only what is needed to answer it. Several questions are several asks in the array, one each: an answer settles the one ask it was given in the shape that ask declares, so a person who answers the part of a bundled ask that interested them settles nothing and is asked again. Paigy sends each ask exactly as you wrote it: a bundled ask arrives as one card. News, progress and findings are their own contact; ANY contact for a person already on a call JOINS that call, whatever channel you asked for, so several arrive as one call."
33018
33271
  ),
33019
33272
  options: external_exports.array(OptionInputSchema2).min(1).max(6).optional(),
33020
- // A CHECKLIST WHEN THE CHOICES ARE INDEPENDENT (owner, 2026-10-02 01:44 UTC: "bring back the
33021
- // checklist mode of answering"). The answer shape was taken off this surface with the wire form
33022
- // (#575) on the promise that Paigy would derive it, and the Goal-scoped contact that replaced it
33023
- // only ever sends pick-one or words (`goal/intake.ts` `answerOf`): three independent fixes went out
33024
- // as "All three / 1 and 3 only / Just log it", which the person could not read without the text and
33025
- // could not answer as the ticks he wanted. "many" is the one shape an agent knows and the read does
33026
- // not: whether its own options exclude each other.
33273
+ // HOW THE OPTIONS ARE ANSWERED, SAID BY THE AGENT (owner, 2026-10-02: "one and many makes sense";
33274
+ // brain_prompts.md §1: structured agent questions need no model). Every card was pick-one while no
33275
+ // agent sent this; no read reshapes cards any more, so this is the card's shape, and the
33276
+ // description says so plainly.
33027
33277
  select: external_exports.enum(["one", "many"]).optional().describe(
33028
- 'How the options are answered: "one" (default) to pick one, "many" to tick any number of them. Use "many" when the options are independent things they may want several of \u2014 never combinations of them like "all three" or "1 and 3". Ignored without options.'
33278
+ 'How the options are answered: "many" makes a checklist (they may want several, e.g. independent fixes), "one" (the default) a pick (choosing one rules out the others). Send "many" whenever more than one option could be wanted at once. The person can always answer in their own words as well. Ignored without options.'
33029
33279
  ),
33030
33280
  answers: external_exports.string().trim().regex(/^[0-9a-fA-F-]{8,36}$/).optional().describe(
33031
33281
  "Your reply answers a question the person asked you: the id the conversation shows for it (8 characters or whole). Their question closes with this reply as its answer, and any decision of yours it was holding back goes back to them. Needs parentId: the Goal the question is on. The reply is sent to them as it is; to also ask something new, send that as its own ask."
33032
33282
  )
33033
33283
  }).strict();
33034
33284
  var StartContactSchema2 = external_exports.object({
33035
- asks: external_exports.array(AskInputSchema2).min(1).describe("The questions to pose, one per object. An ask with a parentId is filed on that Goal as it is; only an ask naming no Goal is placed in the tree by Paigy."),
33285
+ asks: external_exports.array(AskInputSchema2).min(1).describe("The questions to pose, one per object. An ask with a parentId is filed on that Goal as it is; an ask naming no Goal starts a new Goal of yours."),
33036
33286
  waiting: external_exports.enum(["none", "hard"]).default("none").describe("hard requests a call even when channel is notification; user permissions and ring cooldowns still apply."),
33037
33287
  channel: external_exports.enum(["notification", "call"]).default("notification")
33038
33288
  }).strict();
33039
33289
  var ContactSchema2 = external_exports.union([StartContactSchema2, external_exports.object({ deliveryId: external_exports.string().uuid() }).strict()]);
33040
33290
  var CONTACT_SCHEMA2 = { type: "object", ...mcpInputSchema2(ContactSchema2) };
33041
- var CONTACT_DESCRIPTION2 = "Contact the user with one or more asks/questions. Pass an array of asks (each with 'ask', optional 'options', 'select', 'id', 'parentId', 'repo'), plus channel:'notification'|'call', and waiting:'none'|'hard'. An ask that names a Goal (parentId) goes onto that Goal; one that names none is placed in the person's tree by Paigy. Notification returns immediately; collect durable answers with check_replies. On stdio, a Call holds one cancellable ~45s window; continue with ONLY {deliveryId}. One question per 'ask'; several questions are several objects in 'asks'. A bundled ask is taken apart into its own cards by Paigy's one intake read, every one on the Goal the ask lands on; separate pieces of work are separate asks. An ask with no options that is not blocking is a report, and a report is an UPDATE, never a claim on them: it reaches them and is listed apart from what waits on them, so no answer is owed and none should be awaited. On a Goal whose report card is still open it is added to that card, with no new push; one that only says where your work stands while under way is recorded as the Goal's progress, not sent (the result says so). Send options (or waiting:'hard') when you actually need an answer. Each option's label must stand on its own \u2014 the person may see only the labels \u2014 so never a label that points into your text ('All three', 'Option 2', '1 and 3 only'); when the options are independent and they may want several, pass select:'many' and they get a checklist. If the person is already on a call, your contact joins that call automatically \u2014 whatever channel you asked for, with no ring \u2014 and the Delivery it returns IS that call: reread it with contact({deliveryId}) to see everything answered on it so far, and contact again while it is live to add information or a further question to the same call.";
33291
+ var CONTACT_DESCRIPTION2 = "Contact the user with one or more asks/questions. Pass an array of asks (each with 'ask', optional 'options', 'select', 'id', 'parentId', 'repo'), plus channel:'notification'|'call', and waiting:'none'|'hard'. An ask that names a Goal (parentId) goes onto that Goal; one that names none starts a new Goal of yours. Notification returns immediately; collect durable answers with check_replies. On stdio, a Call holds one cancellable ~45s window; continue with ONLY {deliveryId}. One question per 'ask'; several questions are several objects in 'asks'. Each ask is sent exactly as written, with no reading in between: a bundled ask arrives as one card, so separate questions are separate asks. An ask with no options that is not blocking is a report, and a report is an UPDATE, never a claim on them: it reaches them and is listed apart from what waits on them, so no answer is owed and none should be awaited. On a Goal whose report card is still open it is added to that card, with no new push; Where your work stands while under way is progress: report it with update_goal, not contact. Send options (or waiting:'hard') when you actually need an answer. Each option's label must stand on its own \u2014 the person may see only the labels \u2014 so never a label that points into your text ('All three', 'Option 2', '1 and 3 only'). select:'many' makes the card a checklist, for independent options they may want several of; select:'one' (the default) a pick, for alternatives. The person can always answer in their own words, so never add an 'Other' option. If the person is already on a call, your contact joins that call automatically \u2014 whatever channel you asked for, with no ring \u2014 and the Delivery it returns IS that call: reread it with contact({deliveryId}) to see everything answered on it so far, and contact again while it is live to add information or a further question to the same call.";
33042
33292
  var CreateGoalSchema2 = external_exports.object({
33043
33293
  outcome: external_exports.string().trim().min(1).max(1e4),
33044
33294
  /** The work's NAME (#2115) — one to five words, how a person refers to it out loud ("the night
@@ -33061,7 +33311,7 @@ var CreateGoalSchema2 = external_exports.object({
33061
33311
  var CreateGoalToolSchema2 = CreateGoalSchema2.extend({
33062
33312
  idempotencyKey: CreateGoalSchema2.shape.idempotencyKey.optional().describe("Optional. One is minted per call; pass your own only so a retry lands on the same Goal.")
33063
33313
  }).strict();
33064
- var CREATE_GOAL_DESCRIPTION2 = 'Create a durable Goal for an outcome. Without parentGoalId it is placed against your open Goals: if one already IS this work, that Goal comes back (existing: true) and nothing new is created \u2014 continue it; if the work belongs under one, it is created there (parentGoalId in the receipt); otherwise it is a root. Pass parentGoalId yourself to put it under a specific Goal. Pass repo to anchor the work to a specific repository ("owner/repo" or repo name); delegated children inherit it. Pass title to name it in one to five words, as a person would refer to it out loud ("the night rings") \u2014 it heads every list and is spoken on a call; without one the brain writes it. Admission only: the owner must claim it before doing work, then update it as it advances. Returns an admission receipt with goalId, current state, revision, ownerParticipant, and the next step; no Goal content or execution lease.';
33314
+ var CREATE_GOAL_DESCRIPTION2 = 'Create a durable Goal for an outcome. Without parentGoalId it is placed against your open Goals: if one already IS this work, that Goal comes back (existing: true) and nothing new is created \u2014 continue it; if the work belongs under one, it is created there (parentGoalId in the receipt); otherwise it is a root. Pass parentGoalId yourself to put it under a specific Goal. Pass repo to anchor the work to a specific repository ("owner/repo" or repo name); delegated children inherit it. Pass title to name it in one to five words, as a person would refer to it out loud ("the night rings") \u2014 it heads every list and is spoken on a call; without one the brain writes it. Admission only: claim it before doing work, then update it as it advances. Returns an admission receipt with goalId, current state, revision, ownerParticipant, and the next step; no Goal content or execution lease.';
33065
33315
  var UpdateGoalSchema2 = external_exports.object({
33066
33316
  revision: external_exports.number().int().positive(),
33067
33317
  changes: external_exports.object({
@@ -33097,12 +33347,13 @@ var GetGoalSchema2 = external_exports.object({
33097
33347
  * between two of them named. Off by default; `docs/model/goal/diagnose-design.md`. */
33098
33348
  diagnose: external_exports.boolean().optional()
33099
33349
  }).strict();
33100
- var GET_GOAL_DESCRIPTION2 = "Read one Goal without claiming it: its outcome, state, revision, progress, blockers, the conversation on it (each question with its options and what was decided), `next`, the one step to take, and `more`, where to read further. A question in that conversation reads `open` (nothing yet), `answered` (a choice was made, and `answer` carries it), `replied` (they said something and the read settled the question on their words \u2014 NO option of yours was chosen, and the words are the reply line beside it, so read that before you act), or `closed`. The conversation carries everything the person said, every open question and your newest entry; your older entries are left out and counted \u2014 history: true reads every entry in full. Another account's Goals, and another agent's Goal that is not below one of yours, are not disclosed.\n\ndiagnose: true is for when a read has CONFUSED you \u2014 not for the working loop. It adds `diagnosis`, which asks every reader that already answers a question about your work and NAMES the reader behind every value, so you never guess which of two places to look: what state your work is really in (the stored `goals.state` beside the derived `goal_execution_state`, which can differ); whether anything is armed to ring and when (`ladder_candidates`, with the ladder's own last decision); whether a wake fired for you and what it did (durable `wake.*` events, beside when your process was last heard from); and what has reached you (`list_waiting` \u2014 review flags, unstarted work, open questions, the person's newest words). Read `diagnosis.disagreements` FIRST: each one is two readers giving different values for the same fact, with both values and both sources, and it never chooses between them \u2014 that is yours to do, from the Goal's own history. `diagnosis.looked` names every reader asked, including any that could not answer, so an empty answer is never confused with a broken one.";
33101
- var UPDATE_GOAL_DESCRIPTION2 = `Update an owned Goal at an exact revision. State, ownership, dependencies, children, progress, title, and review acknowledgement are explicit; stale revisions are rejected. A CONTACT ON THIS GOAL MOVES ITS REVISION: a question filed on a Goal is a change to it, so an update prepared before a contact and sent after it is refused as stale (409 goal_revision_conflict) \u2014 re-read the Goal, then write. title is the work's name in one to five words, as a person would refer to it out loud (it is spoken on a call and heads every list); null clears it. reviewed: true acknowledges new evidence and closes the Deliveries addressed to you on that Goal, never over an open decision. dueAt (an ISO instant, or null) makes the Goal wait until then; when it passes you are woken for it \u2014 use it for a promise to follow up later. withdraw: [questionId] takes back a question YOU asked on this Goal that is still open \u2014 because you acted on it yourself, it no longer matters, or you asked it wrongly (e.g. waiting: hard when nothing was blocked): it is cancelled, not answered, its card closes and it stops ringing; the id is the one the conversation shows. state: done means the work was accomplished, and it can be reopened: when the person says it is not done ("it's not working"), set state: active on that same Goal instead of starting a new one; its parent reopens with it. state: done while children are still open records your part as done: the Goal waits and closes by itself when its last open child closes. cancelled is final. Returns the Goal as get_goal reads it, at its new revision.`;
33102
- var CLAIM_GOAL_DESCRIPTION2 = "Claim the oldest runnable or review-pending Goal you own, or pass goalId to claim that Goal. Another agent's Goal that has gone quiet for 3 days (check_replies lists them as stalledOthers) is taken over when you claim it, and becomes yours to finish or cancel. Returns the Goal as get_goal reads it, and creates or renews the execution lease.";
33350
+ var GET_GOAL_DESCRIPTION2 = "Read one Goal without claiming it, including others (the ten most recent other contributors, with names, latest entry headlines and times): its outcome, state, revision, progress, blockers, the conversation on it (each question with its options and what was decided), `next`, the one step to take, and `more`, where to read further. A question in that conversation reads `open` (nothing yet), `answered` (a choice was made, and `answer` carries it), `replied` (they said something and the read settled the question on their words \u2014 NO option of yours was chosen, and the words are the reply line beside it, so read that before you act), or `closed`. The conversation carries everything the person said, every open question and your newest entry; your older entries are left out and counted \u2014 history: true reads every entry in full. Every Goal of your person is readable, whichever of their agents owns it; another account's Goals are not disclosed.\n\ndiagnose: true is for when a read has CONFUSED you \u2014 not for the working loop. It adds `diagnosis`, which asks every reader that already answers a question about your work and NAMES the reader behind every value, so you never guess which of two places to look: what state your work is really in (the stored `goals.state` beside the derived `goal_execution_state`, which can differ); whether anything is armed to ring and when (`ladder_candidates`, with the ladder's own last decision); whether a wake fired for you and what it did (durable `wake.*` events, beside when your process was last heard from); and what has reached you (`list_waiting` \u2014 review flags, unstarted work, open questions, the person's newest words). Read `diagnosis.disagreements` FIRST: each one is two readers giving different values for the same fact, with both values and both sources, and it never chooses between them \u2014 that is yours to do, from the Goal's own history. `diagnosis.looked` names every reader asked, including any that could not answer, so an empty answer is never confused with a broken one.";
33351
+ var UPDATE_GOAL_DESCRIPTION2 = `Update a Goal you are on at an exact revision. You are on a Goal you own, or one you have written on (an update with progress, or a contact on it); any of your person's agents may write on any of their Goals, and one that never touched a Goal is refused (409 goal_not_joined). State, ownership, dependencies, children, progress, title, and review acknowledgement are explicit; stale revisions are rejected. A CONTACT ON THIS GOAL MOVES ITS REVISION: a question filed on a Goal is a change to it, so an update prepared before a contact and sent after it is refused as stale (409 goal_revision_conflict) \u2014 re-read the Goal, then write. title is the work's name in one to five words, as a person would refer to it out loud (it is spoken on a call and heads every list); null clears it. reviewed: true acknowledges new evidence and closes the Deliveries addressed to you on that Goal, never over an open decision. dueAt (an ISO instant, or null) makes the Goal wait until then; when it passes you are woken for it \u2014 use it for a promise to follow up later. withdraw: [questionId] takes back a question YOU asked on this Goal that is still open \u2014 because you acted on it yourself, it no longer matters, or you asked it wrongly (e.g. waiting: hard when nothing was blocked): it is cancelled, not answered, its card closes and it stops ringing; the id is the one the conversation shows. state: done means the work was accomplished, and it can be reopened: when the person says it is not done ("it's not working"), set state: active on that same Goal instead of starting a new one; its parent reopens with it. state: done while children are still open records your part as done: the Goal waits and closes by itself when its last open child closes. cancelled is final. Returns the Goal as get_goal reads it, at its new revision.`;
33352
+ var CLAIM_GOAL_DESCRIPTION2 = "Claim a pending answer to your question or the oldest runnable or review-pending Goal you own. Pass goalId to join any Goal of your person; its assignment stays unchanged. Read others before overlapping another agent\u2019s work. Joining lets you contribute and change its state; use update_goal with ownerParticipant when the assignment itself should change. Returns the Goal as get_goal reads it, and marks you as on it, which never shuts another agent out: other agents of your person may write on it and change it too, and two changes at once are told apart by revision (409 goal_revision_conflict).";
33103
33353
  var CHECK_REPLIES_DESCRIPTION2 = "What is waiting for you: your open Deliveries (a request the user started toward you, a handoff), one row each with its Goals, how many decisions are still open, and the newest words in brief; `assigned`, your Goals nobody has started yet, however they became yours (claim_goal({goalId}) starts one); and `review`, your Goals with something new on them \u2014 the user's answers and notes are Entries on the Goal, not Deliveries. A pure read with no arguments: nothing is consumed, acknowledged or claimed by reading it, so call it on startup, after a long wait, or whenever you want to know what is outstanding. To act on one, claim its Goal (claim_goal) or reread a Delivery in full with contact({deliveryId}). Once you have acted on what arrived, update_goal with reviewed: true clears the Goal from `review` and closes the Deliveries addressed to you on it.";
33104
33354
  var CheckRepliesSchema2 = external_exports.object({}).strict();
33105
33355
  var AGENT_TOOLS2 = [
33356
+ { name: "who_is_working", description: "Read your person's agents that contributed in the last 24 hours, newest first: at most 30 agents and their five most recently touched Goals, with their latest entry headline and time. Use get_goal to read a Goal and its other contributors before starting overlapping work. Read-only; no arguments.", inputSchema: mcpInputSchema2(CheckRepliesSchema2) },
33106
33357
  { name: "contact", description: CONTACT_DESCRIPTION2, inputSchema: CONTACT_SCHEMA2 },
33107
33358
  { name: "check_replies", description: CHECK_REPLIES_DESCRIPTION2, inputSchema: mcpInputSchema2(CheckRepliesSchema2) },
33108
33359
  { name: "create_goal", description: CREATE_GOAL_DESCRIPTION2, inputSchema: mcpInputSchema2(CreateGoalToolSchema2) },
@@ -33111,6 +33362,156 @@ var AGENT_TOOLS2 = [
33111
33362
  { name: "update_goal", description: UPDATE_GOAL_DESCRIPTION2, inputSchema: mcpInputSchema2(UpdateGoalToolSchema2) }
33112
33363
  ];
33113
33364
  var AGENT_TOOL_NAMES2 = AGENT_TOOLS2.map((t) => t.name);
33365
+ var id2 = external_exports.string().uuid();
33366
+ var key2 = external_exports.string().min(1).max(40);
33367
+ var participant2 = external_exports.string().regex(/^(human|agent):.+$/, "a participant ID such as agent:<uuid>");
33368
+ var SourceSchema2 = external_exports.object({
33369
+ entryId: id2,
33370
+ span: external_exports.object({ start: external_exports.number().int().min(0), end: external_exports.number().int().min(1) }).strict().refine((s) => s.end > s.start, "a span ends after it starts").optional()
33371
+ }).strict();
33372
+ var ResultRefSchema2 = external_exports.union([external_exports.object({ id: id2 }).strict(), external_exports.object({ local: key2 }).strict()]);
33373
+ var NodeRefSchema2 = external_exports.object({ type: external_exports.enum(["goal", "question"]), id: id2 }).strict();
33374
+ var DependencySchema2 = external_exports.object({
33375
+ blocker: NodeRefSchema2,
33376
+ blocked: NodeRefSchema2,
33377
+ action: external_exports.enum(["start", "complete", "answer"]),
33378
+ reason: external_exports.string().max(500).optional()
33379
+ }).strict();
33380
+ var goalState2 = external_exports.enum(["open", "completed", "canceled"]);
33381
+ var existingGoalChanges2 = [
33382
+ external_exports.object({ kind: external_exports.literal("edit"), goalId: id2, title: external_exports.string().min(1).max(120).optional(), outcome: external_exports.string().min(1).optional() }).strict().refine((c) => c.title !== void 0 || c.outcome !== void 0, "an edit changes the title or the outcome"),
33383
+ external_exports.object({ kind: external_exports.literal("state"), goalId: id2, state: goalState2 }).strict(),
33384
+ external_exports.object({ kind: external_exports.literal("assign"), goalId: id2, ownerId: participant2 }).strict(),
33385
+ external_exports.object({ kind: external_exports.literal("defer"), goalId: id2, until: external_exports.string().datetime().nullable() }).strict(),
33386
+ external_exports.object({ kind: external_exports.literal("move"), goalId: id2, parentGoalId: id2.nullable() }).strict(),
33387
+ external_exports.object({
33388
+ kind: external_exports.literal("dependency"),
33389
+ change: external_exports.enum(["add", "remove"]),
33390
+ goalId: id2,
33391
+ dependsOnGoalId: id2,
33392
+ action: external_exports.enum(["start", "complete"]),
33393
+ reason: external_exports.string().max(500).optional()
33394
+ }).strict()
33395
+ ];
33396
+ var GoalChangeSchema2 = external_exports.union([
33397
+ external_exports.object({
33398
+ kind: external_exports.literal("create"),
33399
+ title: external_exports.string().min(1).max(120),
33400
+ outcome: external_exports.string().min(1),
33401
+ ownerId: participant2,
33402
+ parentGoalId: id2.optional(),
33403
+ sourceEntryIds: external_exports.array(id2)
33404
+ }).strict(),
33405
+ ...existingGoalChanges2
33406
+ ]);
33407
+ var BrainGoalChangeSchema2 = external_exports.union([
33408
+ // newSession: Paigy starts a session to own it (owner, 2026-10-06); until it has, the person owns it.
33409
+ external_exports.object({
33410
+ kind: external_exports.literal("create"),
33411
+ outcome: external_exports.string().min(1),
33412
+ title: external_exports.string().min(1).max(120),
33413
+ ownerId: participant2,
33414
+ parentGoal: ResultRefSchema2.nullable(),
33415
+ newSession: external_exports.literal(true).optional()
33416
+ }).strict(),
33417
+ ...existingGoalChanges2
33418
+ ]);
33419
+ var option2 = external_exports.object({ id: external_exports.string().min(1).max(40), label: external_exports.string().min(1), hint: external_exports.string().optional() }).strict();
33420
+ var QuestionChangeSchema2 = external_exports.union([
33421
+ external_exports.object({
33422
+ kind: external_exports.literal("create"),
33423
+ text: external_exports.string().min(1),
33424
+ answererId: participant2,
33425
+ goal: ResultRefSchema2.optional(),
33426
+ blocks: external_exports.array(external_exports.object({ question: ResultRefSchema2 }).strict()),
33427
+ options: external_exports.array(option2).min(2).optional(),
33428
+ pickMode: external_exports.enum(["one", "many", "rank"]).optional()
33429
+ }).strict().refine((c) => c.options === void 0 === (c.pickMode === void 0), "options and pickMode come together"),
33430
+ external_exports.object({ kind: external_exports.literal("edit"), questionId: id2, text: external_exports.string().min(1) }).strict(),
33431
+ external_exports.object({ kind: external_exports.literal("assign"), questionId: id2, answererId: participant2 }).strict(),
33432
+ external_exports.object({ kind: external_exports.literal("withdraw"), questionId: id2 }).strict(),
33433
+ external_exports.object({ kind: external_exports.literal("dependency"), change: external_exports.enum(["add", "remove"]), edge: DependencySchema2 }).strict()
33434
+ ]);
33435
+ var lessonScope2 = external_exports.union([
33436
+ external_exports.object({ kind: external_exports.literal("user") }).strict(),
33437
+ external_exports.object({ kind: external_exports.literal("goal"), goal: ResultRefSchema2 }).strict()
33438
+ ]);
33439
+ var LessonChangeSchema2 = external_exports.union([
33440
+ external_exports.object({ kind: external_exports.literal("remember"), text: external_exports.string().min(1), scope: lessonScope2 }).strict(),
33441
+ external_exports.object({ kind: external_exports.literal("revise"), lessonId: id2, text: external_exports.string().min(1), scope: lessonScope2 }).strict(),
33442
+ external_exports.object({ kind: external_exports.literal("withdraw"), lessonId: id2 }).strict()
33443
+ ]);
33444
+ var BrainNextSchema2 = external_exports.object({
33445
+ instructions: external_exports.array(external_exports.object({ entryKeys: external_exports.array(key2).min(1) }).strict()),
33446
+ say: external_exports.array(key2),
33447
+ then: external_exports.enum(["listen", "hold", "end", "none"]),
33448
+ waitFor: external_exports.array(ResultRefSchema2),
33449
+ reason: external_exports.string()
33450
+ }).strict();
33451
+ var messageBase2 = {
33452
+ key: key2,
33453
+ text: external_exports.string().min(1),
33454
+ goals: external_exports.array(ResultRefSchema2),
33455
+ questions: external_exports.array(ResultRefSchema2),
33456
+ entryKeys: external_exports.array(key2),
33457
+ obligationIds: external_exports.array(id2)
33458
+ };
33459
+ var BrainMessageSchema2 = external_exports.union([
33460
+ external_exports.object({ ...messageBase2, to: external_exports.object({ kind: external_exports.literal("user") }).strict() }).strict(),
33461
+ external_exports.object({
33462
+ ...messageBase2,
33463
+ to: external_exports.object({ kind: external_exports.literal("session"), sessionId: id2 }).strict(),
33464
+ call: external_exports.object({ callId: id2, listen: external_exports.literal(true) }).strict().optional()
33465
+ }).strict()
33466
+ ]);
33467
+ var BrainSearchSchema2 = external_exports.object({
33468
+ query: external_exports.string().min(1).max(500),
33469
+ within: external_exports.array(external_exports.enum(["entries", "goals", "answers"])).min(1),
33470
+ goalId: id2.optional()
33471
+ }).strict();
33472
+ var BrainResultSchema2 = external_exports.object({
33473
+ messages: external_exports.array(BrainMessageSchema2),
33474
+ entries: external_exports.array(external_exports.object({ key: key2, sources: external_exports.array(SourceSchema2).min(1), goals: external_exports.array(ResultRefSchema2) }).strict()),
33475
+ questions: external_exports.array(external_exports.object({ key: key2, entryKeys: external_exports.array(key2), change: QuestionChangeSchema2 }).strict()),
33476
+ answers: external_exports.array(external_exports.object({
33477
+ question: ResultRefSchema2,
33478
+ entryKeys: external_exports.array(key2).min(1),
33479
+ summary: external_exports.string().min(1),
33480
+ selectedOptionIds: external_exports.array(external_exports.string().min(1)).optional()
33481
+ }).strict()),
33482
+ goals: external_exports.array(external_exports.object({ key: key2, entryKeys: external_exports.array(key2), change: BrainGoalChangeSchema2 }).strict()),
33483
+ feedback: external_exports.array(external_exports.object({ entryKeys: external_exports.array(key2).min(1) }).strict()),
33484
+ lessons: external_exports.array(external_exports.object({ entryKeys: external_exports.array(key2).min(1), change: LessonChangeSchema2 }).strict()),
33485
+ next: BrainNextSchema2,
33486
+ search: BrainSearchSchema2.optional()
33487
+ }).strict();
33488
+ var str2 = external_exports.string();
33489
+ var strs2 = external_exports.array(external_exports.string());
33490
+ var CompactResultSchema2 = external_exports.object({
33491
+ next: external_exports.object({ say: strs2, then: external_exports.enum(["listen", "hold", "end", "none"]), waitFor: strs2, reason: str2, instructions: strs2 }).strict(),
33492
+ messages: external_exports.array(external_exports.object({ key: str2, to: str2, text: str2, about: strs2, entries: strs2, owed: strs2, inviteToCall: external_exports.boolean() }).strict()),
33493
+ entries: external_exports.array(external_exports.object({ key: str2, from: str2, start: external_exports.number().int(), end: external_exports.number().int(), on: strs2 }).strict()),
33494
+ answers: external_exports.array(external_exports.object({ question: str2, entries: strs2, summary: str2, picked: strs2 }).strict()),
33495
+ changes: external_exports.array(external_exports.object({
33496
+ key: str2,
33497
+ what: external_exports.enum(["goal", "question", "lesson"]),
33498
+ op: external_exports.enum(["create", "edit", "assign", "open", "complete", "cancel", "defer", "move", "block", "unblock", "withdraw", "remember", "revise"]),
33499
+ id: str2,
33500
+ text: str2,
33501
+ title: str2,
33502
+ who: str2,
33503
+ under: str2,
33504
+ gate: external_exports.enum(["start", "complete", "answer", "none"]),
33505
+ options: external_exports.array(external_exports.object({ id: str2, label: str2 }).strict()),
33506
+ pick: external_exports.enum(["one", "many", "rank", "words"]),
33507
+ entries: strs2
33508
+ }).strict()),
33509
+ feedback: external_exports.array(strs2),
33510
+ search: external_exports.object({ query: str2, within: strs2, goal: str2 }).strict()
33511
+ }).strict();
33512
+ var COMPACT_RESULT_JSON_SCHEMA2 = (({ $schema: _, ...rest }) => rest)(
33513
+ zodToJsonSchema2(CompactResultSchema2, { $refStrategy: "none" })
33514
+ );
33114
33515
  function entryWords(entry) {
33115
33516
  const content = entry.content;
33116
33517
  if (content && "sealed" in content) return "";
@@ -33123,11 +33524,13 @@ function entryWords(entry) {
33123
33524
  const description = plain.description;
33124
33525
  const parts = [title, ...Array.isArray(description) ? description : []].filter((v) => typeof v === "string");
33125
33526
  if (parts.length) return parts.join("\n\n");
33527
+ const line = plain.line;
33528
+ if (typeof line === "string" && line.trim()) return line;
33126
33529
  }
33127
33530
  return entry.sources.map((source) => source.text).join("\n");
33128
33531
  }
33129
33532
  var LIVE_MS2 = 3 * 6e4;
33130
- var WORKING_MS2 = 30 * 6e4;
33533
+ var WORKING_MS2 = 60 * 6e4;
33131
33534
  var ContextSchema2 = external_exports.object({
33132
33535
  title: external_exports.string().min(1).describe("One-line headline of what you need (required, non-empty)."),
33133
33536
  description: external_exports.array(external_exports.string().min(1)).describe(
@@ -33345,7 +33748,7 @@ var IntentSchema2 = external_exports.object({
33345
33748
  * (`parseDelay`, #1292), and a value here simply wins over that reading. */
33346
33749
  dueInSeconds: external_exports.number().int().positive().optional(),
33347
33750
  /** Feedback only (#812): WHICH failure the complaint names — typed by the mapper that
33348
- * already read the utterance, so `feedback_from_call.kind` stops defaulting to
33751
+ * already read the utterance, so `signals.kind` stops defaulting to
33349
33752
  * 'other' on every row. A table that records that something was wrong and nothing
33350
33753
  * about what cannot answer "is the bot looping less this week?". */
33351
33754
  fault: external_exports.enum(["loop", "unanswered", "overridden", "misheard", "slow", "other"]).optional()
@@ -33479,7 +33882,13 @@ var AgendaTurnSchema2 = external_exports.object({
33479
33882
  /** Whether the walk WAITS for an answer before moving on. Absent = derived as today
33480
33883
  * (a question blocks, context flows). blocking:false on a question = ask and move
33481
33884
  * on, the claim stays pending; blocking:true on context = hold for a reply. */
33482
- blocking: external_exports.boolean().optional()
33885
+ blocking: external_exports.boolean().optional(),
33886
+ /** SPOKEN ONLY IF THEY SAY NOTHING (owner, 2026-10-01, call 812de935: "you're gonna re-ask, but it
33887
+ * shouldn't be the same words … more like, hey, are you still there, or are you able to answer, or
33888
+ * would you need more information"). The walk holds this turn out of its queue; at the queue's end it
33889
+ * listens for the last word, and only if that listen is silent is this turn said and asked. If they
33890
+ * speak, it is dropped and their words are taken like any reply. */
33891
+ ifSilent: external_exports.boolean().optional()
33483
33892
  });
33484
33893
  var CLAIM_STALE_MS2 = 30 * 6e4;
33485
33894
  var InboxItemSchema2 = external_exports.object({
@@ -33623,7 +34032,18 @@ var InboxItemSchema2 = external_exports.object({
33623
34032
  /** THAT GOAL'S NAME (#2416) — what Activity's row is headed by, since a row there is one Goal
33624
34033
  * and the cards it holds sit behind it. Stamped by the same read as `goalState`. */
33625
34034
  goalTitle: external_exports.string().optional()
33626
- }).optional()
34035
+ }).optional(),
34036
+ /** WHAT THIS CARD IS, IN TWELVE CHARACTERS (#3019) — the hash of every other field on it, stamped
34037
+ * by the one read that serves the open list (`apps/api/src/inbox/project.ts` `inboxFor`). It is
34038
+ * how the incremental read knows a card has not moved: the phone echoes back the revs it holds
34039
+ * (`POST /api/inbox/changes`) and is sent only the cards whose rev differs.
34040
+ *
34041
+ * THE PAYLOAD'S OWN HASH, NEVER A STAMP ON THE WORK — the same mechanism as `QueueItem.rev`
34042
+ * (#2928) and an entry's (#3018), for the same reason: a card shows facts no `updated_at` of its
34043
+ * own moves (its Goal's state and name, how cold the work behind it has gone, whether a ring is
34044
+ * live). Optional, so a fixture, the demo and the archive lens need not spell one, and a card
34045
+ * with no rev is simply always re-sent. */
34046
+ rev: external_exports.string().optional()
33627
34047
  });
33628
34048
  var APNS_TOKEN_RE2 = /^[0-9a-fA-F]{64}$/;
33629
34049
  var PushTokenSchema2 = external_exports.object({
@@ -33995,7 +34415,22 @@ var QueueItemSchema2 = external_exports.object({
33995
34415
  * minute after the person speaks erases their instant from it, and the durable traces the client
33996
34416
  * can see (`replies`, `questions[].answeredAt`) miss a spontaneous note entirely — a `request`
33997
34417
  * Entry with no `about_id` is in neither. */
33998
- lastPersonAt: external_exports.string().nullable().optional()
34418
+ lastPersonAt: external_exports.string().nullable().optional(),
34419
+ /** WHAT THIS ROW IS, IN TWELVE CHARACTERS (#2928) — the hash of every other field on it, stamped
34420
+ * by the one projection that builds the row (`apps/api/src/goal/queue.ts`). It is how the
34421
+ * incremental read knows a row has not moved: the phone echoes back the revs it holds
34422
+ * (`POST /api/goals/changes`) and is sent only the rows whose rev differs.
34423
+ *
34424
+ * IT IS THE PAYLOAD'S OWN HASH, NEVER A STAMP ON THE WORK. Nothing here reasons about which
34425
+ * writes change which field — the comparison is over the bytes the phone is holding, so a fact
34426
+ * the row shows that no `updated_at` moves for (a lease lapsing, a dependency's state, a
34427
+ * sibling appearing in `childGoalIds`) cannot go unnoticed. Optional because a hand-built
34428
+ * queue (a fixture, the demo) spells none, and a row with no rev is simply always re-sent. */
34429
+ rev: external_exports.string().optional()
34430
+ });
34431
+ var QueueDeltaSchema2 = external_exports.object({
34432
+ ids: external_exports.array(external_exports.string()),
34433
+ items: external_exports.array(QueueItemSchema2)
33999
34434
  });
34000
34435
  var COLD_AFTER_MS2 = 3 * 24 * 60 * 60 * 1e3;
34001
34436
  var NoteSourceSchema2 = external_exports.enum(["app", "call"]);
@@ -34166,6 +34601,11 @@ var DeviceTokenSchema2 = external_exports.object({
34166
34601
  /** Local host recovery must preserve the launch's runtime and Paigy identity. */
34167
34602
  harness: external_exports.enum(["claude", "codex", "agy"]).optional(),
34168
34603
  session_id: external_exports.string().uuid().optional(),
34604
+ /** A conversation the host must not resume: its context is full, so every turn fails
34605
+ * ("Prompt is too long"). Written when a run hits it (`run.ts` `onFull`); the host skips a slot
34606
+ * whose resumable session is this one, so its Goals reach the dead-agent handoff instead of a
34607
+ * copy that types the person's words into a turn that cannot run (Calls, 2026-10-06). */
34608
+ full_session: external_exports.string().optional(),
34169
34609
  uik_pub: external_exports.string().nullable().optional()
34170
34610
  });
34171
34611
  var SupportRequestSchema2 = external_exports.object({
@@ -34519,9 +34959,13 @@ async function finish(result, state, rail, opts) {
34519
34959
  const progress = result?.trim().slice(0, 1e4) || void 0;
34520
34960
  let revision = goal.revision;
34521
34961
  try {
34522
- const held = await rail.claim(goal.id);
34962
+ const held = await rail.read(goal.id);
34523
34963
  revision = held.revision ?? revision;
34524
34964
  const owed = state.noted?.some((b) => b.goals.includes(goal.id));
34965
+ if (held.state === "done" || held.state === "cancelled") {
34966
+ if (!owed) state.goal = void 0;
34967
+ return;
34968
+ }
34525
34969
  if (!held.openDecisionNeedIds?.length && !owed) {
34526
34970
  await rail.update(goal.id, { revision, changes: { state: "done", ...progress ? { progress } : {} }, reason: "The agent finished its turn." });
34527
34971
  state.goal = void 0;
@@ -34539,17 +34983,31 @@ async function finish(result, state, rail, opts) {
34539
34983
  }
34540
34984
  async function cannotWork(report, state, rail, opts) {
34541
34985
  state.resting = true;
34986
+ const say = (parentId) => rail.contact({ asks: [{ ask: report, ...parentId ? { parentId } : {} }], waiting: "none", channel: "notification" });
34542
34987
  try {
34543
34988
  if (!state.goal) {
34544
- const claimed = await rail.claim();
34545
- if (!claimed.goalId || claimed.revision === void 0) return;
34546
- state.goal = { id: claimed.goalId, revision: claimed.revision };
34989
+ const claimed = await rail.claim().catch(() => void 0);
34990
+ if (claimed?.goalId && claimed.revision !== void 0) state.goal = { id: claimed.goalId, revision: claimed.revision };
34991
+ }
34992
+ if (!state.goal) {
34993
+ await say();
34994
+ return;
34995
+ }
34996
+ try {
34997
+ await say(state.goal.id);
34998
+ } catch (error) {
34999
+ if (!/goal_parent_invalid/.test(error.message)) throw error;
35000
+ opts?.log?.(`\u26A0 the held Goal ${state.goal.id.slice(0, 8)} refused the notice (goal_parent_invalid) \u2014 saying it unplaced`);
35001
+ await say();
34547
35002
  }
34548
- await rail.contact({ asks: [{ ask: report, parentId: state.goal.id }], waiting: "none", channel: "notification" });
34549
35003
  } catch (error) {
34550
35004
  opts?.log?.(`\u26A0 could not say the agent cannot work: ${error.message}`);
34551
35005
  }
34552
35006
  }
35007
+ function conversationFull(result) {
35008
+ return /prompt is too long/i.test(result ?? "");
35009
+ }
35010
+ var FULL_NOTICE = "This agent's conversation is full, so it can no longer take a turn. Its session has ended and will not be resumed; its Goals go to the dead-agent handoff.";
34553
35011
  async function afterTurn(event, state, rail, opts) {
34554
35012
  if (event.failed) {
34555
35013
  const limit = limitIn(event.result, (opts?.now ?? Date.now)());
@@ -34562,6 +35020,11 @@ async function afterTurn(event, state, rail, opts) {
34562
35020
  opts?.log?.(`\u23F8 paused by the usage limit until ${limit.resets}: nothing is typed in until then, and it carries on by itself`);
34563
35021
  return limit;
34564
35022
  }
35023
+ if (conversationFull(event.result)) {
35024
+ if (!state.full) await cannotWork(FULL_NOTICE, state, rail, opts);
35025
+ state.full = true;
35026
+ return void 0;
35027
+ }
34565
35028
  await cannotWork(`The agent stopped without finishing.
34566
35029
 
34567
35030
  ${event.result?.trim() || "No result reported."}`, state, rail, opts);
@@ -34610,11 +35073,16 @@ function beat() {
34610
35073
  }
34611
35074
  var BEAT_REPORT_MS = 10 * 6e4;
34612
35075
  var ended = (state) => state === "done" || state === "cancelled";
34613
- function unheard(brief, state, since = null, after = -1) {
35076
+ function unheard(brief, state, since = null, after = -1, reviewSince) {
34614
35077
  const seen = state.seen ??= /* @__PURE__ */ new Set();
34615
35078
  const words2 = [];
35079
+ const pendingAt = reviewSince ? Date.parse(reviewSince) : null;
34616
35080
  for (const [i, e] of (brief.entries ?? []).entries()) {
34617
35081
  if (seen.has(e.entryId) || !e.authorParticipant.startsWith("human:")) continue;
35082
+ if (pendingAt !== null && Date.parse(e.createdAt) < pendingAt) {
35083
+ seen.add(e.entryId);
35084
+ continue;
35085
+ }
34618
35086
  if (i <= after) {
34619
35087
  seen.add(e.entryId);
34620
35088
  continue;
@@ -34625,6 +35093,12 @@ function unheard(brief, state, since = null, after = -1) {
34625
35093
  const text = entryWords(e).trim();
34626
35094
  if (text) words2.push(text);
34627
35095
  }
35096
+ if (pendingAt !== null) for (const answer of brief.answers ?? []) {
35097
+ const key3 = `answer:${answer.decisionNeedId}`;
35098
+ if (seen.has(key3) || Date.parse(answer.acceptedAt) < pendingAt) continue;
35099
+ seen.add(key3);
35100
+ words2.push(`Answer to question ${answer.decisionNeedId}: ${JSON.stringify(answer.result)}`);
35101
+ }
34628
35102
  return words2;
34629
35103
  }
34630
35104
  function sinceTheWork(brief) {
@@ -34667,16 +35141,16 @@ async function gather(state, rail, held) {
34667
35141
  const listed = /* @__PURE__ */ new Set();
34668
35142
  const announced = state.announced ??= /* @__PURE__ */ new Set();
34669
35143
  if (waiting) {
34670
- for (const id of announced) if (!(waiting.assigned ?? []).some((g) => g.goalId === id)) announced.delete(id);
35144
+ for (const id3 of announced) if (!(waiting.assigned ?? []).some((g) => g.goalId === id3)) announced.delete(id3);
34671
35145
  }
34672
35146
  for (const g of waiting?.assigned ?? []) if (g.goalId !== state.goal.id && !announced.has(g.goalId)) look2(g.goalId, "assigned", g.title);
34673
35147
  for (const g of waiting?.review ?? []) {
34674
35148
  listed.add(g.goalId);
34675
35149
  look2(g.goalId, "waiting work", g.title);
34676
35150
  }
34677
- for (const d of waiting?.deliveries ?? []) for (const id of d.goalIds) {
34678
- listed.add(id);
34679
- look2(id, "waiting work");
35151
+ for (const d of waiting?.deliveries ?? []) for (const id3 of d.goalIds) {
35152
+ listed.add(id3);
35153
+ look2(id3, "waiting work");
34680
35154
  }
34681
35155
  const moved = movedBelow(held, state);
34682
35156
  for (const { goal, since } of moved) look2(goal.goalId, "subtree", goal.title, since);
@@ -34693,9 +35167,9 @@ async function gather(state, rail, held) {
34693
35167
  }
34694
35168
  }
34695
35169
  read.add(goalId);
34696
- const fresh = found.via === "waiting work" || found.via === "assigned" ? sinceTheWork(brief) : { after: -1 };
35170
+ const fresh = !brief.reviewSince && (found.via === "waiting work" || found.via === "assigned") ? sinceTheWork(brief) : { after: -1 };
34697
35171
  if (found.via === "assigned") announced.add(goalId);
34698
- heard.push({ goalId, ...found, brief, words: unheard(brief, state, since ?? null, fresh.after), ...fresh.note ? { note: fresh.note } : {} });
35172
+ heard.push({ goalId, ...found, brief, words: unheard(brief, state, brief.reviewSince ? null : since ?? null, fresh.after, brief.reviewSince), ...fresh.note ? { note: fresh.note } : {} });
34699
35173
  }
34700
35174
  for (const { goal, since } of moved) if (read.has(goal.goalId)) state.below.goals.set(goal.goalId, { since, at: goal.updatedAt ?? null });
34701
35175
  return { heard, listed };
@@ -34714,7 +35188,7 @@ var block = (h) => [
34714
35188
  ...h.note ? [`The last note on it, from the agent before you: ${h.note}`] : [],
34715
35189
  ...h.words
34716
35190
  ].join("\n\n");
34717
- var short = (ids) => ids.map((id) => id.slice(0, 8)).join(", ");
35191
+ var short = (ids) => ids.map((id3) => id3.slice(0, 8)).join(", ");
34718
35192
  var given = (heard) => heard.filter((h) => h.via === "assigned").map((h) => h.goalId);
34719
35193
  async function hear(session, state, rail, held, opts) {
34720
35194
  const log = opts?.log;
@@ -34781,8 +35255,8 @@ async function acknowledge(goalId, brief, state, rail, log) {
34781
35255
  if (acked.has(goalId) && acked.get(goalId) === brief.revision) return;
34782
35256
  acked.set(goalId, brief.revision);
34783
35257
  try {
34784
- const claimed = await rail.claim(goalId);
34785
- const done = await rail.update(goalId, { revision: claimed.revision ?? brief.revision ?? 1, changes: { reviewed: true }, reason: "Read by the harness session; the person's words on it are typed in." });
35258
+ if (brief.revision === void 0) throw new Error("review_revision_missing");
35259
+ const done = await rail.update(goalId, { revision: brief.revision, changes: { reviewed: true }, reason: "Read by the harness session; the person's words on it are typed in." });
34786
35260
  acked.set(goalId, done.revision);
34787
35261
  if (state.goal?.id === goalId && done.revision !== void 0) state.goal.revision = done.revision;
34788
35262
  } catch (error) {
@@ -34819,25 +35293,26 @@ async function look(session, state, rail, opts) {
34819
35293
  brief2 = await rail.claim();
34820
35294
  if (!brief2.goalId || brief2.revision === void 0) {
34821
35295
  state.goal = { id: admitted.goalId, revision: admitted.revision };
34822
- send2(session, state, [HARNESS_INSTRUCTION, prompt].join("\n\n"));
35296
+ send2(session, state, [HARNESS_INSTRUCTION, named(admitted.goalId, void 0, { outcome: prompt }), prompt].join("\n\n"));
34823
35297
  return;
34824
35298
  }
34825
35299
  } else {
34826
35300
  return;
34827
35301
  }
34828
35302
  }
34829
- unheard(brief2, state);
34830
- if (ended(brief2.state)) await rail.update(brief2.goalId, { revision: brief2.revision, changes: { reviewed: true }, reason: "Typed into the session." });
34831
- else {
35303
+ const pendingWords = brief2.reviewSince ? unheard(brief2, state, null, -1, brief2.reviewSince) : null;
35304
+ if (!pendingWords) unheard(brief2, state);
35305
+ if (!ended(brief2.state)) {
34832
35306
  state.goal = { id: brief2.goalId, revision: brief2.revision };
34833
35307
  state.below = baseline(brief2.goalId, brief2.subtree);
34834
35308
  }
34835
35309
  const outcome2 = brief2.outcome?.trim() ?? "";
34836
- const said = (brief2.entries ?? []).map((e) => entryWords(e).trim()).filter((w) => w && w.toLowerCase() !== outcome2.toLowerCase());
35310
+ const said = (pendingWords ?? (brief2.entries ?? []).map((e) => entryWords(e).trim())).filter((w) => w && w.toLowerCase() !== outcome2.toLowerCase());
34837
35311
  const left = brief2.earlier ? brief2.earlier.omitted + brief2.earlier.shortened : 0;
34838
35312
  const earlier = left ? `(${left} earlier entries on this Goal are left out or shortened; get_goal with history: true reads them in full.)` : "";
34839
35313
  const fullText = [outcome2, earlier, ...said].filter(Boolean).join("\n\n");
34840
- send2(session, state, [HARNESS_INSTRUCTION, fullText].filter(Boolean).join("\n\n"));
35314
+ send2(session, state, [HARNESS_INSTRUCTION, named(brief2.goalId, void 0, brief2), fullText].filter(Boolean).join("\n\n"));
35315
+ if (ended(brief2.state)) await acknowledge(brief2.goalId, brief2, state, rail, opts?.log);
34841
35316
  return;
34842
35317
  }
34843
35318
  const brief = await rail.read(state.goal.id);
@@ -34846,6 +35321,7 @@ async function look(session, state, rail, opts) {
34846
35321
  const resolve3 = state.asks?.get(answer.requestEntryId);
34847
35322
  if (!resolve3) continue;
34848
35323
  state.asks.delete(answer.requestEntryId);
35324
+ (state.seen ??= /* @__PURE__ */ new Set()).add(`answer:${answer.decisionNeedId}`);
34849
35325
  resolve3(answer.result);
34850
35326
  }
34851
35327
  if (ended(brief.state)) {
@@ -34923,8 +35399,9 @@ function runHarness(opts) {
34923
35399
  const state = { resting: true };
34924
35400
  const clock4 = beat();
34925
35401
  let session = null;
34926
- const speaksAs = opts.resume ?? opts.session;
34927
- const rail = railFor({ token: opts.token, ...speaksAs ? { reach: reachAs(speaksAs) } : {} });
35402
+ const speaksAs = opts.session ?? opts.resume ?? sessionId();
35403
+ const instance = randomUUID6();
35404
+ const rail = railFor({ token: opts.token, reach: reachAs(speaksAs, instance) });
34928
35405
  let inbox;
34929
35406
  if (opts.harness === "claude") {
34930
35407
  try {
@@ -34975,11 +35452,17 @@ ${event.message}`, state, rail, { log: opts.log });
34975
35452
  tail = [];
34976
35453
  const carried = state.carriedOn && !event.failed;
34977
35454
  if (await afterTurn(event, state, rail, { log: opts.log })) LIMITS.paused(name, Date.now());
34978
- else if (carried) runningAgain();
35455
+ else if (state.full) {
35456
+ opts.log(`\u25A0 ${name}'s conversation is full \u2014 ending this run; it will not be resumed`);
35457
+ opts.onFull?.(speaksAs);
35458
+ stop2();
35459
+ return;
35460
+ } else if (carried) runningAgain();
34979
35461
  clock4.nudge("rest");
34980
35462
  }
34981
35463
  }
34982
35464
  session = startSession({
35465
+ instance,
34983
35466
  harness: opts.harness,
34984
35467
  cwd: opts.cwd,
34985
35468
  mode: opts.mode,
@@ -35022,9 +35505,9 @@ ${event.message}`, state, rail, { log: opts.log });
35022
35505
 
35023
35506
  // src/host.ts
35024
35507
  init_dist();
35025
- import { readFileSync as readFileSync5, writeFileSync as writeFileSync4 } from "fs";
35508
+ import { readFileSync as readFileSync6, writeFileSync as writeFileSync4 } from "fs";
35026
35509
  import { homedir as homedir9 } from "os";
35027
- import { join as join9 } from "path";
35510
+ import { join as join10 } from "path";
35028
35511
 
35029
35512
  // src/broker.ts
35030
35513
  init_evidence();
@@ -35044,15 +35527,15 @@ function ago(iso, now) {
35044
35527
  init_catalog();
35045
35528
 
35046
35529
  // src/workspaces.ts
35047
- import { existsSync as existsSync4, mkdirSync as mkdirSync3, readdirSync as readdirSync2, readFileSync as readFileSync3, statSync as statSync3, writeFileSync as writeFileSync3 } from "fs";
35048
- import { dirname as dirname2, join as join5, resolve as resolve2 } from "path";
35530
+ import { existsSync as existsSync4, mkdirSync as mkdirSync3, readdirSync as readdirSync2, readFileSync as readFileSync4, statSync as statSync3, writeFileSync as writeFileSync3 } from "fs";
35531
+ import { dirname as dirname2, join as join6, resolve as resolve2 } from "path";
35049
35532
  import { homedir as homedir6 } from "os";
35050
35533
  function workspacesFile() {
35051
- return join5(homedir6(), ".paigy", "workspaces.json");
35534
+ return join6(homedir6(), ".paigy", "workspaces.json");
35052
35535
  }
35053
35536
  function listWorkspaces(deps) {
35054
35537
  try {
35055
- const parsed = JSON.parse(readFileSync3(deps.file, "utf8"));
35538
+ const parsed = JSON.parse(readFileSync4(deps.file, "utf8"));
35056
35539
  return Array.isArray(parsed) ? parsed.filter((w) => typeof w === "string") : [];
35057
35540
  } catch {
35058
35541
  return [];
@@ -35081,8 +35564,8 @@ function resolveWakeDir(pinned, deps) {
35081
35564
  }
35082
35565
  function originOf(dir) {
35083
35566
  try {
35084
- if (!statSync3(join5(dir, ".git")).isDirectory()) return null;
35085
- const config = readFileSync3(join5(dir, ".git", "config"), "utf8");
35567
+ if (!statSync3(join6(dir, ".git")).isDirectory()) return null;
35568
+ const config = readFileSync4(join6(dir, ".git", "config"), "utf8");
35086
35569
  const section = config.split(/^\[/m).find((s) => /^remote\s+"origin"\]/.test(s));
35087
35570
  return section?.match(/^\s*url\s*=\s*(.+)$/m)?.[1]?.trim() ?? null;
35088
35571
  } catch {
@@ -35103,7 +35586,7 @@ function listRepos(deps) {
35103
35586
  }
35104
35587
  for (const name of children) {
35105
35588
  if (repos.length >= MAX_REPOS) return repos;
35106
- const path = join5(root, name);
35589
+ const path = join6(root, name);
35107
35590
  const remote = originOf(path);
35108
35591
  if (remote) repos.push({ path, remote });
35109
35592
  }
@@ -35114,9 +35597,9 @@ function listRepos(deps) {
35114
35597
  // src/holder.ts
35115
35598
  init_dist();
35116
35599
  import { execFileSync as execFileSync3 } from "child_process";
35117
- import { readFileSync as readFileSync4, readdirSync as readdirSync3 } from "fs";
35600
+ import { readFileSync as readFileSync5, readdirSync as readdirSync3 } from "fs";
35118
35601
  import { homedir as homedir7 } from "os";
35119
- import { join as join6 } from "path";
35602
+ import { join as join7 } from "path";
35120
35603
  function isAlive(pid) {
35121
35604
  try {
35122
35605
  process.kill(pid, 0);
@@ -35154,9 +35637,9 @@ function proven(pid, procStart, deps) {
35154
35637
  });
35155
35638
  }
35156
35639
  function localHolderPids(deps = {}) {
35157
- const dir = deps.dir ?? join6(process.env.CLAUDE_CONFIG_DIR?.trim() || join6(homedir7(), ".claude"), "sessions");
35640
+ const dir = deps.dir ?? join7(process.env.CLAUDE_CONFIG_DIR?.trim() || join7(homedir7(), ".claude"), "sessions");
35158
35641
  const list = deps.list ?? ((d) => readdirSync3(d));
35159
- const read = deps.read ?? ((f) => readFileSync4(f, "utf8"));
35642
+ const read = deps.read ?? ((f) => readFileSync5(f, "utf8"));
35160
35643
  const check = { alive: deps.alive ?? isAlive, started: deps.started ?? psStart };
35161
35644
  const held = /* @__PURE__ */ new Map();
35162
35645
  let files;
@@ -35169,7 +35652,7 @@ function localHolderPids(deps = {}) {
35169
35652
  if (!/^\d+\.json$/.test(file)) continue;
35170
35653
  let row;
35171
35654
  try {
35172
- row = JSON.parse(read(join6(dir, file)));
35655
+ row = JSON.parse(read(join7(dir, file)));
35173
35656
  } catch {
35174
35657
  continue;
35175
35658
  }
@@ -35199,9 +35682,9 @@ function descendsFrom(pid, ancestor, parent = psParent) {
35199
35682
  return false;
35200
35683
  }
35201
35684
  function localHolders(deps = {}) {
35202
- const dir = deps.dir ?? join6(process.env.CLAUDE_CONFIG_DIR?.trim() || join6(homedir7(), ".claude"), "sessions");
35685
+ const dir = deps.dir ?? join7(process.env.CLAUDE_CONFIG_DIR?.trim() || join7(homedir7(), ".claude"), "sessions");
35203
35686
  const list = deps.list ?? ((d) => readdirSync3(d));
35204
- const read = deps.read ?? ((f) => readFileSync4(f, "utf8"));
35687
+ const read = deps.read ?? ((f) => readFileSync5(f, "utf8"));
35205
35688
  const check = { alive: deps.alive ?? isAlive, started: deps.started ?? psStart };
35206
35689
  const held = /* @__PURE__ */ new Map();
35207
35690
  let files;
@@ -35214,7 +35697,7 @@ function localHolders(deps = {}) {
35214
35697
  if (!/^\d+\.json$/.test(file)) continue;
35215
35698
  let row;
35216
35699
  try {
35217
- row = JSON.parse(read(join6(dir, file)));
35700
+ row = JSON.parse(read(join7(dir, file)));
35218
35701
  } catch {
35219
35702
  continue;
35220
35703
  }
@@ -35289,7 +35772,7 @@ async function endSession(end, deps) {
35289
35772
  // src/owner.ts
35290
35773
  import { closeSync as closeSync2, openSync as openSync2, readSync, readdirSync as readdirSync4 } from "fs";
35291
35774
  import { homedir as homedir8 } from "os";
35292
- import { join as join7 } from "path";
35775
+ import { join as join8 } from "path";
35293
35776
  var HEAD_BYTES = 64e3;
35294
35777
  function readHead(file) {
35295
35778
  const fd = openSync2(file, "r");
@@ -35305,7 +35788,7 @@ function ownerSession(slot, deps = {}) {
35305
35788
  const m = /^session:([0-9a-f]{8})$/.exec(slot);
35306
35789
  if (!m) return null;
35307
35790
  const prefix = m[1];
35308
- const root = deps.projectsDir ?? join7(homedir8(), ".claude", "projects");
35791
+ const root = deps.projectsDir ?? join8(homedir8(), ".claude", "projects");
35309
35792
  const list = deps.list ?? ((dir) => readdirSync4(dir));
35310
35793
  const head = deps.head ?? readHead;
35311
35794
  let folders;
@@ -35317,7 +35800,7 @@ function ownerSession(slot, deps = {}) {
35317
35800
  for (const folder of folders) {
35318
35801
  let files;
35319
35802
  try {
35320
- files = list(join7(root, folder));
35803
+ files = list(join8(root, folder));
35321
35804
  } catch {
35322
35805
  continue;
35323
35806
  }
@@ -35325,7 +35808,7 @@ function ownerSession(slot, deps = {}) {
35325
35808
  if (!file) continue;
35326
35809
  let text;
35327
35810
  try {
35328
- text = head(join7(root, folder, file));
35811
+ text = head(join8(root, folder, file));
35329
35812
  } catch {
35330
35813
  continue;
35331
35814
  }
@@ -35345,7 +35828,7 @@ function ownerSession(slot, deps = {}) {
35345
35828
  // src/update.ts
35346
35829
  import { execFile } from "child_process";
35347
35830
  import { createRequire } from "module";
35348
- import { dirname as dirname3, join as join8 } from "path";
35831
+ import { dirname as dirname3, join as join9 } from "path";
35349
35832
  import { promisify } from "util";
35350
35833
  var SERVICE_LABEL = "ai.paigy.harness";
35351
35834
  var VERSION = createRequire(import.meta.url)("../package.json").version;
@@ -35372,7 +35855,7 @@ async function latestVersion() {
35372
35855
  }
35373
35856
  async function install(version) {
35374
35857
  const bin = dirname3(process.execPath);
35375
- await promisify(execFile)(join8(bin, "npm"), ["install", "-g", `@paigy/harness@${version}`], {
35858
+ await promisify(execFile)(join9(bin, "npm"), ["install", "-g", `@paigy/harness@${version}`], {
35376
35859
  env: { ...process.env, PATH: `${bin}:${process.env.PATH ?? ""}`, npm_config_update_notifier: "false" },
35377
35860
  timeout: 5 * 6e4
35378
35861
  });
@@ -35423,7 +35906,7 @@ function selfUpdater(deps) {
35423
35906
  }
35424
35907
 
35425
35908
  // src/host.ts
35426
- var HOST_FILE = join9(homedir9(), ".paigy", "host.json");
35909
+ var HOST_FILE = join10(homedir9(), ".paigy", "host.json");
35427
35910
  function wakeHarness(slot, saved, claudeTranscript) {
35428
35911
  if (slot === "Desktop") return void 0;
35429
35912
  if (saved !== null) return saved === "agy" || saved === "codex" || saved === "claude" ? saved : void 0;
@@ -35439,26 +35922,33 @@ var claimedRun = (sessionId2) => {
35439
35922
  return { slot, key: runKey(slot) };
35440
35923
  };
35441
35924
  var launchRun = (spec) => ({ session: spec.sessionId });
35925
+ var BOUND_ELSEWHERE_MS = 10 * 6e4;
35926
+ var boundElsewhere = /* @__PURE__ */ new Map();
35927
+ var BOUND_SKIP = "is bound to the session it was paired in, which this host cannot name \u2014 run `paigy-harness handoff` as it, in its folder, to record it";
35442
35928
  var NOTHING_WAITING = "has nothing waiting";
35443
35929
  async function waitingWork(token, session) {
35930
+ const quiet = boundElsewhere.get(token);
35931
+ if (quiet !== void 0 && Date.now() < quiet) return { skip: BOUND_SKIP };
35444
35932
  let found;
35445
35933
  try {
35446
35934
  found = await checkReplies({ token, ...session ? { reach: reachAs(session) } : {} });
35447
35935
  } catch (error) {
35448
35936
  if (error instanceof RevokedError) return { skip: "was revoked: its credential is gone for good", revoked: true };
35449
35937
  if (error instanceof ApiError && error.body?.error === "identity_session_mismatch") {
35450
- return { skip: "is bound to the session it was paired in, which this host cannot name \u2014 run `paigy-harness handoff` as it, in its folder, to record it" };
35938
+ boundElsewhere.set(token, Date.now() + BOUND_ELSEWHERE_MS);
35939
+ return { skip: BOUND_SKIP };
35451
35940
  }
35452
35941
  return { skip: `could not read what is waiting (${error.message})` };
35453
35942
  }
35943
+ boundElsewhere.delete(token);
35454
35944
  const next = found.claimable;
35455
35945
  const about = next ? { goalId: next.goalId, ...next.since ? { since: next.since } : {} } : {};
35456
35946
  const n = found.deliveries.length;
35457
35947
  if (n) return { waiting: n === 1 ? "a message" : `${n} messages`, ...about };
35458
35948
  return next ? { waiting: `Goal ${next.goalId.slice(0, 8)}${next.title ? ` "${next.title}"` : ""}`, ...about } : { skip: NOTHING_WAITING };
35459
35949
  }
35460
- function evict(runs, key, run) {
35461
- if (runs.get(key)?.run === run) runs.delete(key);
35950
+ function evict(runs, key3, run) {
35951
+ if (runs.get(key3)?.run === run) runs.delete(key3);
35462
35952
  }
35463
35953
  var PRESENCE_FRESH_MS = 3 * 6e4;
35464
35954
  var IDLE_HOLDER_MS = 30 * 6e4;
@@ -35501,9 +35991,9 @@ function startHost(opts) {
35501
35991
  const agent2 = slotIdentity(slot).tokenId;
35502
35992
  if (!agent2) return;
35503
35993
  const goalId = found?.goalId;
35504
- const key = `${decision}:${goalId ?? ""}`;
35505
- if (recorded.get(slot) === key) return;
35506
- recorded.set(slot, key);
35994
+ const key3 = `${decision}:${goalId ?? ""}`;
35995
+ if (recorded.get(slot) === key3) return;
35996
+ recorded.set(slot, key3);
35507
35997
  void recordDecision({
35508
35998
  agent: agent2,
35509
35999
  decision,
@@ -35553,7 +36043,7 @@ function startHost(opts) {
35553
36043
  const specs = await claimSessions(asHost).catch(() => []);
35554
36044
  for (const spec of specs) {
35555
36045
  const label = spec.name ?? spec.harness;
35556
- const { slot, key } = claimedRun(spec.sessionId);
36046
+ const { slot, key: key3 } = claimedRun(spec.sessionId);
35557
36047
  const log = (line) => opts.log(`[${label}] ${line}`);
35558
36048
  try {
35559
36049
  saveToken({
@@ -35576,14 +36066,17 @@ function startHost(opts) {
35576
36066
  token: spec.token,
35577
36067
  ...launchRun(spec),
35578
36068
  onExit: () => {
35579
- evict(runs, key, run);
36069
+ evict(runs, key3, run);
35580
36070
  goneAt.set(slot, Date.now());
35581
36071
  opts.log(`\u2716 ${label} ended`);
35582
36072
  },
36073
+ onFull: (session) => {
36074
+ updateSlot(slot, { full_session: session });
36075
+ },
35583
36076
  name: label,
35584
36077
  log
35585
36078
  });
35586
- runs.set(key, { run, label, token: spec.token });
36079
+ runs.set(key3, { run, label, token: spec.token });
35587
36080
  void heartbeat(void 0, { token: spec.token }).catch(() => {
35588
36081
  });
35589
36082
  void refreshIdentities();
@@ -35635,9 +36128,9 @@ function startHost(opts) {
35635
36128
  let lastHolders = /* @__PURE__ */ new Map();
35636
36129
  async function wakeSlot(slot, { presence, holders }, cause = "sweep") {
35637
36130
  {
35638
- const key = runKey(slot);
36131
+ const key3 = runKey(slot);
35639
36132
  if (slot === "Desktop" || isRevoked(slot)) return;
35640
- const live = runs.get(key);
36133
+ const live = runs.get(key3);
35641
36134
  if (live) {
35642
36135
  const theirs = (localHolderPids().get(slot) ?? []).map((p) => p.pid).filter((pid) => !descendsFrom(pid, process.pid));
35643
36136
  if (theirs.length) {
@@ -35672,6 +36165,11 @@ function startHost(opts) {
35672
36165
  }
35673
36166
  const identity = slotIdentity(slot);
35674
36167
  const owner = !identity.harness || identity.harness === "claude" ? ownerSession(slot) : null;
36168
+ const resumes = owner?.sessionId ?? identity.sessionId;
36169
+ if (resumes && identity.fullSession === resumes) {
36170
+ skip(`has a full conversation (${resumes.slice(0, 8)}) \u2014 not resuming it; its Goals go to the dead-agent handoff`);
36171
+ return;
36172
+ }
35675
36173
  const read = async () => {
35676
36174
  const got = await waitingWork(token, identity.sessionId ?? owner?.sessionId);
35677
36175
  if (!("skip" in got)) return got;
@@ -35712,7 +36210,7 @@ function startHost(opts) {
35712
36210
  }
35713
36211
  found ??= await read() ?? void 0;
35714
36212
  if (!found) return;
35715
- if (runs.has(key)) {
36213
+ if (runs.has(key3)) {
35716
36214
  skip("was started by the wake that read it first");
35717
36215
  return;
35718
36216
  }
@@ -35728,14 +36226,17 @@ function startHost(opts) {
35728
36226
  // A dead run must not squat the slot — evict so the next wake can respawn. Only ITS entry:
35729
36227
  // a run that is no longer the slot's must not take the live one's place away with it.
35730
36228
  onExit: () => {
35731
- evict(runs, key, run);
36229
+ evict(runs, key3, run);
35732
36230
  goneAt.set(slot, Date.now());
35733
36231
  opts.log(`\u2716 ${label} ended`);
35734
36232
  },
36233
+ onFull: (session) => {
36234
+ updateSlot(slot, { full_session: session });
36235
+ },
35735
36236
  name: label,
35736
36237
  log
35737
36238
  });
35738
- runs.set(key, { run, label, token });
36239
+ runs.set(key3, { run, label, token });
35739
36240
  void heartbeat(void 0, { token }).catch(() => {
35740
36241
  });
35741
36242
  const woke = `\u25B6 ${owner ? "resumed" : "woke"} ${label} (${harness}) \u2014 ${found.waiting} was waiting, in ${workspace}${decided.why === "gone" ? " (its process here ended; its last heartbeat was not waited out)" : taking}`;
@@ -35788,17 +36289,17 @@ function startHost(opts) {
35788
36289
  void heartbeat(void 0, { token, activity: { lines: lines2, at: (/* @__PURE__ */ new Date()).toISOString() } }).catch(() => {
35789
36290
  });
35790
36291
  };
35791
- for (const [key, r] of runs) {
36292
+ for (const [key3, r] of runs) {
35792
36293
  if (!r.token) continue;
35793
36294
  const lines2 = r.run.tail();
35794
- const was = published.get(key);
36295
+ const was = published.get(key3);
35795
36296
  if (was && sameTail(was.lines, lines2)) continue;
35796
- published.set(key, { token: r.token, lines: lines2 });
36297
+ published.set(key3, { token: r.token, lines: lines2 });
35797
36298
  publishTail(r.token, lines2);
35798
36299
  }
35799
- for (const [key, was] of published) {
35800
- if (runs.has(key)) continue;
35801
- published.delete(key);
36300
+ for (const [key3, was] of published) {
36301
+ if (runs.has(key3)) continue;
36302
+ published.delete(key3);
35802
36303
  if (was.lines.length > 0) publishTail(was.token, []);
35803
36304
  }
35804
36305
  };
@@ -35829,25 +36330,25 @@ function startHost(opts) {
35829
36330
  })));
35830
36331
  };
35831
36332
  const api = {
35832
- sessions: () => [...runs.entries()].map(([id, r]) => [id, r.label]),
36333
+ sessions: () => [...runs.entries()].map(([id3, r]) => [id3, r.label]),
35833
36334
  // Every identity this machine holds, plus what it's doing right now. Slots are the
35834
36335
  // roster (hatched agents, the terminal tools, claimed sessions); a run makes one of
35835
36336
  // them live, and a run mid-turn makes it working.
35836
36337
  roster: () => {
35837
36338
  const live = new Map([...runs.values()].map((r) => [r.label, r.run]));
35838
36339
  const names2 = /* @__PURE__ */ new Map();
35839
- for (const key of listSlots()) if (key !== "Desktop" && !isRevoked(key)) names2.set(slotName(key) ?? key, key);
36340
+ for (const key3 of listSlots()) if (key3 !== "Desktop" && !isRevoked(key3)) names2.set(slotName(key3) ?? key3, key3);
35840
36341
  for (const label of live.keys()) if (!names2.has(label)) names2.set(label, null);
35841
36342
  return [...names2.entries()].map(([name, slot]) => {
35842
- const id = slot ? slotIdentity(slot) : { voice: null, tokenId: null };
36343
+ const id3 = slot ? slotIdentity(slot) : { voice: null, tokenId: null };
35843
36344
  return {
35844
36345
  name,
35845
36346
  // The slot key rides along so the window's agent page can speak AS this agent —
35846
36347
  // its pending reads (`checkReplies`, the same pure read the sweep does) need the
35847
36348
  // slot's own token, and the display name is not a key.
35848
36349
  slot,
35849
- tokenId: id.tokenId,
35850
- voice: id.voice,
36350
+ tokenId: id3.tokenId,
36351
+ voice: id3.voice,
35851
36352
  // RUNNING IS ABOUT THE IDENTITY, NOT ABOUT US (owner, 2026-09-14). This was
35852
36353
  // `live.has(name)` — "this host spawned it and it has not exited" — which is a fact
35853
36354
  // about our own process table, not about the agent. An ordinary terminal session
@@ -35855,7 +36356,7 @@ function startHost(opts) {
35855
36356
  // sessions we started ourselves. The server already knows: `last_seen_at` on the
35856
36357
  // agent's own token, the same evidence `wakeAction` stands back for. So: a run we
35857
36358
  // hold, OR a process the server heard from inside `PRESENCE_FRESH_MS`.
35858
- running: live.has(name) || !!slot && lastHolders.has(slot) || !!id.tokenId && Date.now() - (lastPresence.get(id.tokenId) ?? 0) < PRESENCE_FRESH_MS,
36359
+ running: live.has(name) || !!slot && lastHolders.has(slot) || !!id3.tokenId && Date.now() - (lastPresence.get(id3.tokenId) ?? 0) < PRESENCE_FRESH_MS,
35859
36360
  // `working` stays ours alone — it means a run WE hold is mid-turn, which is the only
35860
36361
  // thing a tail can tell us. A process we did not spawn has no tail here to read.
35861
36362
  working: live.get(name)?.working() ?? false
@@ -35976,20 +36477,14 @@ async function pairThisMachine() {
35976
36477
  }
35977
36478
  }
35978
36479
  function forwardCodexThreadId() {
35979
- const cfg = join10(process.env.CODEX_HOME || join10(homedir10(), ".codex"), "config.toml");
36480
+ const cfg = join11(process.env.CODEX_HOME || join11(homedir10(), ".codex"), "config.toml");
35980
36481
  if (!existsSync5(cfg)) return;
35981
- const text = readFileSync6(cfg, "utf8");
35982
- const head = "[mcp_servers.paigy]\n";
35983
- const at = text.indexOf(head);
35984
- if (at < 0) return;
35985
- const block2 = text.slice(at + head.length, (() => {
35986
- const n = text.indexOf("\n[", at + head.length);
35987
- return n < 0 ? text.length : n;
35988
- })());
35989
- if (/^\s*env_vars\s*=/m.test(block2)) return;
35990
- writeFileSync5(cfg, text.slice(0, at + head.length) + 'env_vars = ["CODEX_THREAD_ID", "CODEX_SESSION_ID"]\n' + text.slice(at + head.length));
36482
+ const text = readFileSync7(cfg, "utf8");
36483
+ const updated = withCodexEnv(text);
36484
+ if (updated !== null && updated !== text) writeFileSync5(cfg, updated);
35991
36485
  }
35992
36486
  async function main() {
36487
+ setClient(`harness@${VERSION}`);
35993
36488
  const parsed = parseArgs(process.argv.slice(2));
35994
36489
  if ("error" in parsed) {
35995
36490
  console.error(`paigy-harness: ${parsed.error}`);
@@ -36005,6 +36500,7 @@ async function main() {
36005
36500
  console.log(" service install the host as a login service (macOS)");
36006
36501
  console.log(" enable-tools allowlist Paigy's tools in Claude Code so they don't prompt each time");
36007
36502
  console.log(" hatch NAME mint a sibling identity from this machine's credential");
36503
+ console.log(' launch NAME "brief" start a helper session with its own identity and its brief as its first Goal [--under GOAL]');
36008
36504
  console.log(" handoff pin this terminal's identity here so your phone can resume it");
36009
36505
  console.log(" triage sweep your whole note queue with a model on THIS machine and");
36010
36506
  console.log(" send grouped suggestions to your phone (close / stale / assign)");
@@ -36078,7 +36574,7 @@ async function main() {
36078
36574
  const wsDeps = { file: workspacesFile() };
36079
36575
  for (const dir of parsed.grant) addWorkspace(dir, wsDeps);
36080
36576
  if (!listWorkspaces(wsDeps).length) {
36081
- const guess = join10(homedir10(), "projects");
36577
+ const guess = join11(homedir10(), "projects");
36082
36578
  if (existsSync5(guess)) {
36083
36579
  addWorkspace(guess, wsDeps);
36084
36580
  console.log(`\u2713 workspace granted: ${guess} (change with --grant DIR)`);
@@ -36110,9 +36606,9 @@ async function main() {
36110
36606
  }
36111
36607
  }
36112
36608
  try {
36113
- const settings = join10(homedir10(), ".claude", "settings.json");
36609
+ const settings = join11(homedir10(), ".claude", "settings.json");
36114
36610
  if (which("claude") && existsSync5(settings)) {
36115
- const cfg = JSON.parse(readFileSync6(settings, "utf8"));
36611
+ const cfg = JSON.parse(readFileSync7(settings, "utf8"));
36116
36612
  if (!cfg["statusLine"]) {
36117
36613
  cfg["statusLine"] = { type: "command", command: "npx -y -p @paigy/mcp@latest paigy-statusline" };
36118
36614
  writeFileSync5(settings, JSON.stringify(cfg, null, 2));
@@ -36168,13 +36664,13 @@ async function main() {
36168
36664
  <key>SoftResourceLimits</key><dict>
36169
36665
  <key>NumberOfFiles</key><integer>65536</integer>
36170
36666
  </dict>
36171
- <key>StandardOutPath</key><string>${join10(homedir10(), ".paigy", "host.log")}</string>
36172
- <key>StandardErrorPath</key><string>${join10(homedir10(), ".paigy", "host.log")}</string>
36667
+ <key>StandardOutPath</key><string>${join11(homedir10(), ".paigy", "host.log")}</string>
36668
+ <key>StandardErrorPath</key><string>${join11(homedir10(), ".paigy", "host.log")}</string>
36173
36669
  </dict></plist>
36174
36670
  `;
36175
- const dir = join10(homedir10(), "Library", "LaunchAgents");
36671
+ const dir = join11(homedir10(), "Library", "LaunchAgents");
36176
36672
  mkdirSync4(dir, { recursive: true });
36177
- const path = join10(dir, `${SERVICE_LABEL}.plist`);
36673
+ const path = join11(dir, `${SERVICE_LABEL}.plist`);
36178
36674
  writeFileSync5(path, plist);
36179
36675
  execSync(`launchctl unload ${path} 2>/dev/null; launchctl load ${path}`, { shell: "/bin/sh" });
36180
36676
  console.log(`\u2713 host installed as a login service (${path}) \u2014 logs at ~/.paigy/host.log`);
@@ -36219,7 +36715,7 @@ async function main() {
36219
36715
  return;
36220
36716
  }
36221
36717
  if (parsed.hatch) {
36222
- overrideToken(readToken("Desktop") || null);
36718
+ overrideToken(readSlot("Desktop") || null);
36223
36719
  const minted = await hatch(parsed.hatch, parsed.voice ?? null);
36224
36720
  saveToken({ access_token: minted.token, name: minted.name ?? parsed.hatch, device: null }, parsed.slot ?? minted.name ?? parsed.hatch);
36225
36721
  if (!minted.name) {
@@ -36227,8 +36723,7 @@ async function main() {
36227
36723
  return;
36228
36724
  }
36229
36725
  console.log(`\u2713 hatched "${minted.name}" \u2014 it's on your phone's Agents screen now.`);
36230
- console.log(` speak as it: PAIGY_AGENT="${minted.name}" <any paigy tool>`);
36231
- console.log(` run with it: paigy-harness --identity "${minted.name}" --harness codex "\u2026"`);
36726
+ console.log(` start a helper with its own session instead: paigy-harness launch "<name>" "<brief>"`);
36232
36727
  return;
36233
36728
  }
36234
36729
  if (parsed.host) {
@@ -36246,21 +36741,27 @@ async function main() {
36246
36741
  });
36247
36742
  return;
36248
36743
  }
36249
- let identityToken;
36250
- if (parsed.identity) {
36251
- const slot = readToken(parsed.identity);
36252
- if (!slot) {
36253
- console.error(`No slot for "${parsed.identity}" \u2014 hatch it first: paigy-harness hatch "${parsed.identity}"`);
36254
- process.exit(1);
36255
- }
36256
- identityToken = slot;
36257
- }
36258
36744
  const state = detectAll().find((a) => a.name === parsed.harness);
36259
36745
  if (state && state.status !== "ready") {
36260
36746
  const hint = state.hint ?? "setup incomplete";
36261
36747
  console.error(`\u270B ${state.label}: ${hint}`);
36262
36748
  process.exit(1);
36263
36749
  }
36750
+ let launched;
36751
+ if (parsed.launch) {
36752
+ overrideToken(readSlot("Desktop") || null);
36753
+ const session = randomUUID7();
36754
+ const minted = await hatch(parsed.launch, parsed.voice ?? null, {
36755
+ reach: reachAs(session),
36756
+ brief: parsed.prompt,
36757
+ ...parsed.under ? { parentGoalId: parsed.under } : {}
36758
+ }).catch((e) => {
36759
+ console.error(`\u270B the helper was not launched: ${e.message}`);
36760
+ process.exit(1);
36761
+ }).finally(() => overrideToken(null));
36762
+ launched = { token: minted.token, session, ...minted.goalId ? { goalId: minted.goalId } : {} };
36763
+ console.log(`\u2713 launched "${minted.name ?? parsed.launch}"${minted.name ? "" : " (unnamed: you already have an agent with that name)"}, on its own session; its Goal is ${minted.goalId ?? "missing"}`);
36764
+ }
36264
36765
  const askTerminal = async (promptText) => {
36265
36766
  if (parsed.graceSeconds <= 0 || !process.stdin.isTTY) return null;
36266
36767
  const readline = await import("readline/promises");
@@ -36281,9 +36782,10 @@ async function main() {
36281
36782
  harness: parsed.harness,
36282
36783
  cwd: parsed.cwd,
36283
36784
  mode: parsed.mode,
36284
- prompt: parsed.prompt,
36785
+ // hatch already admitted this brief; the pump must not admit it again after completion.
36786
+ prompt: launched ? "" : parsed.prompt,
36285
36787
  ...state?.bin ? { bin: state.bin } : {},
36286
- ...identityToken ? { token: identityToken } : {},
36788
+ ...launched ? { token: launched.token, session: launched.session } : {},
36287
36789
  localAsk: {
36288
36790
  permission: async (summary) => {
36289
36791
  const said = await askTerminal(`\u23F8 blocked: ${summary} \u2014 allow? [y/n]`);
@@ -36295,7 +36797,7 @@ async function main() {
36295
36797
  });
36296
36798
  const beat2 = async () => {
36297
36799
  try {
36298
- await heartbeat();
36800
+ await heartbeat(void 0, launched ? { token: launched.token } : {});
36299
36801
  signedOut = false;
36300
36802
  } catch (e) {
36301
36803
  if (!isUnauthorized(e) || signedOut) return;