@astrosheep/square 0.3.105 → 0.4.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 (143) hide show
  1. package/dist/activity-feed.js +1 -1
  2. package/dist/artifact-store.d.ts +41 -0
  3. package/dist/artifact-store.js +272 -0
  4. package/dist/artifact.d.ts +8 -12
  5. package/dist/artifact.js +66 -343
  6. package/dist/attention-presentation.d.ts +33 -7
  7. package/dist/attention-presentation.js +33 -69
  8. package/dist/boundary-presentation.d.ts +0 -2
  9. package/dist/boundary-presentation.js +17 -22
  10. package/dist/catch-decisions.d.ts +2 -2
  11. package/dist/catch-decisions.js +14 -4
  12. package/dist/catch-selection.d.ts +8 -0
  13. package/dist/catch-selection.js +5 -0
  14. package/dist/channel-artifact.d.ts +10 -0
  15. package/dist/channel-artifact.js +55 -0
  16. package/dist/channel-delivery.d.ts +11 -0
  17. package/dist/channel-delivery.js +51 -0
  18. package/dist/channel-domain.d.ts +3 -0
  19. package/dist/channel-domain.js +83 -0
  20. package/dist/channel-facade.d.ts +76 -0
  21. package/dist/channel-facade.js +1 -0
  22. package/dist/channel-internal.d.ts +126 -0
  23. package/dist/channel-internal.js +440 -0
  24. package/dist/channel-metadata.d.ts +11 -0
  25. package/dist/channel-metadata.js +1 -0
  26. package/dist/channel-ports.d.ts +241 -0
  27. package/dist/channel-ports.js +1 -0
  28. package/dist/channel-presentation.d.ts +17 -0
  29. package/dist/channel-presentation.js +22 -0
  30. package/dist/channel-sqlite-schema.d.ts +13 -0
  31. package/dist/channel-sqlite-schema.js +81 -0
  32. package/dist/channel-transport.d.ts +62 -0
  33. package/dist/channel-transport.js +1 -0
  34. package/dist/channel-values.d.ts +27 -0
  35. package/dist/channel-values.js +90 -0
  36. package/dist/channel.d.ts +31 -21
  37. package/dist/channel.js +42 -74
  38. package/dist/claude-delivery-status.js +1 -1
  39. package/dist/claude-delivery.d.ts +2 -5
  40. package/dist/claude-delivery.js +56 -103
  41. package/dist/claude-mod.js +4 -4
  42. package/dist/claude-transport.d.ts +5 -0
  43. package/dist/claude-transport.js +58 -0
  44. package/dist/cli/context.d.ts +2 -2
  45. package/dist/cli/context.js +0 -1
  46. package/dist/cli/maintenance-commands.d.ts +0 -4
  47. package/dist/cli/maintenance-commands.js +2 -29
  48. package/dist/cli/program.js +1 -1
  49. package/dist/cli/registry.js +1 -2
  50. package/dist/codex-address.d.ts +1 -1
  51. package/dist/codex-queue.d.ts +2 -2
  52. package/dist/codex-queue.js +1 -3
  53. package/dist/decisions.js +3 -3
  54. package/dist/delivery-deferral.d.ts +9 -18
  55. package/dist/delivery-deferral.js +4 -4
  56. package/dist/delivery-health.d.ts +4 -4
  57. package/dist/delivery-health.js +11 -11
  58. package/dist/delivery-operations.d.ts +15 -2
  59. package/dist/delivery-operations.js +60 -30
  60. package/dist/delivery.d.ts +44 -33
  61. package/dist/delivery.js +49 -75
  62. package/dist/help.js +1 -6
  63. package/dist/http-delivery.d.ts +2 -2
  64. package/dist/http-delivery.js +2 -4
  65. package/dist/inbox.d.ts +10 -18
  66. package/dist/inbox.js +44 -53
  67. package/dist/index.d.ts +1 -1
  68. package/dist/index.js +1 -1
  69. package/dist/mcp.d.ts +2 -1
  70. package/dist/mcp.js +40 -70
  71. package/dist/message.d.ts +7 -0
  72. package/dist/message.js +23 -0
  73. package/dist/model.d.ts +41 -77
  74. package/dist/model.js +7 -139
  75. package/dist/neutral.d.ts +72 -0
  76. package/dist/neutral.js +27 -0
  77. package/dist/notifications.d.ts +2 -8
  78. package/dist/notifications.js +15 -50
  79. package/dist/operation-presentation.d.ts +1 -2
  80. package/dist/operation-presentation.js +1 -7
  81. package/dist/owner.d.ts +2 -2
  82. package/dist/owner.js +1 -1
  83. package/dist/paseo-delivery.d.ts +1 -1
  84. package/dist/paseo-delivery.js +2 -4
  85. package/dist/paseo-timeline.js +1 -0
  86. package/dist/plugins/opencode/delivery.js +27 -42
  87. package/dist/ports.d.ts +46 -168
  88. package/dist/presentation-operations.d.ts +1 -14
  89. package/dist/presentation-operations.js +16 -16
  90. package/dist/presentation.d.ts +5 -5
  91. package/dist/presentation.js +1 -0
  92. package/dist/runtime.js +2 -2
  93. package/dist/search.js +1 -1
  94. package/dist/sqlite-channel.d.ts +15 -0
  95. package/dist/sqlite-channel.js +600 -0
  96. package/dist/sqlite-framing.d.ts +8 -0
  97. package/dist/sqlite-framing.js +31 -0
  98. package/dist/sqlite-square.d.ts +12 -13
  99. package/dist/sqlite-square.js +192 -248
  100. package/dist/sqlite-values.d.ts +21 -0
  101. package/dist/sqlite-values.js +78 -0
  102. package/dist/square-api.d.ts +1 -1
  103. package/dist/square-api.js +1 -1
  104. package/dist/square-core.d.ts +1 -1
  105. package/dist/square-domain.d.ts +21 -7
  106. package/dist/square-domain.js +93 -94
  107. package/dist/square-facade.d.ts +12 -66
  108. package/dist/square-index.d.ts +1 -1
  109. package/dist/square-index.js +1 -1
  110. package/dist/square-location.d.ts +6 -1
  111. package/dist/square-location.js +1 -1
  112. package/dist/square-receive.d.ts +2 -3
  113. package/dist/square-sqlite.d.ts +45 -44
  114. package/dist/square-sqlite.js +308 -764
  115. package/dist/square-tools.d.ts +8 -0
  116. package/dist/square-tools.js +39 -0
  117. package/dist/views.d.ts +6 -6
  118. package/dist/views.js +15 -9
  119. package/dist/wake-preview.d.ts +7 -0
  120. package/dist/wake-preview.js +15 -0
  121. package/dist/wake-sink.d.ts +2 -2
  122. package/dist/wake-sink.js +1 -1
  123. package/dist/wake-transports.d.ts +7 -0
  124. package/dist/wake-transports.js +42 -0
  125. package/guides/claude-native.md +13 -10
  126. package/guides/codex-delivery.md +3 -1
  127. package/guides/participant-ownership.md +1 -1
  128. package/guides/row-runtime-delivery-evidence.md +2 -0
  129. package/guides/row-storage-design.md +19 -44
  130. package/guides/square-api.md +137 -60
  131. package/package.json +3 -3
  132. package/plugins/claude/.claude-plugin/plugin.json +1 -1
  133. package/plugins/claude/types.d.ts +1 -1
  134. package/plugins/codex/.codex-plugin/plugin.json +1 -1
  135. package/plugins/opencode/delivery.ts +28 -41
  136. package/plugins/pi/square-pi.js +28 -51
  137. package/dist/square-legacy-framing.d.ts +0 -11
  138. package/dist/square-legacy-framing.js +0 -64
  139. package/dist/square-migration-host-ledger.d.ts +0 -26
  140. package/dist/square-migration-host-ledger.js +0 -169
  141. package/dist/square-migration.d.ts +0 -30
  142. package/dist/square-migration.js +0 -599
  143. package/guides/migration.md +0 -156
@@ -16,6 +16,14 @@ export declare class SquareExpressDrafts {
16
16
  consume(token?: string): void;
17
17
  retain(args: JsonObject, owner: Owner | undefined, token: string | undefined, failure: JsonObject, expressAttempted: boolean): string | undefined;
18
18
  }
19
+ interface ToolBinding {
20
+ identity: ToolIdentity;
21
+ open(location: string | undefined, control: OperationControl): Promise<Square>;
22
+ }
23
+ export declare function createSquareToolRunner(): (tool: ToolDefinition, args: JsonObject, control: OperationControl, bind: () => Promise<ToolBinding> | ToolBinding, defaultLocation?: string) => Promise<{
24
+ text: string;
25
+ isError?: true;
26
+ }>;
19
27
  interface ToolDefinition {
20
28
  name: string;
21
29
  description: string;
@@ -45,6 +45,45 @@ export class SquareExpressDrafts {
45
45
  return created;
46
46
  }
47
47
  }
48
+ export function createSquareToolRunner() {
49
+ const drafts = new SquareExpressDrafts();
50
+ return async (tool, args, control, bind, defaultLocation) => {
51
+ let toolArgs = args;
52
+ let owner;
53
+ let token;
54
+ let attempted = false;
55
+ let square;
56
+ try {
57
+ const binding = await bind();
58
+ owner = binding.identity.owner;
59
+ if (tool.name === 'express') {
60
+ const resolved = drafts.resolve(toolArgs, owner);
61
+ toolArgs = resolved.args;
62
+ token = resolved.token;
63
+ }
64
+ square = await binding.open(toolArgs.location, control);
65
+ let text;
66
+ try {
67
+ attempted = tool.name === 'express';
68
+ text = await tool.run(square, toolArgs, control, binding.identity);
69
+ drafts.consume(token);
70
+ }
71
+ finally {
72
+ await square.close();
73
+ }
74
+ return { text };
75
+ }
76
+ catch (error) {
77
+ const failure = squareToolFailure(error, control.signal);
78
+ const draft = tool.name === 'express' ? drafts.retain(toolArgs, owner, token, failure, attempted) : undefined;
79
+ return { isError: true, text: squareToolFailureText(failure, {
80
+ location: square?.location ?? toolArgs.location ?? defaultLocation,
81
+ participant: typeof toolArgs.as === 'string' ? toolArgs.as : undefined,
82
+ draft,
83
+ }) };
84
+ }
85
+ };
86
+ }
48
87
  const location = z.string().optional().describe('Which square: a .square file path. Relative paths start from the working directory. Leave it out for the configured square.');
49
88
  const participant = z.string().optional().describe('Your name in the square. Leave it out if you hold exactly one name here.');
50
89
  const activityId = z.string().regex(/^act\/(0|[1-9][0-9]*)$/);
package/dist/views.d.ts CHANGED
@@ -1,19 +1,19 @@
1
1
  import { type ActivityId } from './square-core.js';
2
- import { type StoredAct } from './model.js';
2
+ import { type HydratedAct } from './model.js';
3
3
  import type { ActivityFilter, SquareRead } from './ports.js';
4
4
  import type { Activity, ArchiveRecord, PerceivedActivity, HistoryQuery, HistoryContinuation, ParticipantsResult, EntryPresentation, StatusResult, SquareObservation, CatchPresence } from './square-facade.js';
5
5
  export declare const HISTORY_DEFAULT_LIMIT = 10;
6
6
  export declare const HISTORY_MAX_LIMIT = 100;
7
7
  export declare const NON_READ: readonly ["join", "done", "say", "listen", "ignore", "unlisten"];
8
- /** The one StoredAct-to-public-Activity field mapping. Rejects read bookkeeping. */
9
- export declare function toPublicActivity(stored: StoredAct): Activity;
10
- export declare function toPerceivedActivity(facts: SquareRead, stored: StoredAct, viewer: string): PerceivedActivity;
8
+ /** The one stored-to-public Activity field mapping. Rejects read bookkeeping. */
9
+ export declare function toPublicActivity(stored: HydratedAct): Activity;
10
+ export declare function toPerceivedActivity(facts: SquareRead, stored: HydratedAct, viewer: string): PerceivedActivity;
11
11
  export declare function parseRequiredActivityId(id: ActivityId): number;
12
12
  /** History adds archive context and ordering to the shared storage-side query predicates. */
13
13
  export declare function selectHistory(facts: SquareRead, query: HistoryQuery, limit: number | null, kinds: ActivityFilter['kinds'], presentation?: boolean): {
14
14
  continuation?: HistoryContinuation | undefined;
15
- activities: StoredAct[];
16
- visibleActivities: StoredAct[];
15
+ activities: HydratedAct[];
16
+ visibleActivities: HydratedAct[];
17
17
  totalMatches: number;
18
18
  };
19
19
  export declare function publicActivities(activities: readonly ArchiveRecord[]): Activity[];
package/dist/views.js CHANGED
@@ -11,15 +11,15 @@ const STATUS_HERE_WINDOW_MS = 30 * 60_000;
11
11
  const PRESENCE_WINDOW_MS = 8 * 60 * 60_000;
12
12
  export const NON_READ = ['join', 'done', 'say', 'listen', 'ignore', 'unlisten'];
13
13
  const ARCHIVE = new Set(['join', 'done', 'say']);
14
- /** The one StoredAct-to-public-Activity field mapping. Rejects read bookkeeping. */
14
+ /** The one stored-to-public Activity field mapping. Rejects read bookkeeping. */
15
15
  export function toPublicActivity(stored) {
16
16
  if (stored.kind === 'read')
17
17
  throw new Error(`Cannot expose stored activity ${formatActivityId(stored.index)}`);
18
18
  return { id: formatActivityId(stored.index), at: stored.at, kind: stored.kind, actor: stored.actor,
19
+ ...(stored.kind === 'say' && stored.messageIndex !== undefined ? { messageId: `msg/${stored.messageIndex}` } : {}),
19
20
  ...(stored.kind === 'say' && stored.reach !== undefined ? { reach: stored.reach } : {}),
20
21
  ...('body' in stored && stored.body !== undefined ? { body: stored.body } : {}),
21
- ...(stored.kind === 'say' && stored.metadata !== undefined ? { metadata: stored.metadata } : {}),
22
- ...(stored.kind === 'say' && stored.delivery !== undefined ? { delivery: stored.delivery } : {}),
22
+ ...('metadata' in stored && stored.metadata !== undefined ? { metadata: stored.metadata } : {}),
23
23
  mentions: stored.kind === 'say' ? stored.mentions ?? [] : [], ...('target' in stored ? { target: stored.target } : {}),
24
24
  ...(stored.kind === 'say' && stored.reply !== undefined ? { reply: formatActivityId(stored.reply) } : {}) };
25
25
  }
@@ -144,7 +144,10 @@ export function queryStatus(facts, context, viewer = '', observe = false) {
144
144
  const header = facts.header(), standingCount = inSquareCount(facts);
145
145
  const listener = participants.find((p) => p.presence !== 'never-joined' && nameKey(p.name) === nameKey(viewer));
146
146
  const latest = facts.activityHeads({ kinds: ['say', 'done'] }, { edge: 'newest', limit: 1 }).items[0];
147
- const latestAct = latest === undefined ? undefined : facts.activity(latest.index);
147
+ const joinHeads = observe ? facts.activityHeads({ kinds: ['join'], afterIndex: latest?.index ?? -1 }, { edge: 'newest', limit: 3 }).items : [];
148
+ const indexes = [...new Set([...(latest === undefined ? [] : [latest.index]), ...joinHeads.map(head => head.index)])];
149
+ const hydrated = new Map(facts.activities(indexes).map(activity => [activity.index, activity]));
150
+ const latestAct = latest === undefined ? undefined : hydrated.get(latest.index);
148
151
  const data = {
149
152
  hardCap: header.hardCap,
150
153
  ...(header.throttlePerMinute === undefined ? {} : { throttlePerMinute: header.throttlePerMinute }),
@@ -155,10 +158,13 @@ export function queryStatus(facts, context, viewer = '', observe = false) {
155
158
  if (!observe)
156
159
  return data;
157
160
  const afterIndex = latestAct?.index ?? -1;
158
- const joins = facts.activities(facts.activityHeads({ kinds: ['join'], afterIndex }, { edge: 'newest', limit: 3 }).items.map((h) => h.index)).map((activity) => ({
159
- rejoined: facts.activityCount({ kinds: ['done'], actors: [activity.actor], actorMatch: 'exact', beforeIndex: activity.index }) > 0,
160
- activity: toPublicActivity(activity)
161
- }));
161
+ const joins = joinHeads.flatMap(head => {
162
+ const activity = hydrated.get(head.index);
163
+ return activity === undefined ? [] : [{
164
+ rejoined: facts.activityCount({ kinds: ['done'], actors: [activity.actor], actorMatch: 'exact', beforeIndex: activity.index }) > 0,
165
+ activity: toPublicActivity(activity)
166
+ }];
167
+ });
162
168
  const canonicalViewer = facts.participant(viewer)?.name ?? viewer;
163
169
  return {
164
170
  ...data,
@@ -190,7 +196,7 @@ export function streamTailProjection(facts, last = HISTORY_DEFAULT_LIMIT, recipi
190
196
  throw new SquareError('invalid_args', `Invalid stream tail: expected a non-negative safe integer no greater than ${PAGE_SIZE}.`);
191
197
  const heads = last === 0 ? [] : recipient === undefined
192
198
  ? facts.activityHeads({ kinds: NON_READ }, { edge: 'newest', limit: last }).items
193
- : facts.directed(recipient, {}, { edge: 'newest', limit: last }).items;
199
+ : facts.directed(recipient, { kinds: ['say'] }, { edge: 'newest', limit: last }).items;
194
200
  const activities = facts.activities(heads.map((head) => head.index)).map((activity) => recipient === undefined
195
201
  ? toPublicActivity(activity) : toPerceivedActivity(facts, activity, recipient));
196
202
  return { activities, cursor: facts.header().lastActIndex, hasMore: false };
@@ -0,0 +1,7 @@
1
+ import type { WakeProjectionContext, WakeProjection, SquareArtifactPort } from './ports.js';
2
+ export declare function squareWakeProjection(artifact: SquareArtifactPort): WakeProjection;
3
+ /** Agora-framed projection over the narrow captured delivery context. */
4
+ export declare function wakePreview(facts: import('./ports.js').SquareRead, request: WakeProjectionContext): {
5
+ payload: string;
6
+ coverage: "full" | "clipped";
7
+ } | undefined;
@@ -0,0 +1,15 @@
1
+ import { parseMessageId } from './message.js';
2
+ import { nativePendingPreview } from './inbox.js';
3
+ import { canonicalPathSync } from './canonical-path.js';
4
+ export function squareWakeProjection(artifact) {
5
+ return async (context) => (await artifact.read(facts => wakePreview(facts, context))).value;
6
+ }
7
+ /** Agora-framed projection over the narrow captured delivery context. */
8
+ export function wakePreview(facts, request) {
9
+ const index = parseMessageId(request.message);
10
+ if (index === undefined)
11
+ return undefined;
12
+ const preview = nativePendingPreview(facts, { location: canonicalPathSync(request.location), participant: request.participant,
13
+ generation: request.seat.generation, owner: request.seat.owner, index, route: request.route, now: Date.now() });
14
+ return preview === undefined ? undefined : { payload: preview.payload, coverage: preview.clipped ? 'clipped' : 'full' };
15
+ }
@@ -4,14 +4,14 @@ export interface PaseoWakeRequest {
4
4
  prompt: string;
5
5
  location: string;
6
6
  participant: string;
7
- activity: string;
7
+ message: string;
8
8
  attemptN?: number;
9
9
  }
10
10
  /**
11
11
  * The daemon's own dedup key for one attempt. Every retry of the same attempt
12
12
  * derives the same id; a later attempt of the same attention derives a new one.
13
13
  */
14
- export declare function paseoWakeMessageId(request: Pick<PaseoWakeRequest, 'location' | 'participant' | 'activity' | 'attemptN'>): string;
14
+ export declare function paseoWakeMessageId(request: Pick<PaseoWakeRequest, 'location' | 'participant' | 'message' | 'attemptN'>): string;
15
15
  /** Steer one existing Paseo agent through the shared delivery entry. Never interrupts a turn. */
16
16
  export declare function sendPaseoWake(request: PaseoWakeRequest, opts?: {
17
17
  timeoutMs?: number;
package/dist/wake-sink.js CHANGED
@@ -6,7 +6,7 @@ import { DeliveryError, connect } from './packages/agent-delivery/src/index.js';
6
6
  */
7
7
  export function paseoWakeMessageId(request) {
8
8
  const digest = createHash('sha256')
9
- .update([request.location, request.participant, request.activity, request.attemptN ?? 0].join('|'))
9
+ .update([request.location, request.participant, request.message, request.attemptN ?? 0].join('|'))
10
10
  .digest('hex');
11
11
  return `square-${digest.slice(0, 32)}`;
12
12
  }
@@ -0,0 +1,7 @@
1
+ import type { WakeRouteKind } from './channel-values.js';
2
+ import type { WakeTransportPort } from './channel-transport.js';
3
+ export type WakeTransports = Readonly<Partial<Record<WakeRouteKind, WakeTransportPort>>>;
4
+ /** Concrete transports use wall time; semantic state time belongs to Square operations. */
5
+ export declare function createDefaultWakeTransport(env?: NodeJS.ProcessEnv, suppliedTransports?: WakeTransports): Promise<WakeTransportPort>;
6
+ /** Route selection only: all implementations receive the same request and final gate. */
7
+ export declare function createWakeTransport(transports: WakeTransports): WakeTransportPort;
@@ -0,0 +1,42 @@
1
+ /** Concrete transports use wall time; semantic state time belongs to Square operations. */
2
+ export async function createDefaultWakeTransport(env = process.env, suppliedTransports) {
3
+ if (suppliedTransports !== undefined)
4
+ return createWakeTransport(suppliedTransports);
5
+ const transports = {};
6
+ try {
7
+ const { CodexQueueTransport } = await import('./codex-queue.js');
8
+ transports['codex-queue'] = new CodexQueueTransport({ env });
9
+ }
10
+ catch { /* core-only builds may omit Codex */ }
11
+ if (env.SQUARE_DISABLE_PASEO_WAKE !== '1') {
12
+ try {
13
+ const { PaseoWakeTransport } = await import('./paseo-delivery.js');
14
+ transports.paseo = new PaseoWakeTransport();
15
+ }
16
+ catch { /* Paseo is optional */ }
17
+ }
18
+ const { createClaudeWakeTransport } = await import('./claude-transport.js');
19
+ transports['claude-native'] = createClaudeWakeTransport(env);
20
+ const { HttpWakeTransport } = await import('./http-delivery.js');
21
+ transports.http = new HttpWakeTransport({ env });
22
+ return createWakeTransport(transports);
23
+ }
24
+ /** Route selection only: all implementations receive the same request and final gate. */
25
+ export function createWakeTransport(transports) {
26
+ const missing = (kind) => ({ outcome: 'not-capable', diagnostic: `no transport for ${kind}` });
27
+ return {
28
+ async probe(route) {
29
+ const transport = transports[route.kind];
30
+ if (transport === undefined)
31
+ return missing(route.kind);
32
+ try {
33
+ return await transport.probe?.(route) ?? true;
34
+ }
35
+ catch (error) {
36
+ return { outcome: 'not-capable', diagnostic: error instanceof Error ? error.message : String(error) };
37
+ }
38
+ },
39
+ attempt: (request, timeoutMs, beforeSend) => transports[request.route.kind]?.attempt(request, timeoutMs, beforeSend)
40
+ ?? Promise.resolve(missing(request.route.kind)),
41
+ };
42
+ }
@@ -31,7 +31,8 @@ register their native wake addresses only through their loaded integrations. An
31
31
  ordinary reconnect or reattachment cannot replace a current native address with a
32
32
  generic Paseo proposal. Addresses belong to the artifact seat generation, not an
33
33
  expiring routes table: explicit receiver withdrawal permits fallback, and a new
34
- seat generation cannot inherit the previous generation's native registration.
34
+ seat generation cannot inherit the previous generation's native registration. Endpoint generations
35
+ are opaque strings, compared for equality rather than interpreted.
35
36
  Participant expressions do not publish replacement addresses.
36
37
 
37
38
  This is route preference, not permission to bypass receiver policy. Claude can
@@ -117,9 +118,10 @@ See [participant-ownership.md](participant-ownership.md).
117
118
  ## Body, admission, and presentation
118
119
 
119
120
  The coordinator uses Square's canonical audience projection and bounded body
120
- preview. Each notification identifies the square, receiving participant and
121
- activity before its event and body. A clipped preview describes catching that
122
- activity to read it in full; it never embeds shell commands or tool-call syntax.
121
+ preview. Agora notifications identify the square, receiving participant and activity before its
122
+ event and body. A clipped preview describes catching that activity to read it in full; it never
123
+ embeds shell commands or tool-call syntax. Direct Channel notifications carry their stored preview
124
+ or body instead. Channel custody and consumption use `msg/N`; Agora relations use `act/N`.
123
125
  Opaque text correlation resolves through bound memberships and the existing
124
126
  attempt ledger, never a path or asserted source from incoming text.
125
127
 
@@ -140,11 +142,12 @@ pass through. Recognized stale/cancelled deliveries can be consumed before queue
140
142
  No ambiguous send is blindly retried.
141
143
 
142
144
  The sole presentation writer observes **returned stored main user-role text**
143
- after `session.append.next`. It matches the entire expected payload within
144
- Claude's idle/busy peer framing. A complete preview records seen + presented;
145
- a clipped one records clipped only. This means stored in model context, not
146
- processed or understood. Catch/presentation races are idempotent and revalidated
147
- immediately before send and inside the observation transaction.
145
+ after `session.append.next`. The native attempt persists the payload hash and full/clipped coverage
146
+ before sending. Stored ACK matches the entire framed payload against that persisted hash and checks
147
+ the captured custody and current eligibility; it does not depend on rendering the payload again with
148
+ the current renderer. Persisted full coverage records seen + presented; clipped coverage records
149
+ clipped only. This means stored in model context, not processed or understood. Catch/presentation
150
+ races are idempotent and revalidated immediately before send and inside the observation transaction.
148
151
 
149
152
  ## Cancellation and custody
150
153
 
@@ -152,7 +155,7 @@ Explicit plugin `turn.abort` and terminal `turn.complete(reason:'aborted')`
152
155
  suppress the outstanding local batch without recording seen. Ordinary answer,
153
156
  refusal, and error completion are not user cancellation. Separate engine-owned
154
157
  family state survives hot reload, containing the abort timestamp and frozen
155
- membership generations. The artifact stores a generation-scoped monotonic activity
158
+ membership generations. The artifact stores a generation-scoped monotonic message-index
156
159
  cutoff; replacement generations cannot inherit the old abort.
157
160
 
158
161
  Engine state reads are snapshots of one dispatch. Confirmation therefore uses
@@ -40,7 +40,9 @@ an exact owner from `harnessOwner({ channel: 'codex', session })`, not a bare se
40
40
  boundary store uses Square's caller-selected `SQUARE_CODEX_BOUNDARIES` file,
41
41
  defaulting to `~/.square/codex-boundaries.json`; its JSON observations are not
42
42
  conversation storage and are not proof of current native execution or consumption.
43
- Square's format-8 artifact remains authoritative for membership, attachment and delivery evidence.
43
+ Square's format-11 artifact remains authoritative for membership, attachment and delivery evidence.
44
+ Message custody uses `msg/N`; Agora activity relations use `act/N`. Endpoint generations are opaque
45
+ and are compared for equality when fencing custody.
44
46
  Detached members appear away indefinitely and keep accumulating unread audience, but have no
45
47
  write or proactive delivery eligibility until same-owner reattachment. Only a host-confirmed
46
48
  permanent deletion uses fenced membership-ending cleanup; Codex SessionEnd is not that proof.
@@ -88,4 +88,4 @@ policy. Neither detach nor a deferral can recall an already-dispatched external
88
88
  Tests exercise foreign/stale/detached handles, same-owner restoration with unread activity intact,
89
89
  voluntary leave, explicit takeover, permanent deletion, exact-owner adapter lifecycle, generation
90
90
  fences and delivery eligibility. Assertions belong to authoritative facts, not helper ordering or
91
- display copy. Migration is offline and explicit; see [migration.md](migration.md).
91
+ display copy.
@@ -1,5 +1,7 @@
1
1
  # Row runtime delivery evidence
2
2
 
3
+ > Historical record: migration and legacy formats described below have since been removed.
4
+
3
5
  Candidate implementation: `833d6f15c9071767eb49a9562a4c42a93c6f4000` plus post-review removal of three dead runtime exports and benchmark phase baselines. Baseline: `99679eb2905dde5f282025bc7f5494f7da065e54`. This report is Deliverer evidence, **not independent review or acceptance**. Explicit migration is a separate delivery; no publication, live migration, host service change, or remote native presentation was performed.
4
6
 
5
7
  ## Deletion and replacement
@@ -1,12 +1,8 @@
1
1
  # Row-oriented artifact design
2
2
 
3
- > Historical design: the public SDK `Square.snapshot()` and its closure were retired. Snapshot-specific proposals below record the design at the time, not the current API.
3
+ > Historical, superseded design: this document records the original format-2 row-storage proposal and its former acceptance terms, not current instructions or the current API. Square artifacts now use a breaking fresh format; there is no migration command or migration support. The public SDK `Square.snapshot()` and its closure were also retired.
4
4
 
5
- **Historical accepted design for artifact format 2.** The current runtime uses format 3 for the
6
- `unlisten` event; see [Square API](square-api.md#artifact-format-and-explicit-migration) for current
7
- format/migration behavior. The schema and delivery-stage terms below record the original row-storage
8
- replacement, not a pending implementation or a second current-format definition.
9
- Source baseline: `99679eb` (0.3.70). This document specifies the design; [runtime delivery evidence](row-runtime-delivery-evidence.md) records implementation verification and actual capacity measurements. Explicit migration remains a separately accepted delivery.
5
+ Source baseline: `99679eb` (0.3.70). The schema and delivery-stage terms below record the original row-storage replacement; [runtime delivery evidence](row-runtime-delivery-evidence.md) records implementation verification and capacity measurements from that work.
10
6
 
11
7
  ## Decision in brief
12
8
 
@@ -14,14 +10,13 @@ Source baseline: `99679eb` (0.3.70). This document specifies the design; [runtim
14
10
  - Domain code owns behavior; the artifact adapter owns SQLite. Keep the public operation facade; any future daemon runs those operations and their transactions server-side, rather than transmitting callback-based storage ports.
15
11
  - Persist authority once: activities, sparse receipts, leases, ordered routes and configuration. Maintain participant/attention/audience indices atomically; do not add an inbox, cursor, eligible/notified flags, or a sidecar.
16
12
  - Keep receiver-owned discovery without guaranteed push. Background traversal must progress despite unrelated writes and revisit earlier withheld candidates on change/expiry.
17
- - Explicit `square --location <path.square> migrate` converts v1 in place in one transaction. No runtime dual format, automatic migration, daemon or socket is added.
18
- - Two acceptance boundaries: row-backed runtime, then explicit migration. Release both together. No claim of 300-process capacity until the implementation is measured.
13
+ - No claim of 300-process capacity until the implementation is measured.
19
14
 
20
- This document supersedes the exploratory inbox/snapshot sketches and temporary design reports. The domain specification below fixes interfaces/schema/algorithms; the migration and delivery terms fix failure handling and verification. The AGENTS.md amendment is proposed here and lands with runtime implementation, not as a claim about today's authority.
15
+ This historical proposal superseded exploratory inbox/snapshot sketches and temporary design reports. Its domain specification and delivery terms record the interfaces, algorithms and verification proposed at the time, not today's authority.
21
16
 
22
17
  # Domain specification
23
18
 
24
- The interfaces below are the settled private interfaces; public behavior remains unchanged. Migration and acceptance are specified later in this document.
19
+ The interfaces below describe the private interfaces proposed at the time; historical runtime acceptance is described later in this document.
25
20
 
26
21
  ## 1. Boundary and authority
27
22
 
@@ -36,7 +31,7 @@ Three layers:
36
31
  - A domain transaction wrapper implements `SquareRead`/`SquareWrite`. `land()` allocates an index and runs the single shared landing transition. This wrapper owns interpretation of domain facts, not SQL.
37
32
  - The private SQLite driver decodes typed rows, translates the finite selectors below, and applies typed landing effects. Only this driver performs artifact I/O. No SQL, row objects, statement handles, SQLite names, or transaction capabilities reach renderers/harnesses. The memory adapter implements the same capabilities and uses the same landing transition.
38
33
 
39
- There is no whole-state runtime fallback. Full integrity inspection, legacy migration, and an explicit test/export projection are exceptional bounded-by-request operations; hot callers must not invoke them.
34
+ There is no whole-state runtime fallback. Full integrity inspection and an explicit test/export projection are exceptional bounded-by-request operations; hot callers must not invoke them.
40
35
 
41
36
  ## 2. Exact private domain port
42
37
 
@@ -230,7 +225,7 @@ interface LandingFacts {
230
225
  function deriveLanding(activity: StoredAct, facts: LandingFacts): LandingEffect;
231
226
  ```
232
227
 
233
- `deriveLanding` is pure and shared by runtime and rebuild. `land()` reads the necessary narrow facts, validates structural invariants (not action admission again), allocates **header.nextActIndex**, calls this transition, and applies the effect plus nextActIndex increment atomically. Migration supplies the preserved assigned indices; it never calls the allocator or admission validation. Earlier reply author lookup uses the existing activity row; missing earlier coordinate means no author. Valid replay never requires a future author because reply < own index.
228
+ `deriveLanding` is pure and shared by runtime and rebuild. `land()` reads the necessary narrow facts, validates structural invariants (not action admission again), allocates **header.nextActIndex**, calls this transition, and applies the effect plus nextActIndex increment atomically. Earlier reply author lookup uses the existing activity row; missing earlier coordinate means no author. Valid replay never requires a future author because reply < own index.
234
229
 
235
230
  `markSeen` accepts any nonnegative index below nextActIndex, even if no activity/participant exists. It refuses unassigned coordinates and non-finite timestamps; it inserts only missing exact-owner receipts. Actions—not a receipt FK—ensure catch/native writes concern the intended activities. Lease writers similarly retain unknown/raw owner fallback. Only receipt insertion marks seen; presentation outcome, cancellation, and wake evidence do not.
236
231
 
@@ -338,7 +333,7 @@ Actor's original spelling lives in actor_json; actor_key_json is its indexed ide
338
333
 
339
334
  Route payload contains location, original participant spelling, channel, address, optional epoch, and all extra properties accepted by the v1 validator; sessionId/kind/updatedAt are reconstructed from columns. `participant_key_json` is only a derivative, not a replacement for original participant spelling. Routes have **no unique identity constraint**. Import positions are array positions; `replaceRoutes` can rewrite this small array to positions 0..n-1. Holes in positions from internal deletion are harmless provided order is retained, but the chosen runtime replacement implementation rewrites contiguous positions. No canonical-location column: legacy routes retain raw locations; current route policy canonicalizes when it currently does, and wake/native equality does not silently gain canonicalization.
340
335
 
341
- Preserve finite route epoch/extra JSON values and empty strings; do not otherwise tighten their legacy shapes. Use ordinary JSON encoding, not a bespoke numeric codec. Migration explicitly refuses non-finite numbers anywhere in a route (updatedAt, epoch, or nested extras) before DDL/inserts and leaves the artifact unchanged; never silently coerce them to null. These exponent-overflow values can pass the old permissive validator on manually authored JSON, but are not non-finite values normally persisted by the v1 JSON.stringify writer. Runtime codecs likewise require finite route numeric values. Raw schema equality is not receipt or participant equality.
336
+ Preserve finite route epoch/extra JSON values and empty strings; do not otherwise tighten their legacy shapes. Use ordinary JSON encoding, not a bespoke numeric codec. These exponent-overflow values can pass the old permissive validator on manually authored JSON, but are not non-finite values normally persisted by the v1 JSON.stringify writer. Runtime codecs likewise require finite route numeric values. Raw schema equality is not receipt or participant equality.
342
337
 
343
338
  No receipt `state` column: all receipts are seen. No additional name registry: a participant is first touched by ANY actor-bearing activity, not necessarily join.
344
339
 
@@ -350,7 +345,7 @@ Landing uses pre-activity participant/attention facts:
350
345
  3. join sets joined=true/done=false and lastJoinIndex=index. done sets joined=false/done=true and clears OUTGOING listen only. Ignore survives departure/rejoin; incoming attention is not cleared. Say increments lifetime count, even for unusual imported prejoin/postdone sequences.
351
346
  4. listen inserts listen only when not already listening; removes matching ignore. ignore removes matching listen and inserts ignore only when absent. Preserve target's first retained spelling and relation order, including unknown/self targets. A no-op legacy activity still touches actor time; replay never applies the current ten-name admission cap. Read does not acknowledge receipts or advance a persisted cursor.
352
347
 
353
- There is one production transition, no SQL triggers and no separate migration fold. Test-only frozen old fold/replay supplies differential evidence. Index integrity checking can rebuild through the production transition but cannot replace differential tests with self-comparison.
348
+ There is one production transition and no SQL triggers. Test-only frozen old fold/replay supplies differential evidence. Index integrity checking can rebuild through the production transition but cannot replace differential tests with self-comparison.
354
349
 
355
350
  Existing route policy remains domain code over `routes()` plus `replaceRoutes()`:
356
351
  - Identity is canonical location + nameKey(participant) + EXACT sessionId where routes.ts currently uses routeIdentityKey. Applying a route removes **every** matching identity and appends one new row at the tail. Nonmatching order is preserved.
@@ -428,7 +423,7 @@ No production structure below carries `.state`, all `.activities`, or a deferred
428
423
  | Claude cancellation/resume/route discovery | cancellation=max existing activity index with at<=cutoff (not assumed chronological time); use newest activity-head pages in one read txn, testing timestamps from greatest index downward and stopping at the first match. If none matches, cutoff is -1. Resume last join/done by EXACT actor spelling; no full snapshot. Routes keep first-match order. |
429
424
  | nativePendingPreview (Claude/OpenCode), WakeCurrentness | exact directedAt + joined/latestJoin/unseen receipt, routes first-match/exact epoch/address, fresh lease, captured cancellation cutoff. Generic currentness still joins selected owned routes with host evidence; does not newly consult lease. Pre-effect projection does not persist eligibility. |
430
425
  | public Square.snapshot().delivered(name,id) | explicit receiptAssignments + detached roster resolution + small header/status in ONE read txn, as below. Other production callers must not use this for count/standing. |
431
- | doctor / explicit import/export tests | full selected-row validation and replay comparison of indices; detached result includes standing count, not state for CLI header. Legacy validator lives only in explicit migration/test oracle. No automatic repair. |
426
+ | doctor / explicit import/export tests | full selected-row validation and replay comparison of indices; detached result includes standing count, not state for CLI header. No automatic repair. |
432
427
 
433
428
  ### Public SDK snapshot closure (retired)
434
429
 
@@ -446,7 +441,7 @@ Keep synchronous arbitrary `delivered(name,id)`. `snapshot()` intentionally copi
446
441
 
447
442
  ## 8. Error/transaction lifecycle (fixed)
448
443
 
449
- - Open existing artifact create-disabled; validate owned header/schema before persistent pragmas, and validate again in the transaction. New runtime refuses v1 with existing invalid_args plus migration_required recovery per lead terms; no dual read or automatic migration. Missing/unsupported/corrupt refusal semantics stay; selected row corruption is reported on access. Full doctor checks unrelated rows explicitly, rather than every hot read scanning authority.
444
+ - Open existing artifact create-disabled; validate owned header/schema before persistent pragmas, and validate again in the transaction. Missing, unsupported and corrupt artifacts are refused; selected row corruption is reported on access. Full doctor checks unrelated rows explicitly, rather than every hot read scanning authority.
450
445
  - `read` starts one SQLite read transaction and pins revision before callback. Results are detached. A busy acquisition before callback may retry after the existing 25ms cancellable yield. No callback replay once invoked. `transact` starts BEGIN IMMEDIATE, invokes once, performs domain writes/read-your-writes, and increments revision ONCE if any authoritative value changed. No-op transaction returns unchanged version/changed=false; no whole-state clone/deep-equality cycle.
451
446
  - BUSY COMMIT retries the SAME transaction/callback result. SQL/codec/callback error, thenable result, expired capability use, close, or abort before successful commit rolls back; capability is invalidated on every exit. Callback throw retains the original error. Exhausting safe nextActIndex/revision refuses before irreversible commit. If callback catches an internal driver failure, transaction is marked failed and cannot commit partial changes. A harmless domain validation exception can be caught before a write (needed by endOwnedSession's already_done/not_joined handling).
452
447
  - Per-port queued writes and reads-after-prior-writes retain current ordering; memory port has equivalent serialization/no-op/revision behavior. Close aborts busy waits, waits for queued operations, releases observers/handles, and is idempotent; changed() returns false on close. Explicit caller abort propagates its reason. No returned callback/result exposes DB lifetime.
@@ -457,23 +452,9 @@ Keep synchronous arbitrary `delivered(name,id)`. `snapshot()` intentionally copi
457
452
 
458
453
  No unresolved product decision remains for this storage design. Chosen cost tradeoffs are intentional: O(recipients) audience rows at landing (bells included), indexed exact counts/ordinals may scan keys, regex history still examines matching bodies, explicit SDK snapshot copies receipts, and complete sessionInbox remains complete. These are not promises of measured capacity. Host-ledger format/global NDJSON parsing/GC and harness scheduling improvements are excluded.
459
454
 
460
- Migration implements the schema here using the single explicit in-place transaction below; it does not invent the schema/keys/domain transition. Verification, two independently acceptable deliveries, and capacity evidence are fixed in the migration and delivery terms below. Receipt lookup uses exact canonical roster spelling; route ordering/duplicates are retained; no mandatory backup or --check/--backup/max-workers configuration is introduced.
455
+ The historical delivery terms below accompanied the domain specification above.
461
456
 
462
- # Migration and delivery terms
463
-
464
- These terms apply together with the domain specification above.
465
-
466
- ## Migration protocol
467
-
468
- - Only `square --location <path.square> migrate`. No --check, --backup, --force, auto-migrate, bulk mode, separate lock database, sidecar, daemon, or runtime dual reader. An operator can make an offline backup with ordinary tooling; the command does not invent a backup lifecycle.
469
- - application_id remains 0x53515245; user_version 2 identifies rows. Normal new-format reads/writes refuse version 1 with invalid_args / reason migration_required and descriptive offline-migration guidance. The CLI adds the shell-quoted recovery command; native tool errors do not embed invocation syntax. build --force does not bypass it. Unknown/unrelated/invalid formats are refused, not repaired.
470
- - `doctor` remains read-only: recognizes legacy v1 and prints the migration recovery command (exit 2); validates v2 fully, including a replay comparison of derived indices. It must not imply that legacy v1 is damaged. Directory/list probing retains omission semantics for unsupported files; no new implicit migration/discovery subsystem.
471
- - Open existing canonical path create-disabled. A read-only preflight establishes owned known schema/version before any persistent pragma or DDL. Require existing DELETE journal mode, refuse another mode without changing it; the shipped v1 creator/writer already establishes DELETE. Set connection busy_timeout=0 and synchronous=FULL. Acquire BEGIN IMMEDIATE, re-check format/schema under the lock, and validate the full v1 snapshot inside it. If v2 is already present and has valid framing/header, return already-format-2 without changing revision. A second migrator follows this same in-lock check.
472
- - Use v1 validation retained ONLY in migration (test oracle may also retain it), plus one explicit restriction: non-finite numbers anywhere in a route (including nested extras) are unsupported input, refused before DDL/inserts with the artifact untouched. They are not normally persisted as non-finite values by the v1 JSON.stringify writer; do not add a bespoke overflow-number codec or silently coerce to null. Copy normally persisted authoritative facts losslessly, preserving revision and nextActIndex, activity indices/gaps and optional field distinctions, raw receipt/lease owner keys, route order/duplicates, strings and finite fractional timestamps. Absent routes and [] both become zero rows; empty receipt-owner maps are behaviorless and may become zero receipt rows. Do not canonicalize receipts or add foreign keys that reject accepted v1 facts.
473
- - Actual receipt lookup is exact canonical roster spelling, not lowercase nameKey: preserve the raw owner-key relation and resolve lookup via the domain. Free-form JS strings must survive SQLite binding; JSON string encoding (including for key strings where necessary) preserves lone surrogates. All normalized lookup keys come from domain nameKey, never SQLite LOWER.
474
- - Create v2 tables and insert authority. Build derived participant/attention/audience facts with the SAME single-step domain transition used by runtime landing (admission checks are NOT replayed). Check insert/constraint failures normally; do not add a second full replay or a second in-memory copy just to validate the function against itself. Lossless authority equality and old-replay equivalence are migration tests; doctor can explicitly recompute indices for integrity checking. Drop square_snapshot. Set user_version=2 inside the same transaction. Commit once; nothing is published piecemeal.
475
- - Busy acquisition/read retries yield using existing 25ms retry and operation cancellation. Busy COMMIT retries the same transaction; never rerun copy or domain callback. Error/abort before successful COMMIT rolls back. Process death before commit recovers v1 through SQLite journal; after commit leaves complete v2. Preserve path/inode/registry identity. No host-ledger mutation and no synthetic activity.
476
- - Storage exclusion is guaranteed for the shipped SQLite v1 runtime because it validates again after BEGIN IMMEDIATE: its write commits before migration, or it sees v2 and refuses afterward. A pre-migration read can finish with its old snapshot. Migration does not revoke in-flight remote delivery or stop processes; recommend stopping/upgrading attached runtimes for an operationally quiet migration. Arbitrary external path replacement and pre-SQLite binaries are outside the artifact update protocol. Do not claim a distributed transaction or exactly-once remote delivery.
457
+ # Historical delivery terms
477
458
 
478
459
  ## Independent discovery and concurrency
479
460
 
@@ -485,26 +466,22 @@ These terms apply together with the domain specification above.
485
466
 
486
467
  ## Acceptance boundary and verification
487
468
 
488
- Two independently acceptable implementations, not one aggregate:
489
- 1. Row-backed runtime: new format creation, domain port and single transition, all production callers moved, old whole-state runtime path removed, v1 refusal/doctor recovery, public behavior preserved and cost evidence.
490
- 2. Explicit v1 migration: depends on the settled v2 schema/transition; migration CLI and transactional preservation/recovery evidence. Core v2 behavior can be accepted on newly created artifacts without migration; migration is independently accepted on v1 fixtures. Release should ship both together so existing users have the recovery command.
491
- Host-ledger format/GC, daemon/socket service, new notification delivery semantics, version pinning, and publication are excluded.
469
+ The historical row-backed runtime delivery covered new format creation, a domain port and single transition, moving production callers, removal of the old whole-state runtime path, refusal of old formats, public behavior and cost evidence. Host-ledger format/GC, daemon/socket service, new notification delivery semantics, version pinning, and publication were excluded.
492
470
 
493
471
  ### Mandatory deletion and simplification acceptance
494
472
 
495
473
  This is a replacement, not an additive adapter layer. Acceptance MUST reject an implementation that leaves the unnecessary old machinery in place even if behavior tests pass.
496
474
 
497
475
  - Remove the production whole-state read/transact/snapshot-replacement path, full-state clones/deep-equality write detection, replay-per-operation delivery/perception closures, obsolete `FromState`/delta bridges, and `.state`/whole-history renderer inputs replaced by the caller map. Delete dead callers, exports and tests of removed implementation details; retain behavioral coverage.
498
- - One production landing transition and one definition of each domain predicate. No parallel old/new runtime paths, compatibility wrappers, generic query framework, duplicate conversion layers, or unsupported defensive branches. The v1 decoder exists ONLY for explicit migration; frozen legacy semantic oracles are test-only. Full doctor/export and explicit SDK snapshot exceptions are narrow capabilities, not runtime fallbacks.
499
- - Hand-written production source must be net smaller than pre-change baseline `99679eb2905dde5f282025bc7f5494f7da065e54`, both for the runtime candidate and the final combined runtime+migration candidate. Migration adds only its necessary one-time conversion code and must fit that combined reduction; it need not be net-negative relative to the already reduced runtime candidate. Count tracked production `.ts`, `.js`, `.mjs` files; exclude tests/fixtures, scripts, documentation, generated output, vendored references and dependencies. No unrelated deletions, moving production code into excluded paths, code minification, formatting-only reductions or removing behavioral tests to game the result.
500
- - Delivery evidence includes the deletion/replacement map (old mechanism → replacement or removal), remaining legacy-reference search with justified migration/test-only exceptions, and production additions/deletions/net delta against the fixed baseline. Independent review judges unnecessary abstraction and duplication in addition to correctness. A passing test suite or negative line count alone cannot waive this criterion; unexplained retained obsolete code or net growth is a rejection, not deferred cleanup.
476
+ - One production landing transition and one definition of each domain predicate. No parallel old/new runtime paths, compatibility wrappers, generic query framework, or unsupported defensive branches. Full doctor/export and explicit SDK snapshot exceptions are narrow capabilities, not runtime fallbacks.
477
+ - Hand-written runtime production source was to be net smaller than pre-change baseline `99679eb2905dde5f282025bc7f5494f7da065e54`. Count tracked production `.ts`, `.js`, `.mjs` files; exclude tests/fixtures, scripts, documentation, generated output, vendored references and dependencies. No unrelated deletions, moving production code into excluded paths, code minification, formatting-only reductions or removing behavioral tests to game the result.
478
+ - Delivery evidence includes the deletion/replacement map (old mechanism → replacement or removal) and production additions/deletions/net delta against the fixed baseline. Independent review judges unnecessary abstraction and duplication in addition to correctness. A passing test suite or negative line count alone cannot waive this criterion; unexplained retained obsolete code or net growth is a rejection, not deferred cleanup.
501
479
 
502
480
  Minimum meaningful evidence (not a Cartesian test matrix):
503
481
  - Differential trace covering mention/reply/listen/ignore/bell/done/rejoin: maintained indices equal the frozen v1 replay oracle (test-only), including route precedence and roster order. Comparing the new transition to itself does not count as semantic evidence. One shared production transition, no SQL trigger policy.
504
482
  - Sparse receipt scenario: earlier unseen hole, later filtered/exact catch, repeat exact catch no write, pre-rejoin catch versus post-rejoin notification, truthful remaining and cursor/behind/presence distinction. Filter before limit; history context uses existing activity positions.
505
483
  - Two-process transaction race and short recovery tests: concurrent catches do not double-consume ordinary catch; atomic activity+audience; abort/rollback and commit-busy callback runs once. Existing native epoch/cancel/claim-before-send/after-send tests stay green; no stronger distributed guarantee claimed.
506
484
  - Discovery scenario with hints disabled and push absent, including an early withheld candidate and a later eligible one; expiry alone re-enables the earlier candidate. Verify failed evidence does not busy-loop. Preserve Pi omitted notification behavior.
507
- - Migration: one representative lossless legacy fixture including gaps/orphan receipts/case keys and optional fields; second run no-op; invalid input no writes; concurrent v1 writer/version gate; process death before commit rolls back. Use actual old artifact implementation or pinned installed binary for old-writer evidence, not v2 code pretending to be old.
508
485
  - Capacity evidence: adapt existing scripts/benchmark-idle-wait.mjs rather than add a daemon or general benchmark framework. Permit 300 workers directly (no max-workers config). Same artifact, 300 independent processes and shared synthetic host ledger. Run idle, then active bell discovery with push absent/hints disabled, then simultaneous catches. Report actual readiness count, completions, revision/selected-row instrumentation with positive controls, hydrated rows/bytes, CPU, busy/commit duration, discovery latency and ledger work separately. Bound run and fail loudly on incomplete workers; do not silently lower count. Existing 20s discovery window is a probe deadline, not an SLA. Compare small/larger unrelated histories to establish no full-history hydration on recipient hot reads; SQL exact counts may still scan index entries. Update instrumentation: old square_snapshot regex otherwise falsely counts zero after v2. No capacity success claim before running on implemented code.
509
486
  - Commands after implementation: npm test (already sandboxed); npm run test:cli-process; explicit benchmark via node --import ./test/sandbox-env.js scripts/benchmark-idle-wait.mjs. No live registry/session identities or native remote delivery during probes.
510
487
 
@@ -516,7 +493,7 @@ This is an explicit proposed amendment authorized by the requested boundary rede
516
493
 
517
494
  ## Binding plan
518
495
 
519
- The current lead agent remains holder of both deliveries. Assign implementation hands independently from acceptance boundaries; the reviewer of a candidate must not be its deliverer. Use both `reviewed` and `verified` gates. Do not bind an aggregate storage-plus-migration contract.
496
+ The historical runtime plan assigned implementation and acceptance independently: the reviewer of a candidate was not its deliverer, and both `reviewed` and `verified` gates applied.
520
497
 
521
498
  **Runtime delivery Region:**
522
499
  ```text
@@ -556,9 +533,7 @@ guides/change-waits.md
556
533
  ```
557
534
  These are planning regions, not a requirement to edit every listed file. Host-ledger persistence and packages/agent-delivery transport internals are excluded. New private domain/artifact helper modules use the existing `square-` family; no generic query framework is introduced.
558
535
 
559
- **Migration delivery Region:** `artifact.ts`, `square-storage.ts`, the new private migration module `square-migration.ts`, `square-state.ts` for isolated v1 validation, `model.ts`, `cli/maintenance-commands.ts`, `cli/registry.ts`, `cli/program.ts`, `help.ts`, `test/migration.test.js`, its `test/fixtures/**`, and migration documentation. Depends on the runtime delivery's v2 schema/codec/shared transition. Sharing files is coordination, not an extra dependency.
560
-
561
- Verification declarations for both delivery snapshots include `npm test` and `npm run test:cli-process` (sandboxed by their scripts), with timeouts chosen from actual baseline duration rather than arbitrarily cutting off tests. Runtime evidence additionally runs the adapted benchmark:
536
+ The historical runtime verification declarations included `npm test` and `npm run test:cli-process` (sandboxed by their scripts), with timeouts chosen from actual baseline duration rather than arbitrarily cutting off tests. Runtime evidence also included the adapted benchmark:
562
537
  ```sh
563
538
  node --import ./test/sandbox-env.js scripts/benchmark-idle-wait.mjs --workers 300 --mode session
564
539
  node --import ./test/sandbox-env.js scripts/benchmark-idle-wait.mjs --workers 300 --mode session --active --no-hints