@paigy/harness 0.3.34 → 0.3.35

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 (3) hide show
  1. package/dist/cli.js +239 -120
  2. package/dist/main.js +237 -118
  3. package/package.json +1 -1
package/dist/main.js CHANGED
@@ -1930,27 +1930,27 @@ var require_chunkstream = __commonJS({
1930
1930
  this._buffers = null;
1931
1931
  this.emit("close");
1932
1932
  };
1933
- ChunkStream.prototype._processReadAllowingLess = function(read) {
1933
+ ChunkStream.prototype._processReadAllowingLess = function(read3) {
1934
1934
  this._reads.shift();
1935
1935
  let smallerBuf = this._buffers[0];
1936
- if (smallerBuf.length > read.length) {
1937
- this._buffered -= read.length;
1938
- this._buffers[0] = smallerBuf.slice(read.length);
1939
- read.func.call(this, smallerBuf.slice(0, read.length));
1936
+ if (smallerBuf.length > read3.length) {
1937
+ this._buffered -= read3.length;
1938
+ this._buffers[0] = smallerBuf.slice(read3.length);
1939
+ read3.func.call(this, smallerBuf.slice(0, read3.length));
1940
1940
  } else {
1941
1941
  this._buffered -= smallerBuf.length;
1942
1942
  this._buffers.shift();
1943
- read.func.call(this, smallerBuf);
1943
+ read3.func.call(this, smallerBuf);
1944
1944
  }
1945
1945
  };
1946
- ChunkStream.prototype._processRead = function(read) {
1946
+ ChunkStream.prototype._processRead = function(read3) {
1947
1947
  this._reads.shift();
1948
1948
  let pos = 0;
1949
1949
  let count = 0;
1950
- let data = Buffer.alloc(read.length);
1951
- while (pos < read.length) {
1950
+ let data = Buffer.alloc(read3.length);
1951
+ while (pos < read3.length) {
1952
1952
  let buf = this._buffers[count++];
1953
- let len = Math.min(buf.length, read.length - pos);
1953
+ let len = Math.min(buf.length, read3.length - pos);
1954
1954
  buf.copy(data, pos, 0, len);
1955
1955
  pos += len;
1956
1956
  if (len !== buf.length) {
@@ -1960,17 +1960,17 @@ var require_chunkstream = __commonJS({
1960
1960
  if (count > 0) {
1961
1961
  this._buffers.splice(0, count);
1962
1962
  }
1963
- this._buffered -= read.length;
1964
- read.func.call(this, data);
1963
+ this._buffered -= read3.length;
1964
+ read3.func.call(this, data);
1965
1965
  };
1966
1966
  ChunkStream.prototype._process = function() {
1967
1967
  try {
1968
1968
  while (this._buffered > 0 && this._reads && this._reads.length > 0) {
1969
- let read = this._reads[0];
1970
- if (read.allowLess) {
1971
- this._processReadAllowingLess(read);
1972
- } else if (this._buffered >= read.length) {
1973
- this._processRead(read);
1969
+ let read3 = this._reads[0];
1970
+ if (read3.allowLess) {
1971
+ this._processReadAllowingLess(read3);
1972
+ } else if (this._buffered >= read3.length) {
1973
+ this._processRead(read3);
1974
1974
  } else {
1975
1975
  break;
1976
1976
  }
@@ -3595,12 +3595,12 @@ var require_sync_reader = __commonJS({
3595
3595
  };
3596
3596
  SyncReader.prototype.process = function() {
3597
3597
  while (this._reads.length > 0 && this._buffer.length) {
3598
- let read = this._reads[0];
3599
- if (this._buffer.length && (this._buffer.length >= read.length || read.allowLess)) {
3598
+ let read3 = this._reads[0];
3599
+ if (this._buffer.length && (this._buffer.length >= read3.length || read3.allowLess)) {
3600
3600
  this._reads.shift();
3601
3601
  let buf = this._buffer;
3602
- this._buffer = buf.slice(read.length);
3603
- read.func.call(this, buf.slice(0, read.length));
3602
+ this._buffer = buf.slice(read3.length);
3603
+ read3.func.call(this, buf.slice(0, read3.length));
3604
3604
  } else {
3605
3605
  break;
3606
3606
  }
@@ -9995,9 +9995,17 @@ var StartContactSchema = external_exports.object({
9995
9995
  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."),
9996
9996
  channel: external_exports.enum(["notification", "call"]).default("notification")
9997
9997
  }).strict();
9998
- var ContactSchema = external_exports.union([StartContactSchema, external_exports.object({ deliveryId: external_exports.string().uuid() }).strict()]);
9998
+ var ReceiveContactSchema = external_exports.object({
9999
+ wait: external_exports.boolean().optional().describe(
10000
+ "Only controls when this returns. true (the default when you send and acknowledge nothing): wait up to about 45 seconds for incoming communication addressed to you, and return as soon as some is available. false: return what is waiting now. It does not mean work is blocked, set urgency, or ask for a call. `waitOutcome` says which happened: `available`, `expired` (nothing arrived in the window; wait again without sending again), or `not_waited` (a hosted connection never holds a wait)."
10001
+ ),
10002
+ ackEventIds: external_exports.array(external_exports.string().uuid()).min(1).max(100).optional().describe(
10003
+ "The exact eventIds of the events you have handled: an acknowledgment (ACK). Reading alone acknowledges nothing, so an event comes back until you acknowledge it; after that the next batch can come. Each recipient acknowledges separately, for itself only. A Question you owe is answered (an ask with `answers`), never acknowledged away: that id is refused until it is answered."
10004
+ )
10005
+ }).strict();
10006
+ var ContactSchema = external_exports.union([StartContactSchema, external_exports.object({ deliveryId: external_exports.string().uuid() }).strict(), ReceiveContactSchema]);
9999
10007
  var CONTACT_SCHEMA = { type: "object", ...mcpInputSchema(ContactSchema) };
10000
- var 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.";
10008
+ var 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 answers by receiving (below). 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, never a claim on them, so no answer is owed and none should be awaited. A report reaches the person only when it answers something they asked you, or once the Goal is done; any other report is recorded as the Goal's progress and nobody is notified. So when the work is finished, mark the Goal done first, then send one message saying what is done and anything they need to do or check. On a Goal whose report card is still open, a report that does reach them is added to that card, with no new push. 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, a contact that reaches them 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.\n\nRECEIVING: contact with no asks sends nothing and returns `events`, a limited batch of what is addressed to you (not a history page): `question`, a Question you owe (answer it with an ask whose `answers` is its questionId); `update`, something new on one of your Goals (a reply, an answer: read it with get_goal); `instruction`, a request or note sent to you. `hasMore` says more are waiting. Reading acknowledges nothing: once you have handled events, confirm their eventIds with contact({ackEventIds}), and the next batch can come. contact({}) waits up to about 45 seconds for something to arrive; contact({wait:false}) returns at once. It also lists work given to you that nobody has started (`assigned`; claim_goal starts it) and your work gone quiet (`stalled`).";
10001
10009
  var CreateGoalSchema = external_exports.object({
10002
10010
  outcome: external_exports.string().trim().min(1).max(1e4),
10003
10011
  /** The work's NAME (#2115) — one to five words, how a person refers to it out loud ("the night
@@ -10017,10 +10025,6 @@ var CreateGoalSchema = external_exports.object({
10017
10025
  * repo name. Delegated work inherits this from its parent Goal when omitted. */
10018
10026
  repo: external_exports.string().trim().min(1).max(200).optional()
10019
10027
  });
10020
- var CreateGoalToolSchema = CreateGoalSchema.extend({
10021
- idempotencyKey: CreateGoalSchema.shape.idempotencyKey.optional().describe("Optional. One is minted per call; pass your own only so a retry lands on the same Goal.")
10022
- }).strict();
10023
- var 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.';
10024
10028
  var UpdateGoalSchema = external_exports.object({
10025
10029
  revision: external_exports.number().int().positive(),
10026
10030
  changes: external_exports.object({
@@ -10044,7 +10048,65 @@ var UpdateGoalSchema = external_exports.object({
10044
10048
  reason: external_exports.string().trim().min(1).max(2e3),
10045
10049
  operationId: external_exports.string().uuid().optional()
10046
10050
  }).strict();
10047
- var UpdateGoalToolSchema = UpdateGoalSchema.omit({ operationId: true }).extend({ goalId: external_exports.string().uuid() }).strict();
10051
+ var UpdateGoalToolSchema = external_exports.object({
10052
+ goalId: external_exports.string().uuid(),
10053
+ revision: UpdateGoalSchema.shape.revision,
10054
+ changes: UpdateGoalSchema.shape.changes.innerType().pick({ progress: true, reviewed: true, dueAt: true, withdraw: true }).strict().refine((v) => Object.keys(v).length > 0),
10055
+ reason: UpdateGoalSchema.shape.reason
10056
+ }).strict();
10057
+ var changedGoal = external_exports.string().uuid().describe("The Goal to change, as a read shows it.");
10058
+ var goalTitle = external_exports.string().trim().min(1).max(80).describe("The Goal's short display name: one to five words, how a person refers to it out loud.");
10059
+ var goalOutcome = external_exports.string().trim().min(1).max(1e4).describe("The full desired result. There is no third description field.");
10060
+ var CreateChange = external_exports.object({
10061
+ kind: external_exports.literal("create"),
10062
+ title: goalTitle,
10063
+ outcome: goalOutcome,
10064
+ ownerId: external_exports.string().trim().min(1).optional().describe("Who owns the work: an agent's participant (as who_is_working shows it) or the person's. Omitted: you."),
10065
+ parentGoalId: external_exports.string().uuid().optional().describe("The Goal it belongs under. Omitted: a root."),
10066
+ sourceEntryIds: external_exports.array(external_exports.string().uuid()).max(20).optional().describe("The whole Entries the work came from, ones you can read.")
10067
+ }).strict();
10068
+ var EditChange = external_exports.object({ kind: external_exports.literal("edit"), goalId: changedGoal, title: goalTitle.optional(), outcome: goalOutcome.optional() }).strict();
10069
+ var StateChange = external_exports.object({ kind: external_exports.literal("state"), goalId: changedGoal, state: external_exports.enum(["open", "completed", "canceled"]).describe(
10070
+ "completed: the Goal's own work is done now (refused while required children are open); open: reopen it; canceled: it will not be done."
10071
+ ) }).strict();
10072
+ var AssignChange = external_exports.object({ kind: external_exports.literal("assign"), goalId: changedGoal, ownerId: external_exports.string().trim().min(1).describe("The new owner's participant.") }).strict();
10073
+ var DeferChange = external_exports.object({ kind: external_exports.literal("defer"), goalId: changedGoal, until: external_exports.string().datetime({ offset: true }).nullable().describe(
10074
+ "Postpone it until this instant (its owner is woken then), or null to take the postponement back."
10075
+ ) }).strict();
10076
+ var MoveChange = external_exports.object({ kind: external_exports.literal("move"), goalId: changedGoal, parentGoalId: external_exports.string().uuid().nullable().describe(
10077
+ "Its new parent, or null for a root. Only this Goal moves; its new parent's other children stay."
10078
+ ) }).strict();
10079
+ var DependencyChange = external_exports.object({
10080
+ kind: external_exports.literal("dependency"),
10081
+ change: external_exports.enum(["add", "remove"]),
10082
+ goalId: changedGoal,
10083
+ dependsOnGoalId: external_exports.string().uuid().describe("The Goal it waits on."),
10084
+ action: external_exports.enum(["start", "complete"]).describe("What waits: starting goalId, or completing it."),
10085
+ reason: external_exports.string().trim().min(1).max(2e3).optional().describe("Why, as an explanation, never as policy.")
10086
+ }).strict();
10087
+ var read = { revision: external_exports.number().int().positive().optional() };
10088
+ var GoalChangeSchema = external_exports.discriminatedUnion("kind", [
10089
+ CreateChange,
10090
+ EditChange.extend(read),
10091
+ StateChange.extend(read),
10092
+ AssignChange.extend(read),
10093
+ DeferChange.extend(read),
10094
+ MoveChange.extend(read),
10095
+ DependencyChange
10096
+ ]);
10097
+ var editNames = (changes, ctx) => changes.forEach((c, i) => {
10098
+ if (c.kind === "edit" && c.title === void 0 && c.outcome === void 0) {
10099
+ ctx.addIssue({ code: external_exports.ZodIssueCode.custom, path: ["changes", i], message: "an edit supplies title, outcome, or both" });
10100
+ }
10101
+ });
10102
+ var ManageGoalsSchema = external_exports.object({
10103
+ requestId: external_exports.string().uuid().optional(),
10104
+ changes: external_exports.array(GoalChangeSchema).min(1).max(50)
10105
+ }).strict().superRefine((v, ctx) => editNames(v.changes, ctx));
10106
+ var ManageGoalsToolSchema = external_exports.object({
10107
+ changes: external_exports.array(external_exports.discriminatedUnion("kind", [CreateChange, EditChange, StateChange, AssignChange, DeferChange, MoveChange, DependencyChange])).min(1).max(50).describe("The changes, applied in order, each on its own.")
10108
+ }).strict().superRefine((v, ctx) => editNames(v.changes, ctx));
10109
+ var MANAGE_GOALS_DESCRIPTION = "Create, edit, assign, organize or close work. Every change here changes Goals; answering, withdrawing or asking Questions stays in contact. Each change applies independently: a refused one names why (`results[i].error`, e.g. goal_revision_conflict, goal_children_open, goal_not_joined, goal_not_found) and the rest still apply, so read every result: a partial result is never a complete success. Kinds: create (title, outcome, ownerId, parentGoalId, sourceEntryIds) returns the new Goal's id in `results[i].goalId`, in the order requested, to use in later calls; edit (title and/or outcome); state (open, completed, canceled); assign (ownerId); defer (until, or null); move (parentGoalId, or null for a root: only this Goal moves); dependency (add or remove: goalId waits on dependsOnGoalId to start or to complete). A Goal cannot be completed while its required children or dependencies remain open: finish or move them first. Finishing the children does not prove the parent's own work is done. An edit applies at the version you last read: if someone changed the Goal since, it is refused as goal_revision_conflict, so read it again (get_goal) and reconsider. You may change a Goal you own or have written on. Returns `ok` (every change applied), `results` per change (applied or failed), and `goals`, each changed Goal's id, state, title, outcome and revision.";
10048
10110
  var ClaimGoalSchema = external_exports.object({ goalId: external_exports.string().uuid().optional() }).strict();
10049
10111
  var GetGoalSchema = external_exports.object({
10050
10112
  goalId: external_exports.string().uuid(),
@@ -10057,18 +10119,24 @@ var GetGoalSchema = external_exports.object({
10057
10119
  diagnose: external_exports.boolean().optional()
10058
10120
  }).strict();
10059
10121
  var 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.";
10060
- var 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.`;
10061
- var 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).";
10062
- var 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.";
10063
- var CheckRepliesSchema = external_exports.object({}).strict();
10122
+ var UPDATE_GOAL_DESCRIPTION = "Report work on a Goal you are on, at an exact revision: progress, review acknowledgement, when to wake for it, and withdrawing a question of yours. What the Goal is (its title, outcome, state, owner, parent, dependencies) changes with manage_goals. 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). 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. progress says where the work stands. reviewed: true acknowledges new evidence and closes the Deliveries addressed to you on that Goal, never over an open decision (contact({ackEventIds}) does the same for an `update` event). 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. Returns the Goal as get_goal reads it, at its new revision.";
10123
+ var 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 it; use manage_goals (assign) 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).";
10124
+ var SearchToolSchema = external_exports.object({
10125
+ query: external_exports.string().trim().min(1).max(500),
10126
+ types: external_exports.array(external_exports.enum(["entry", "goal", "answer"])).min(1).optional(),
10127
+ goalId: external_exports.string().uuid().optional(),
10128
+ limit: external_exports.number().int().min(1).max(20).optional()
10129
+ }).strict();
10130
+ var SEARCH_DESCRIPTION = "Search your person's history across all of their agents: Entries (what anyone said or wrote, typed or spoken on a call), Goals (by title and outcome) and Answers (found by their Question or by the words that gave them). query is words to look for; records sharing more of its words rank first, and exact names work. types narrows it to entry, goal and/or answer (default: all three). goalId searches under one Goal: its Entries, its Questions' Answers, and it and its immediate children. limit is matches per type, 1 to 20 (default 8). Read-only. Each match carries its whole saved words, its ID and its links (an Answer carries its Question, the choice made and the Entries that support it); `omitted` counts what matched but was left out, so narrow the words or add a goalId to see it. Nothing found is not proof that nothing exists; a refused search says why. Sealed (encrypted) content is never searched or returned.";
10131
+ var WhoIsWorkingSchema = external_exports.object({}).strict();
10064
10132
  var AGENT_TOOLS = [
10065
- { 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) },
10133
+ { 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(WhoIsWorkingSchema) },
10066
10134
  { name: "contact", description: CONTACT_DESCRIPTION, inputSchema: CONTACT_SCHEMA },
10067
- { name: "check_replies", description: CHECK_REPLIES_DESCRIPTION, inputSchema: mcpInputSchema(CheckRepliesSchema) },
10068
- { name: "create_goal", description: CREATE_GOAL_DESCRIPTION, inputSchema: mcpInputSchema(CreateGoalToolSchema) },
10135
+ { name: "manage_goals", description: MANAGE_GOALS_DESCRIPTION, inputSchema: mcpInputSchema(ManageGoalsToolSchema) },
10069
10136
  { name: "claim_goal", description: CLAIM_GOAL_DESCRIPTION, inputSchema: mcpInputSchema(ClaimGoalSchema) },
10070
10137
  { name: "get_goal", description: GET_GOAL_DESCRIPTION, inputSchema: mcpInputSchema(GetGoalSchema) },
10071
- { name: "update_goal", description: UPDATE_GOAL_DESCRIPTION, inputSchema: mcpInputSchema(UpdateGoalToolSchema) }
10138
+ { name: "update_goal", description: UPDATE_GOAL_DESCRIPTION, inputSchema: mcpInputSchema(UpdateGoalToolSchema) },
10139
+ { name: "search", description: SEARCH_DESCRIPTION, inputSchema: mcpInputSchema(SearchToolSchema) }
10072
10140
  ];
10073
10141
  var AGENT_TOOL_NAMES = AGENT_TOOLS.map((t) => t.name);
10074
10142
  var id = external_exports.string().uuid();
@@ -10099,17 +10167,6 @@ var existingGoalChanges = [
10099
10167
  reason: external_exports.string().max(500).optional()
10100
10168
  }).strict()
10101
10169
  ];
10102
- var GoalChangeSchema = external_exports.union([
10103
- external_exports.object({
10104
- kind: external_exports.literal("create"),
10105
- title: external_exports.string().min(1).max(120),
10106
- outcome: external_exports.string().min(1),
10107
- ownerId: participant,
10108
- parentGoalId: id.optional(),
10109
- sourceEntryIds: external_exports.array(id)
10110
- }).strict(),
10111
- ...existingGoalChanges
10112
- ]);
10113
10170
  var BrainGoalChangeSchema = external_exports.union([
10114
10171
  // newSession: Paigy starts a session to own it (owner, 2026-10-06); until it has, the person owns it.
10115
10172
  external_exports.object({
@@ -10493,7 +10550,7 @@ var AwaitItemSchema = external_exports.discriminatedUnion("type", [
10493
10550
  /** The awaited ask was REPLACED by a newer notification on its thread (e.g. a
10494
10551
  * post-feedback revision, #633) — the user will never answer this id. Stop
10495
10552
  * awaiting it; the live ask is the thread's newest turn (await that one, or
10496
- * re-orient via check_replies). */
10553
+ * re-orient via contact({})). */
10497
10554
  external_exports.object({
10498
10555
  type: external_exports.literal("superseded"),
10499
10556
  parentId: external_exports.string(),
@@ -11223,7 +11280,7 @@ var HostDecisionSchema = external_exports.object({
11223
11280
  goalId: external_exports.string().uuid().nullable().optional(),
11224
11281
  /** When the server last heard from the agent, as the host read it: the presence it stood back for. */
11225
11282
  seenAt: external_exports.string().datetime().nullable().optional(),
11226
- /** When that work last moved (`claimable.since` on `check_replies`), the fact the bound is judged on. */
11283
+ /** When that work last moved (`claimable.since` on an agent's `contact({})` read), the fact the bound is judged on. */
11227
11284
  since: external_exports.string().datetime().nullable().optional(),
11228
11285
  /** What the host said, in its log's own words: why it stood back, or what the take-over did. */
11229
11286
  said: external_exports.string().max(300).optional()
@@ -11566,28 +11623,28 @@ var authToken = (explicit) => explicit ?? tokenOverride ?? readToken();
11566
11623
  async function fail(what, res) {
11567
11624
  throw new ApiError(what, res.status, await res.text());
11568
11625
  }
11569
- async function createGoal(input, opts = {}) {
11626
+ async function manageGoals(input, opts = {}) {
11570
11627
  const token = authToken(opts.token) ?? "";
11571
- const res = await ensureAuthed(await (opts.reach ?? reach)(`${BACKEND_URL}/api/goals`, {
11628
+ const res = await ensureAuthed(await (opts.reach ?? reach)(`${BACKEND_URL}/api/goals/manage`, {
11572
11629
  method: "POST",
11573
- headers: { "content-type": "application/json", authorization: `Bearer ${token}`, "x-paigy-model": "goal-entry-v1" },
11630
+ headers: { "content-type": "application/json", authorization: `Bearer ${token}` },
11574
11631
  body: JSON.stringify(input)
11575
11632
  }));
11576
- if (!res.ok) await fail("create_goal", res);
11633
+ if (!res.ok) await fail("manage_goals", res);
11577
11634
  return await res.json();
11578
11635
  }
11579
11636
  async function claimGoal(goalId, opts = {}) {
11580
11637
  const token = authToken(opts.token) ?? "";
11581
- const res = await ensureAuthed(await (opts.reach ?? reach)(`${BACKEND_URL}/api/goals/claim`, { method: "POST", headers: { "content-type": "application/json", authorization: `Bearer ${token}`, "x-paigy-model": "goal-entry-v1" }, body: JSON.stringify(goalId ? { goalId } : {}) }));
11638
+ const res = await ensureAuthed(await (opts.reach ?? reach)(`${BACKEND_URL}/api/goals/claim`, { method: "POST", headers: { "content-type": "application/json", authorization: `Bearer ${token}` }, body: JSON.stringify(goalId ? { goalId } : {}) }));
11582
11639
  if (!res.ok) await fail("claim_goal", res);
11583
11640
  return await res.json();
11584
11641
  }
11585
- async function getGoal(goalId, opts = {}, read = {}) {
11642
+ async function getGoal(goalId, opts = {}, read3 = {}) {
11586
11643
  const token = authToken(opts.token) ?? "";
11587
- const query = [read.history ? "history=1" : "", read.diagnose ? "diagnose=1" : ""].filter(Boolean).join("&");
11644
+ const query = [read3.history ? "history=1" : "", read3.diagnose ? "diagnose=1" : ""].filter(Boolean).join("&");
11588
11645
  const res = await ensureAuthed(await (opts.reach ?? reach)(`${BACKEND_URL}/api/goals/${encodeURIComponent(goalId)}${query ? `?${query}` : ""}`, {
11589
11646
  method: "GET",
11590
- headers: { authorization: `Bearer ${token}`, "x-paigy-model": "goal-entry-v1" }
11647
+ headers: { authorization: `Bearer ${token}` }
11591
11648
  }));
11592
11649
  if (!res.ok) await fail("get_goal", res);
11593
11650
  return await res.json();
@@ -11595,7 +11652,7 @@ async function getGoal(goalId, opts = {}, read = {}) {
11595
11652
  async function updateGoal(goalId, input, opts = {}) {
11596
11653
  const token = authToken(opts.token) ?? "";
11597
11654
  const operationId = input.operationId ?? randomUUID2();
11598
- const res = await ensureAuthed(await (opts.reach ?? reach)(`${BACKEND_URL}/api/goals/${encodeURIComponent(goalId)}`, { method: "PATCH", headers: { "content-type": "application/json", authorization: `Bearer ${token}`, "x-paigy-model": "goal-entry-v1" }, body: JSON.stringify({ ...input, operationId }) }));
11655
+ const res = await ensureAuthed(await (opts.reach ?? reach)(`${BACKEND_URL}/api/goals/${encodeURIComponent(goalId)}`, { method: "PATCH", headers: { "content-type": "application/json", authorization: `Bearer ${token}` }, body: JSON.stringify({ ...input, operationId }) }));
11599
11656
  if (!res.ok) await fail("update_goal", res);
11600
11657
  return await res.json();
11601
11658
  }
@@ -11674,7 +11731,7 @@ async function listNotes(opts = {}) {
11674
11731
  }
11675
11732
  async function listConnections(opts = {}) {
11676
11733
  const res = await ensureAuthed(await reach(`${BACKEND_URL}/api/tokens`, {
11677
- headers: { authorization: `Bearer ${authToken(opts.token)}`, "x-paigy-model": "goal-entry-v1" }
11734
+ headers: { authorization: `Bearer ${authToken(opts.token)}` }
11678
11735
  }));
11679
11736
  if (!res.ok) throw new Error(`list_connections failed: ${res.status} ${await res.text()}`);
11680
11737
  return await res.json();
@@ -11738,13 +11795,14 @@ function currentRepo(cwd = process.cwd()) {
11738
11795
  }
11739
11796
  return asked;
11740
11797
  }
11741
- var 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.";
11798
+ var NOT_SENT = "Recorded as the Goal's progress, not sent: nobody was notified. The person is told only a question, an answer to one they asked you, and what you say once the Goal is done. To close the work, mark the Goal done first, then send the one message saying what is done and anything they need to do or check.";
11742
11799
  var 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.";
11743
11800
  async function contact(input, opts = {}) {
11744
11801
  const parsed = ContactSchema.parse(input);
11802
+ if (!("asks" in parsed) && !("deliveryId" in parsed)) throw new Error("contact with nothing to send receives: call receiveContact");
11745
11803
  opts.signal?.throwIfAborted();
11746
11804
  const send22 = opts.reach ?? reach;
11747
- const headers = { "content-type": "application/json", authorization: `Bearer ${authToken(opts.token) ?? ""}`, "x-paigy-model": "goal-entry-v1" };
11805
+ const headers = { "content-type": "application/json", authorization: `Bearer ${authToken(opts.token) ?? ""}` };
11748
11806
  let deliveryId;
11749
11807
  let deliveries = [];
11750
11808
  let recorded = [];
@@ -11789,7 +11847,7 @@ async function contact(input, opts = {}) {
11789
11847
  const all = deliveries.filter((d) => !!d.deliveryId && !!d.goalId).map(({ id: id22, deliveryId: deliveryId2, goalId }) => ({ ...id22 ? { id: id22 } : {}, deliveryId: deliveryId2, goalId }));
11790
11848
  const joinedCard = deliveries[0]?.joinedCard === true;
11791
11849
  const joinedCall = deliveries[0]?.joinedCall === true;
11792
- const read = async (signal2) => {
11850
+ const read3 = async (signal2) => {
11793
11851
  const res = await ensureAuthed(await send22(`${BACKEND_URL}/api/deliveries/${encodeURIComponent(deliveryId)}`, { headers, signal: signal2 }));
11794
11852
  if (!res.ok) await fail("read_delivery", res);
11795
11853
  const one = await res.json();
@@ -11803,14 +11861,14 @@ async function contact(input, opts = {}) {
11803
11861
  };
11804
11862
  };
11805
11863
  const settled = (d) => d.kind === "notification" || d.state === "closed" || d.answers.length > 0 || d.entries.some((e) => e.kind === "contribution");
11806
- if (opts.waits === false) return read(opts.signal);
11864
+ if (opts.waits === false) return read3(opts.signal);
11807
11865
  const window = AbortSignal.timeout(AWAIT_WINDOW_MS);
11808
11866
  const signal = opts.signal ? AbortSignal.any([opts.signal, window]) : window;
11809
11867
  let latest;
11810
11868
  try {
11811
11869
  while (true) {
11812
11870
  signal.throwIfAborted();
11813
- latest = await read(signal);
11871
+ latest = await read3(signal);
11814
11872
  if (settled(latest)) return latest;
11815
11873
  await sleep2(5e3, void 0, { signal });
11816
11874
  }
@@ -11820,11 +11878,11 @@ async function contact(input, opts = {}) {
11820
11878
  throw error;
11821
11879
  }
11822
11880
  }
11823
- async function checkReplies(opts = {}) {
11881
+ async function receive(opts = {}) {
11824
11882
  const res = await ensureAuthed(await (opts.reach ?? reach)(`${BACKEND_URL}/api/deliveries`, {
11825
- headers: { authorization: `Bearer ${authToken(opts.token) ?? ""}`, "x-paigy-model": "goal-entry-v1" }
11883
+ headers: { authorization: `Bearer ${authToken(opts.token) ?? ""}` }
11826
11884
  }));
11827
- if (!res.ok) await fail("check_replies", res);
11885
+ if (!res.ok) await fail("receive", res);
11828
11886
  return await res.json();
11829
11887
  }
11830
11888
  var HEARTBEAT_MS = 25e3;
@@ -12774,7 +12832,7 @@ function proven(pid, procStart, deps) {
12774
12832
  function localHolderPids(deps = {}) {
12775
12833
  const dir = deps.dir ?? join6(process.env.CLAUDE_CONFIG_DIR?.trim() || join6(homedir6(), ".claude"), "sessions");
12776
12834
  const list = deps.list ?? ((d) => readdirSync2(d));
12777
- const read = deps.read ?? ((f) => readFileSync4(f, "utf8"));
12835
+ const read3 = deps.read ?? ((f) => readFileSync4(f, "utf8"));
12778
12836
  const check = { alive: deps.alive ?? isAlive, started: deps.started ?? psStart };
12779
12837
  const held = /* @__PURE__ */ new Map();
12780
12838
  let files;
@@ -12787,7 +12845,7 @@ function localHolderPids(deps = {}) {
12787
12845
  if (!/^\d+\.json$/.test(file)) continue;
12788
12846
  let row;
12789
12847
  try {
12790
- row = JSON.parse(read(join6(dir, file)));
12848
+ row = JSON.parse(read3(join6(dir, file)));
12791
12849
  } catch {
12792
12850
  continue;
12793
12851
  }
@@ -12819,7 +12877,7 @@ function descendsFrom(pid, ancestor, parent = psParent) {
12819
12877
  function localHolders(deps = {}) {
12820
12878
  const dir = deps.dir ?? join6(process.env.CLAUDE_CONFIG_DIR?.trim() || join6(homedir6(), ".claude"), "sessions");
12821
12879
  const list = deps.list ?? ((d) => readdirSync2(d));
12822
- const read = deps.read ?? ((f) => readFileSync4(f, "utf8"));
12880
+ const read3 = deps.read ?? ((f) => readFileSync4(f, "utf8"));
12823
12881
  const check = { alive: deps.alive ?? isAlive, started: deps.started ?? psStart };
12824
12882
  const held = /* @__PURE__ */ new Map();
12825
12883
  let files;
@@ -12832,7 +12890,7 @@ function localHolders(deps = {}) {
12832
12890
  if (!/^\d+\.json$/.test(file)) continue;
12833
12891
  let row;
12834
12892
  try {
12835
- row = JSON.parse(read(join6(dir, file)));
12893
+ row = JSON.parse(read3(join6(dir, file)));
12836
12894
  } catch {
12837
12895
  continue;
12838
12896
  }
@@ -14317,9 +14375,17 @@ var StartContactSchema2 = external_exports.object({
14317
14375
  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."),
14318
14376
  channel: external_exports.enum(["notification", "call"]).default("notification")
14319
14377
  }).strict();
14320
- var ContactSchema2 = external_exports.union([StartContactSchema2, external_exports.object({ deliveryId: external_exports.string().uuid() }).strict()]);
14378
+ var ReceiveContactSchema2 = external_exports.object({
14379
+ wait: external_exports.boolean().optional().describe(
14380
+ "Only controls when this returns. true (the default when you send and acknowledge nothing): wait up to about 45 seconds for incoming communication addressed to you, and return as soon as some is available. false: return what is waiting now. It does not mean work is blocked, set urgency, or ask for a call. `waitOutcome` says which happened: `available`, `expired` (nothing arrived in the window; wait again without sending again), or `not_waited` (a hosted connection never holds a wait)."
14381
+ ),
14382
+ ackEventIds: external_exports.array(external_exports.string().uuid()).min(1).max(100).optional().describe(
14383
+ "The exact eventIds of the events you have handled: an acknowledgment (ACK). Reading alone acknowledges nothing, so an event comes back until you acknowledge it; after that the next batch can come. Each recipient acknowledges separately, for itself only. A Question you owe is answered (an ask with `answers`), never acknowledged away: that id is refused until it is answered."
14384
+ )
14385
+ }).strict();
14386
+ var ContactSchema2 = external_exports.union([StartContactSchema2, external_exports.object({ deliveryId: external_exports.string().uuid() }).strict(), ReceiveContactSchema2]);
14321
14387
  var CONTACT_SCHEMA2 = { type: "object", ...mcpInputSchema2(ContactSchema2) };
14322
- 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.";
14388
+ 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 answers by receiving (below). 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, never a claim on them, so no answer is owed and none should be awaited. A report reaches the person only when it answers something they asked you, or once the Goal is done; any other report is recorded as the Goal's progress and nobody is notified. So when the work is finished, mark the Goal done first, then send one message saying what is done and anything they need to do or check. On a Goal whose report card is still open, a report that does reach them is added to that card, with no new push. 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, a contact that reaches them 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.\n\nRECEIVING: contact with no asks sends nothing and returns `events`, a limited batch of what is addressed to you (not a history page): `question`, a Question you owe (answer it with an ask whose `answers` is its questionId); `update`, something new on one of your Goals (a reply, an answer: read it with get_goal); `instruction`, a request or note sent to you. `hasMore` says more are waiting. Reading acknowledges nothing: once you have handled events, confirm their eventIds with contact({ackEventIds}), and the next batch can come. contact({}) waits up to about 45 seconds for something to arrive; contact({wait:false}) returns at once. It also lists work given to you that nobody has started (`assigned`; claim_goal starts it) and your work gone quiet (`stalled`).";
14323
14389
  var CreateGoalSchema2 = external_exports.object({
14324
14390
  outcome: external_exports.string().trim().min(1).max(1e4),
14325
14391
  /** The work's NAME (#2115) — one to five words, how a person refers to it out loud ("the night
@@ -14339,10 +14405,6 @@ var CreateGoalSchema2 = external_exports.object({
14339
14405
  * repo name. Delegated work inherits this from its parent Goal when omitted. */
14340
14406
  repo: external_exports.string().trim().min(1).max(200).optional()
14341
14407
  });
14342
- var CreateGoalToolSchema2 = CreateGoalSchema2.extend({
14343
- idempotencyKey: CreateGoalSchema2.shape.idempotencyKey.optional().describe("Optional. One is minted per call; pass your own only so a retry lands on the same Goal.")
14344
- }).strict();
14345
- 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.';
14346
14408
  var UpdateGoalSchema2 = external_exports.object({
14347
14409
  revision: external_exports.number().int().positive(),
14348
14410
  changes: external_exports.object({
@@ -14366,7 +14428,65 @@ var UpdateGoalSchema2 = external_exports.object({
14366
14428
  reason: external_exports.string().trim().min(1).max(2e3),
14367
14429
  operationId: external_exports.string().uuid().optional()
14368
14430
  }).strict();
14369
- var UpdateGoalToolSchema2 = UpdateGoalSchema2.omit({ operationId: true }).extend({ goalId: external_exports.string().uuid() }).strict();
14431
+ var UpdateGoalToolSchema2 = external_exports.object({
14432
+ goalId: external_exports.string().uuid(),
14433
+ revision: UpdateGoalSchema2.shape.revision,
14434
+ changes: UpdateGoalSchema2.shape.changes.innerType().pick({ progress: true, reviewed: true, dueAt: true, withdraw: true }).strict().refine((v) => Object.keys(v).length > 0),
14435
+ reason: UpdateGoalSchema2.shape.reason
14436
+ }).strict();
14437
+ var changedGoal2 = external_exports.string().uuid().describe("The Goal to change, as a read shows it.");
14438
+ var goalTitle2 = external_exports.string().trim().min(1).max(80).describe("The Goal's short display name: one to five words, how a person refers to it out loud.");
14439
+ var goalOutcome2 = external_exports.string().trim().min(1).max(1e4).describe("The full desired result. There is no third description field.");
14440
+ var CreateChange2 = external_exports.object({
14441
+ kind: external_exports.literal("create"),
14442
+ title: goalTitle2,
14443
+ outcome: goalOutcome2,
14444
+ ownerId: external_exports.string().trim().min(1).optional().describe("Who owns the work: an agent's participant (as who_is_working shows it) or the person's. Omitted: you."),
14445
+ parentGoalId: external_exports.string().uuid().optional().describe("The Goal it belongs under. Omitted: a root."),
14446
+ sourceEntryIds: external_exports.array(external_exports.string().uuid()).max(20).optional().describe("The whole Entries the work came from, ones you can read.")
14447
+ }).strict();
14448
+ var EditChange2 = external_exports.object({ kind: external_exports.literal("edit"), goalId: changedGoal2, title: goalTitle2.optional(), outcome: goalOutcome2.optional() }).strict();
14449
+ var StateChange2 = external_exports.object({ kind: external_exports.literal("state"), goalId: changedGoal2, state: external_exports.enum(["open", "completed", "canceled"]).describe(
14450
+ "completed: the Goal's own work is done now (refused while required children are open); open: reopen it; canceled: it will not be done."
14451
+ ) }).strict();
14452
+ var AssignChange2 = external_exports.object({ kind: external_exports.literal("assign"), goalId: changedGoal2, ownerId: external_exports.string().trim().min(1).describe("The new owner's participant.") }).strict();
14453
+ var DeferChange2 = external_exports.object({ kind: external_exports.literal("defer"), goalId: changedGoal2, until: external_exports.string().datetime({ offset: true }).nullable().describe(
14454
+ "Postpone it until this instant (its owner is woken then), or null to take the postponement back."
14455
+ ) }).strict();
14456
+ var MoveChange2 = external_exports.object({ kind: external_exports.literal("move"), goalId: changedGoal2, parentGoalId: external_exports.string().uuid().nullable().describe(
14457
+ "Its new parent, or null for a root. Only this Goal moves; its new parent's other children stay."
14458
+ ) }).strict();
14459
+ var DependencyChange2 = external_exports.object({
14460
+ kind: external_exports.literal("dependency"),
14461
+ change: external_exports.enum(["add", "remove"]),
14462
+ goalId: changedGoal2,
14463
+ dependsOnGoalId: external_exports.string().uuid().describe("The Goal it waits on."),
14464
+ action: external_exports.enum(["start", "complete"]).describe("What waits: starting goalId, or completing it."),
14465
+ reason: external_exports.string().trim().min(1).max(2e3).optional().describe("Why, as an explanation, never as policy.")
14466
+ }).strict();
14467
+ var read2 = { revision: external_exports.number().int().positive().optional() };
14468
+ var GoalChangeSchema2 = external_exports.discriminatedUnion("kind", [
14469
+ CreateChange2,
14470
+ EditChange2.extend(read2),
14471
+ StateChange2.extend(read2),
14472
+ AssignChange2.extend(read2),
14473
+ DeferChange2.extend(read2),
14474
+ MoveChange2.extend(read2),
14475
+ DependencyChange2
14476
+ ]);
14477
+ var editNames2 = (changes, ctx) => changes.forEach((c, i) => {
14478
+ if (c.kind === "edit" && c.title === void 0 && c.outcome === void 0) {
14479
+ ctx.addIssue({ code: external_exports.ZodIssueCode.custom, path: ["changes", i], message: "an edit supplies title, outcome, or both" });
14480
+ }
14481
+ });
14482
+ var ManageGoalsSchema2 = external_exports.object({
14483
+ requestId: external_exports.string().uuid().optional(),
14484
+ changes: external_exports.array(GoalChangeSchema2).min(1).max(50)
14485
+ }).strict().superRefine((v, ctx) => editNames2(v.changes, ctx));
14486
+ var ManageGoalsToolSchema2 = external_exports.object({
14487
+ changes: external_exports.array(external_exports.discriminatedUnion("kind", [CreateChange2, EditChange2, StateChange2, AssignChange2, DeferChange2, MoveChange2, DependencyChange2])).min(1).max(50).describe("The changes, applied in order, each on its own.")
14488
+ }).strict().superRefine((v, ctx) => editNames2(v.changes, ctx));
14489
+ var MANAGE_GOALS_DESCRIPTION2 = "Create, edit, assign, organize or close work. Every change here changes Goals; answering, withdrawing or asking Questions stays in contact. Each change applies independently: a refused one names why (`results[i].error`, e.g. goal_revision_conflict, goal_children_open, goal_not_joined, goal_not_found) and the rest still apply, so read every result: a partial result is never a complete success. Kinds: create (title, outcome, ownerId, parentGoalId, sourceEntryIds) returns the new Goal's id in `results[i].goalId`, in the order requested, to use in later calls; edit (title and/or outcome); state (open, completed, canceled); assign (ownerId); defer (until, or null); move (parentGoalId, or null for a root: only this Goal moves); dependency (add or remove: goalId waits on dependsOnGoalId to start or to complete). A Goal cannot be completed while its required children or dependencies remain open: finish or move them first. Finishing the children does not prove the parent's own work is done. An edit applies at the version you last read: if someone changed the Goal since, it is refused as goal_revision_conflict, so read it again (get_goal) and reconsider. You may change a Goal you own or have written on. Returns `ok` (every change applied), `results` per change (applied or failed), and `goals`, each changed Goal's id, state, title, outcome and revision.";
14370
14490
  var ClaimGoalSchema2 = external_exports.object({ goalId: external_exports.string().uuid().optional() }).strict();
14371
14491
  var GetGoalSchema2 = external_exports.object({
14372
14492
  goalId: external_exports.string().uuid(),
@@ -14379,18 +14499,24 @@ var GetGoalSchema2 = external_exports.object({
14379
14499
  diagnose: external_exports.boolean().optional()
14380
14500
  }).strict();
14381
14501
  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.";
14382
- 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.`;
14383
- 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).";
14384
- 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.";
14385
- var CheckRepliesSchema2 = external_exports.object({}).strict();
14502
+ var UPDATE_GOAL_DESCRIPTION2 = "Report work on a Goal you are on, at an exact revision: progress, review acknowledgement, when to wake for it, and withdrawing a question of yours. What the Goal is (its title, outcome, state, owner, parent, dependencies) changes with manage_goals. 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). 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. progress says where the work stands. reviewed: true acknowledges new evidence and closes the Deliveries addressed to you on that Goal, never over an open decision (contact({ackEventIds}) does the same for an `update` event). 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. Returns the Goal as get_goal reads it, at its new revision.";
14503
+ 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 it; use manage_goals (assign) 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).";
14504
+ var SearchToolSchema2 = external_exports.object({
14505
+ query: external_exports.string().trim().min(1).max(500),
14506
+ types: external_exports.array(external_exports.enum(["entry", "goal", "answer"])).min(1).optional(),
14507
+ goalId: external_exports.string().uuid().optional(),
14508
+ limit: external_exports.number().int().min(1).max(20).optional()
14509
+ }).strict();
14510
+ var SEARCH_DESCRIPTION2 = "Search your person's history across all of their agents: Entries (what anyone said or wrote, typed or spoken on a call), Goals (by title and outcome) and Answers (found by their Question or by the words that gave them). query is words to look for; records sharing more of its words rank first, and exact names work. types narrows it to entry, goal and/or answer (default: all three). goalId searches under one Goal: its Entries, its Questions' Answers, and it and its immediate children. limit is matches per type, 1 to 20 (default 8). Read-only. Each match carries its whole saved words, its ID and its links (an Answer carries its Question, the choice made and the Entries that support it); `omitted` counts what matched but was left out, so narrow the words or add a goalId to see it. Nothing found is not proof that nothing exists; a refused search says why. Sealed (encrypted) content is never searched or returned.";
14511
+ var WhoIsWorkingSchema2 = external_exports.object({}).strict();
14386
14512
  var AGENT_TOOLS2 = [
14387
- { 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) },
14513
+ { 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(WhoIsWorkingSchema2) },
14388
14514
  { name: "contact", description: CONTACT_DESCRIPTION2, inputSchema: CONTACT_SCHEMA2 },
14389
- { name: "check_replies", description: CHECK_REPLIES_DESCRIPTION2, inputSchema: mcpInputSchema2(CheckRepliesSchema2) },
14390
- { name: "create_goal", description: CREATE_GOAL_DESCRIPTION2, inputSchema: mcpInputSchema2(CreateGoalToolSchema2) },
14515
+ { name: "manage_goals", description: MANAGE_GOALS_DESCRIPTION2, inputSchema: mcpInputSchema2(ManageGoalsToolSchema2) },
14391
14516
  { name: "claim_goal", description: CLAIM_GOAL_DESCRIPTION2, inputSchema: mcpInputSchema2(ClaimGoalSchema2) },
14392
14517
  { name: "get_goal", description: GET_GOAL_DESCRIPTION2, inputSchema: mcpInputSchema2(GetGoalSchema2) },
14393
- { name: "update_goal", description: UPDATE_GOAL_DESCRIPTION2, inputSchema: mcpInputSchema2(UpdateGoalToolSchema2) }
14518
+ { name: "update_goal", description: UPDATE_GOAL_DESCRIPTION2, inputSchema: mcpInputSchema2(UpdateGoalToolSchema2) },
14519
+ { name: "search", description: SEARCH_DESCRIPTION2, inputSchema: mcpInputSchema2(SearchToolSchema2) }
14394
14520
  ];
14395
14521
  var AGENT_TOOL_NAMES2 = AGENT_TOOLS2.map((t) => t.name);
14396
14522
  var id2 = external_exports.string().uuid();
@@ -14421,17 +14547,6 @@ var existingGoalChanges2 = [
14421
14547
  reason: external_exports.string().max(500).optional()
14422
14548
  }).strict()
14423
14549
  ];
14424
- var GoalChangeSchema2 = external_exports.union([
14425
- external_exports.object({
14426
- kind: external_exports.literal("create"),
14427
- title: external_exports.string().min(1).max(120),
14428
- outcome: external_exports.string().min(1),
14429
- ownerId: participant2,
14430
- parentGoalId: id2.optional(),
14431
- sourceEntryIds: external_exports.array(id2)
14432
- }).strict(),
14433
- ...existingGoalChanges2
14434
- ]);
14435
14550
  var BrainGoalChangeSchema2 = external_exports.union([
14436
14551
  // newSession: Paigy starts a session to own it (owner, 2026-10-06); until it has, the person owns it.
14437
14552
  external_exports.object({
@@ -14832,7 +14947,7 @@ var AwaitItemSchema2 = external_exports.discriminatedUnion("type", [
14832
14947
  /** The awaited ask was REPLACED by a newer notification on its thread (e.g. a
14833
14948
  * post-feedback revision, #633) — the user will never answer this id. Stop
14834
14949
  * awaiting it; the live ask is the thread's newest turn (await that one, or
14835
- * re-orient via check_replies). */
14950
+ * re-orient via contact({})). */
14836
14951
  external_exports.object({
14837
14952
  type: external_exports.literal("superseded"),
14838
14953
  parentId: external_exports.string(),
@@ -15560,7 +15675,7 @@ var HostDecisionSchema2 = external_exports.object({
15560
15675
  goalId: external_exports.string().uuid().nullable().optional(),
15561
15676
  /** When the server last heard from the agent, as the host read it: the presence it stood back for. */
15562
15677
  seenAt: external_exports.string().datetime().nullable().optional(),
15563
- /** When that work last moved (`claimable.since` on `check_replies`), the fact the bound is judged on. */
15678
+ /** When that work last moved (`claimable.since` on an agent's `contact({})` read), the fact the bound is judged on. */
15564
15679
  since: external_exports.string().datetime().nullable().optional(),
15565
15680
  /** What the host said, in its log's own words: why it stood back, or what the take-over did. */
15566
15681
  said: external_exports.string().max(300).optional()
@@ -15783,7 +15898,7 @@ function sameTail(a, b) {
15783
15898
  }
15784
15899
 
15785
15900
  // src/run.ts
15786
- import { randomUUID as randomUUID6 } from "crypto";
15901
+ import { randomUUID as randomUUID5 } from "crypto";
15787
15902
 
15788
15903
  // src/harness/session.ts
15789
15904
  import { spawn } from "child_process";
@@ -16394,8 +16509,13 @@ function railFor(opts) {
16394
16509
  update: (goalId, input) => updateGoal(goalId, input, opts),
16395
16510
  // One read and back: the pump owns the waiting, so a Call must not hold a window here.
16396
16511
  contact: (input) => contact(input, { ...opts, waits: false }),
16397
- create: (input) => createGoal(input, opts),
16398
- waiting: () => checkReplies(opts)
16512
+ create: async (input) => {
16513
+ const made = await manageGoals({ changes: [{ kind: "create", ...input }] }, opts);
16514
+ const goal = made.goals.find((g) => g.goalId === made.results[0]?.goalId);
16515
+ if (!goal) throw new Error(`manage_goals create failed: ${made.results[0]?.error ?? "no goal"}`);
16516
+ return { goalId: goal.goalId, revision: goal.revision };
16517
+ },
16518
+ waiting: () => receive(opts)
16399
16519
  };
16400
16520
  }
16401
16521
  function cancelAsks(state) {
@@ -16524,7 +16644,6 @@ ${event.result?.trim() || "No result reported."}`, state, rail, opts);
16524
16644
  }
16525
16645
 
16526
16646
  // src/paigy/conversation.ts
16527
- import { randomUUID as randomUUID5 } from "crypto";
16528
16647
  var HARNESS_INSTRUCTION = "You are running as an unattended background harness agent; your user reaches you through Paigy and is not at this terminal. Nothing wakes you after your turn ends but the person, so wait on CI or a deploy inside the turn. The person never sees your turn's final message: it is kept as progress on this Goal. Anything the person needs \u2014 a question, a result, a blocker \u2014 you send through Paigy's contact tool, once; the harness sends nothing on your behalf. What the person says later arrives with the Goal it was said on named in front of it; answer them on that Goal (its id as the contact's parentId).";
16529
16648
  var SAFETY_MS = 6e4;
16530
16649
  var ASK_BEAT_MS = 5e3;
@@ -16642,23 +16761,23 @@ async function gather(state, rail, held) {
16642
16761
  const moved = movedBelow(held, state);
16643
16762
  for (const { goal, since } of moved) look2(goal.goalId, "subtree", goal.title, since);
16644
16763
  const heard = [];
16645
- const read = /* @__PURE__ */ new Set();
16764
+ const read3 = /* @__PURE__ */ new Set();
16646
16765
  for (const [goalId, { since, ...found }] of looks) {
16647
16766
  let brief = found.brief;
16648
16767
  if (!brief) {
16649
16768
  try {
16650
16769
  brief = await rail.read(goalId);
16651
16770
  } catch (error) {
16652
- if (error.status === 404) read.add(goalId);
16771
+ if (error.status === 404) read3.add(goalId);
16653
16772
  continue;
16654
16773
  }
16655
16774
  }
16656
- read.add(goalId);
16775
+ read3.add(goalId);
16657
16776
  const fresh = !brief.reviewSince && (found.via === "waiting work" || found.via === "assigned") ? sinceTheWork(brief) : { after: -1 };
16658
16777
  if (found.via === "assigned") announced.add(goalId);
16659
16778
  heard.push({ goalId, ...found, brief, words: unheard(brief, state, brief.reviewSince ? null : since ?? null, fresh.after, brief.reviewSince), ...fresh.note ? { note: fresh.note } : {} });
16660
16779
  }
16661
- for (const { goal, since } of moved) if (read.has(goal.goalId)) state.below.goals.set(goal.goalId, { since, at: goal.updatedAt ?? null });
16780
+ for (const { goal, since } of moved) if (read3.has(goal.goalId)) state.below.goals.set(goal.goalId, { since, at: goal.updatedAt ?? null });
16662
16781
  return { heard, listed };
16663
16782
  }
16664
16783
  var GIVEN = "This Goal was given to you, and nobody has started it. Carry on with what you're doing unless it changes that; claim_goal with its id when you take it up.";
@@ -16776,7 +16895,7 @@ async function look(session, state, rail, opts) {
16776
16895
  if (opts?.initialPrompt?.trim()) {
16777
16896
  const prompt = opts.initialPrompt.trim();
16778
16897
  opts.initialPrompt = void 0;
16779
- const admitted = await rail.create({ outcome: prompt, idempotencyKey: randomUUID5() });
16898
+ const admitted = await rail.create({ title: prompt.split(/\s+/).slice(0, 5).join(" ").slice(0, 80), outcome: prompt });
16780
16899
  brief2 = await rail.claim();
16781
16900
  if (!brief2.goalId || brief2.revision === void 0) {
16782
16901
  state.goal = { id: admitted.goalId, revision: admitted.revision };
@@ -16867,9 +16986,9 @@ async function pump(session, state, rail, opts) {
16867
16986
  }
16868
16987
  if (!await opts.onIdle()) return;
16869
16988
  if (now() - since >= BEAT_REPORT_MS) {
16870
- const read = counts.wake + counts.rest + counts.safety;
16871
- if (read || counts.skipped || tally.noted || tally.seen || tally.announced) {
16872
- opts.log?.(`\u25B9 beats: ${read} read (${counts.wake} wake, ${counts.rest} rest, ${counts.safety} safety), ${counts.skipped} wake mid-turn skipped, ${tally.noted} noted mid-turn, ${tally.seen} seen by the hook, ${tally.announced} assigned announced${tally.paused ? `, ${tally.paused} held by the usage limit` : ""}`);
16989
+ const read3 = counts.wake + counts.rest + counts.safety;
16990
+ if (read3 || counts.skipped || tally.noted || tally.seen || tally.announced) {
16991
+ opts.log?.(`\u25B9 beats: ${read3} read (${counts.wake} wake, ${counts.rest} rest, ${counts.safety} safety), ${counts.skipped} wake mid-turn skipped, ${tally.noted} noted mid-turn, ${tally.seen} seen by the hook, ${tally.announced} assigned announced${tally.paused ? `, ${tally.paused} held by the usage limit` : ""}`);
16873
16992
  }
16874
16993
  counts.wake = counts.rest = counts.safety = counts.skipped = tally.noted = tally.seen = tally.announced = tally.paused = 0;
16875
16994
  since = now();
@@ -16887,7 +17006,7 @@ function runHarness(opts) {
16887
17006
  const clock4 = beat();
16888
17007
  let session = null;
16889
17008
  const speaksAs = opts.session ?? opts.resume ?? sessionId();
16890
- const instance = randomUUID6();
17009
+ const instance = randomUUID5();
16891
17010
  const rail = railFor({ token: opts.token, reach: reachAs(speaksAs, instance) });
16892
17011
  let inbox;
16893
17012
  if (opts.harness === "claude") {
@@ -17114,7 +17233,7 @@ async function waitingWork(token, session) {
17114
17233
  if (quiet !== void 0 && Date.now() < quiet) return { skip: BOUND_SKIP };
17115
17234
  let found;
17116
17235
  try {
17117
- found = await checkReplies({ token, ...session ? { reach: reachAs(session) } : {} });
17236
+ found = await receive({ token, ...session ? { reach: reachAs(session) } : {} });
17118
17237
  } catch (error) {
17119
17238
  if (error instanceof RevokedError) return { skip: "was revoked: its credential is gone for good", revoked: true };
17120
17239
  if (error instanceof ApiError && error.body?.error === "identity_session_mismatch") {
@@ -17353,7 +17472,7 @@ function startHost(opts) {
17353
17472
  skip(`has a full conversation (${resumes.slice(0, 8)}) \u2014 not resuming it; its Goals go to the dead-agent handoff`);
17354
17473
  return;
17355
17474
  }
17356
- const read = async () => {
17475
+ const read3 = async () => {
17357
17476
  const got = await waitingWork(token, identity.sessionId ?? owner?.sessionId);
17358
17477
  if (!("skip" in got)) return got;
17359
17478
  if (got.revoked) {
@@ -17365,7 +17484,7 @@ function startHost(opts) {
17365
17484
  return null;
17366
17485
  };
17367
17486
  if (decided.why === "presence") {
17368
- found = await read() ?? void 0;
17487
+ found = await read3() ?? void 0;
17369
17488
  if (!found) return;
17370
17489
  const since = found.since;
17371
17490
  decided = wakeAction(false, Date.now(), seenByServer, { ...here2, ...since ? { movedAt: Date.parse(since) } : {} });
@@ -17391,7 +17510,7 @@ function startHost(opts) {
17391
17510
  skip("has no granted folder to wake in");
17392
17511
  return;
17393
17512
  }
17394
- found ??= await read() ?? void 0;
17513
+ found ??= await read3() ?? void 0;
17395
17514
  if (!found) return;
17396
17515
  if (runs.has(key3)) {
17397
17516
  skip("was started by the wake that read it first");
@@ -17527,7 +17646,7 @@ function startHost(opts) {
17527
17646
  return {
17528
17647
  name,
17529
17648
  // The slot key rides along so the window's agent page can speak AS this agent —
17530
- // its pending reads (`checkReplies`, the same pure read the sweep does) need the
17649
+ // its pending reads (`receive`, the same pure read the sweep does) need the
17531
17650
  // slot's own token, and the display name is not a key.
17532
17651
  slot,
17533
17652
  tokenId: id3.tokenId,
@@ -17646,7 +17765,7 @@ ipcMain.handle("paigy:agent", async (_e, name) => {
17646
17765
  const entry = (host?.roster() ?? readHostState()?.roster ?? []).find((a) => a.name === name);
17647
17766
  if (!entry) return null;
17648
17767
  const token = entry.slot ? readToken(entry.slot) : "";
17649
- const open = token ? await checkReplies({ token }).then((r) => r.deliveries).catch(() => null) : null;
17768
+ const open = token ? await receive({ token }).then((r) => r.deliveries).catch(() => null) : null;
17650
17769
  return {
17651
17770
  ...entry,
17652
17771
  pending: open ? {