@intentic/sandbox-contract 1.349.0 → 1.351.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/dist/contracts/agents.contract.d.ts +493 -0
  2. package/dist/contracts/agents.contract.d.ts.map +1 -1
  3. package/dist/contracts/agents.contract.js +19 -1
  4. package/dist/contracts/agents.contract.js.map +1 -1
  5. package/dist/contracts/system.contract.d.ts +6 -0
  6. package/dist/contracts/system.contract.d.ts.map +1 -1
  7. package/dist/events/system-events.d.ts +4 -0
  8. package/dist/events/system-events.d.ts.map +1 -1
  9. package/dist/ids/conversation-ids.d.ts +3 -0
  10. package/dist/ids/conversation-ids.d.ts.map +1 -1
  11. package/dist/ids/conversation-ids.js +4 -0
  12. package/dist/ids/conversation-ids.js.map +1 -1
  13. package/dist/index.d.ts +499 -0
  14. package/dist/index.d.ts.map +1 -1
  15. package/dist/schemas/agent-people.d.ts +23 -0
  16. package/dist/schemas/agent-people.d.ts.map +1 -0
  17. package/dist/schemas/agent-people.js +22 -0
  18. package/dist/schemas/agent-people.js.map +1 -0
  19. package/dist/schemas/agents-list.d.ts +456 -0
  20. package/dist/schemas/agents-list.d.ts.map +1 -1
  21. package/dist/schemas/agents-list.js +8 -0
  22. package/dist/schemas/agents-list.js.map +1 -1
  23. package/dist/schemas/agents.d.ts +7 -21
  24. package/dist/schemas/agents.d.ts.map +1 -1
  25. package/dist/schemas/agents.js +6 -20
  26. package/dist/schemas/agents.js.map +1 -1
  27. package/dist/schemas/conversation-links.d.ts +1 -0
  28. package/dist/schemas/conversation-links.d.ts.map +1 -1
  29. package/dist/schemas/conversation-links.js +1 -0
  30. package/dist/schemas/conversation-links.js.map +1 -1
  31. package/dist/schemas/devices.d.ts +2 -1
  32. package/dist/schemas/devices.d.ts.map +1 -1
  33. package/dist/schemas/devices.js +2 -1
  34. package/dist/schemas/devices.js.map +1 -1
  35. package/dist/state/workspace-state.d.ts +6 -0
  36. package/dist/state/workspace-state.d.ts.map +1 -1
  37. package/dist/state/workspace-state.js +2 -6
  38. package/dist/state/workspace-state.js.map +1 -1
  39. package/package.json +5 -5
  40. package/src/contracts/agents.contract.ts +24 -1
  41. package/src/ids/conversation-ids.test.ts +15 -0
  42. package/src/ids/conversation-ids.ts +11 -0
  43. package/src/schemas/agent-people.ts +36 -0
  44. package/src/schemas/agents-list.ts +16 -0
  45. package/src/schemas/agents.ts +10 -31
  46. package/src/schemas/conversation-links.ts +5 -0
  47. package/src/schemas/devices.ts +5 -5
  48. package/src/state/workspace-state.test.ts +2 -0
  49. package/src/state/workspace-state.ts +5 -6
@@ -10,6 +10,8 @@ import { AgentNeedSchema } from "./needs.js";
10
10
  import { EMOJI_MAX_LENGTH, isSingleEmoji } from "../text/emoji.js";
11
11
  import { ProgramAskSchema } from "../events/requests.js";
12
12
  import { ReviewTallySchema, TurnProofSchema } from "./work-assurance.js";
13
+ import { AgentReactionSchema, SessionOwnerSchema } from "./agent-people.js";
14
+ export { AgentReactionSchema, ReactorSchema, SessionOwnerSchema, type AgentReaction, type Reactor, type SessionOwner } from "./agent-people.js";
13
15
  // A fleet agent is any conversation with a registry entry, keyed by conversationId. Isolated ones own a git worktree
14
16
  // (branch agent/<id>); workspace conversations have none, but both share one status/activity/cost lifecycle.
15
17
 
@@ -237,37 +239,6 @@ export type LandedMessageDraft = z.infer<typeof LandedMessageDraftSchema>;
237
239
  // offer the press that clears a refusal without knowing whose refusal it is.
238
240
  export const LandConflictReasonSchema = z.enum(["workspace", "diverged", "binary"]);
239
241
  export type LandConflictReason = z.infer<typeof LandConflictReasonSchema>;
240
- // One person behind one mark. The instant rides along so the group can be ordered by who was first, which is also the
241
- // order the names read in.
242
- export const ReactorSchema = z.object({
243
- email: z.string().describe("Who it was, as the sandbox verified them."),
244
- name: z.string().optional().describe("What to call them, when their sign-in carried a name. Absent leaves the address to stand for them."),
245
- at: z.number().describe("When they marked it, in milliseconds."),
246
- });
247
- export type Reactor = z.infer<typeof ReactorSchema>;
248
- // The member answerable for a conversation: whose questions its cards are, who a reviewer asks about its work. Derived
249
- // once from the starter, moved only by `agents.assign`; never a program, which is what `startedBy` is for.
250
- export const SessionOwnerSchema = z.object({
251
- email: z.string().describe("Who answers for this conversation, as the sandbox verified them."),
252
- name: z
253
- .string()
254
- .optional()
255
- .describe("What to call them, when the sign-in that made them its owner carried a name. Absent leaves the address to stand for them."),
256
- since: z.number().describe("When they became its owner, in milliseconds."),
257
- });
258
- export type SessionOwner = z.infer<typeof SessionOwnerSchema>;
259
- // Grouped by emoji on the wire, not as a flat list of presses: every surface draws one chip per emoji, and grouping
260
- // here is what stops three of them each grouping it differently.
261
- export const AgentReactionSchema = z.object({
262
- emoji: z.string().describe("The mark itself, one emoji, carried as the character rather than as a name that would need a table on both sides."),
263
- by: z
264
- .array(ReactorSchema)
265
- .min(1)
266
- .describe(
267
- "Everyone wearing this mark, oldest first, each by name. Carried whole rather than as a count, because a chip reading 3 that cannot say whose is a number nobody can answer. Never empty: the last person taking theirs back takes the whole chip with it.",
268
- ),
269
- });
270
- export type AgentReaction = z.infer<typeof AgentReactionSchema>;
271
242
  export const AgentSummarySchema = z.object({
272
243
  id: z.string().describe("The conversation id, which is how every other call addresses it."),
273
244
  sessionId: z.string().optional().describe("The provider session behind the last turn. It is retired whenever the model or account changes."),
@@ -412,6 +383,14 @@ export const AgentSummarySchema = z.object({
412
383
  fresh: FreshSessionSchema.optional().describe(
413
384
  "Set on a conversation started on another conversation's work without its messages (a code review, a test pass, a person's own ask): which one, for what, and when. Absent for every other conversation.",
414
385
  ),
386
+ // Latched on the opening turn (ids/conversation-ids.ts homeConversationId). Rides the summary because it decides who
387
+ // may see the row at all (auth/fleet-scope.ts visibleTo): its owner, and the sandbox's owner.
388
+ home: z
389
+ .literal(true)
390
+ .optional()
391
+ .describe(
392
+ "This is its owner's home conversation in this sandbox: the one long-running chat the master view opens, which orchestrates its own subagents, holds their work until it accepts it, and lands and commits by itself. Only its owner and the sandbox's owner see it. Absent for every other conversation.",
393
+ ),
415
394
  // Root repo's short base sha; per-repo bases stay daemon-internal.
416
395
  base: z.string().optional().describe("The commit its private copy started from, shortened."),
417
396
  costUsd: z.number().optional().describe("What it has cost so far, in dollars. A subagent's spend is its own and is not folded in here."),
@@ -36,6 +36,11 @@ export const FreshSessionSchema = z.object({
36
36
  of: ConversationIdSchema.describe("The conversation whose work it started from."),
37
37
  kind: FreshKindSchema.describe("What it was opened for: a code review, a test pass, or the person's own ask."),
38
38
  at: z.number().describe("When it started, in milliseconds. Work its origin changed after this is work it has not seen."),
39
+ // An orchestrator judging its own subagent's work (spawn with `freshOf`): the session is still the origin's child, cut
40
+ // from its work and landing back into it, but it reports to the agent that opened it, which supervises it.
41
+ by: ConversationIdSchema.optional().describe(
42
+ "The agent that opened it, when an agent did rather than a person: an orchestrator judging the work of a subagent it spawned. Its report goes to that agent. Absent for a person's session.",
43
+ ),
39
44
  });
40
45
  export type FreshSession = z.infer<typeof FreshSessionSchema>;
41
46
 
@@ -304,8 +304,7 @@ export const DevicePortSchema = z.object({
304
304
  command: z.string().optional(),
305
305
  });
306
306
  export type DevicePort = z.infer<typeof DevicePortSchema>;
307
- // The device's one agent process as a single block; `running` also gates whether the rest of the report is still
308
- // current, a dead loop leaves every other row reading as it did before it died.
307
+ // The device's one agent process; `running` gates whether the rest of a report is current (a dead loop freezes it).
309
308
  export const DeviceAgentSchema = z.object({
310
309
  running: z.boolean(),
311
310
  pid: z.number().int().optional(),
@@ -313,12 +312,13 @@ export const DeviceAgentSchema = z.object({
313
312
  installed: z.string().optional(),
314
313
  // Build actually serving, stamped in the pidfile; can lag `installed` indefinitely (see `agentBuildSkew`).
315
314
  build: z.string().optional(),
316
- // When the loop last finished a pass; a live process can have a dead loop (see `agentStalled`).
315
+ // When the sync loop last moved; absent while nothing is paired (no loop runs). A live process can have a dead loop.
317
316
  lastTickAt: z.number().optional(),
318
317
  });
319
318
  export type DeviceAgent = z.infer<typeof DeviceAgentSchema>;
320
- // Loop polls every 5s with two 10s network timeouts per pairing; a minute is several passes of slack.
321
- export const AGENT_STALL_AFTER_MS = 60_000;
319
+ // Stalled only once the agent's own restart of a loop that stopped moving (machine sync/mirror.ts) is overdue.
320
+ export const WATCHER_STALL_MS = 20 * 60_000;
321
+ export const AGENT_STALL_AFTER_MS = WATCHER_STALL_MS + 2 * 60_000;
322
322
  export const agentStalled = (agent: DeviceAgent, now: number): boolean =>
323
323
  agent.running && agent.lastTickAt !== undefined && now - agent.lastTickAt > AGENT_STALL_AFTER_MS;
324
324
  export const DeviceReportSchema = z.object({
@@ -398,6 +398,8 @@ describe(`VERSIONED_STATE_PATHS`, () => {
398
398
  // Which commands count as heavy, and how many may run at once; a shared-box decision worth a `git log`
399
399
  // line.
400
400
  `${STATE_DIR}/config/heavy-commands.json`,
401
+ // What a home conversation reviews, merges and asks a person about; same reason as the safety policy.
402
+ `${STATE_DIR}/config/home.md`,
401
403
  `${STATE_DIR}/config/loop-designs.json`,
402
404
  `${STATE_DIR}/config/personas.json`,
403
405
  // A persona's prompt and reachable skills: the text that decides how it behaves, same reason as its card.
@@ -100,6 +100,10 @@ const STATE_FILES = [
100
100
  // may do unasked, so a fresh sandbox should start already governed and changes should show in review. Absent falls
101
101
  // back to `DEFAULT_SAFETY_POLICY`, not unconfigured.
102
102
  { path: ".intentic/config/safety.md", invalidates: ["safety-policy"], portability: "carry", versioned: true },
103
+ // What every home conversation works by (conversations/home/home-policy.ts): when it reviews, tests, merges and asks a
104
+ // person. `carry`+`versioned` like the safety policy, since it governs what an orchestrator lands unasked. Absent falls
105
+ // back to `DEFAULT_HOME_POLICY`.
106
+ { path: ".intentic/config/home.md", invalidates: [], portability: "carry", versioned: true, why: "Read per home turn; no view shows it." },
103
107
  // Verdicts the policy above produced, newest first. `derived`/`local`: evidence about this machine, self-trimming,
104
108
  // not carried. Own query key, separate from the policy's, since a verdict must not invalidate the document someone
105
109
  // is editing.
@@ -305,12 +309,7 @@ const STATE_FILES = [
305
309
  // Unlike the settings file, this switch is observed by the Extensions tab's query, so a flip elsewhere shows up
306
310
  // live. Toggling doesn't itself rerun the host, that happens via the loader's reconcile, triggered by the tab's own
307
311
  // toggle.
308
- {
309
- path: ".intentic/config/extension-enablement.json",
310
- invalidates: ["extensions"],
311
- portability: "carry",
312
- versioned: true,
313
- },
312
+ { path: ".intentic/config/extension-enablement.json", invalidates: ["extensions"], portability: "carry", versioned: true },
314
313
  // Workspace extensions: one directory per extension, written directly by the agent's file tools and live
315
314
  // immediately (no clone, no install step). `authored`, unlike `.intentic/extensions/` below which holds clones.
316
315
  // `versioned`: every other load path is already reviewable (a git-installed extension's sha, a baked one's image);