@astrosheep/square 0.3.70 → 0.3.72

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 (126) hide show
  1. package/dist/activity-feed.d.ts +4 -5
  2. package/dist/activity-feed.js +14 -10
  3. package/dist/artifact.d.ts +26 -33
  4. package/dist/artifact.js +346 -317
  5. package/dist/attention-presentation.js +2 -9
  6. package/dist/automatic-session.js +6 -6
  7. package/dist/boundary-presentation.js +3 -3
  8. package/dist/catch-decisions.d.ts +19 -12
  9. package/dist/catch-decisions.js +32 -68
  10. package/dist/claude-delivery.js +7 -7
  11. package/dist/claude-mod.js +18 -7
  12. package/dist/cli/catch-presentation.d.ts +7 -0
  13. package/dist/cli/catch-presentation.js +55 -0
  14. package/dist/cli/context.d.ts +1 -1
  15. package/dist/cli/context.js +5 -23
  16. package/dist/cli/express-presentation.d.ts +10 -0
  17. package/dist/cli/express-presentation.js +196 -0
  18. package/dist/cli/maintenance-commands.d.ts +4 -0
  19. package/dist/cli/maintenance-commands.js +29 -6
  20. package/dist/cli/observation-commands.d.ts +7 -5
  21. package/dist/cli/observation-commands.js +275 -262
  22. package/dist/cli/program.d.ts +1 -1
  23. package/dist/cli/program.js +43 -56
  24. package/dist/cli/registry.js +2 -1
  25. package/dist/cli/square-commands.d.ts +3 -9
  26. package/dist/cli/square-commands.js +134 -255
  27. package/dist/codex-queue.js +4 -1
  28. package/dist/decisions.d.ts +26 -74
  29. package/dist/decisions.js +190 -335
  30. package/dist/delivery-health.js +13 -22
  31. package/dist/delivery-operations.d.ts +0 -11
  32. package/dist/delivery-operations.js +44 -33
  33. package/dist/delivery.d.ts +33 -32
  34. package/dist/delivery.js +70 -81
  35. package/dist/help.js +6 -1
  36. package/dist/inbox.d.ts +27 -0
  37. package/dist/inbox.js +55 -18
  38. package/dist/index.d.ts +2 -4
  39. package/dist/index.js +1 -1
  40. package/dist/list.d.ts +7 -1
  41. package/dist/list.js +49 -122
  42. package/dist/mcp.d.ts +1 -1
  43. package/dist/mcp.js +7 -37
  44. package/dist/model.d.ts +4 -44
  45. package/dist/model.js +1 -3
  46. package/dist/notifications.d.ts +1 -1
  47. package/dist/notifications.js +13 -7
  48. package/dist/open-square.d.ts +16 -2
  49. package/dist/open-square.js +40 -1
  50. package/dist/packages/agent-delivery/src/claude.d.ts +2 -11
  51. package/dist/packages/agent-delivery/src/index.d.ts +2 -42
  52. package/dist/packages/agent-delivery/src/opencode.d.ts +2 -11
  53. package/dist/packages/agent-delivery/src/paseo.d.ts +2 -13
  54. package/dist/packages/agent-delivery/src/pi-client.d.ts +2 -9
  55. package/dist/packages/agent-delivery/src/types.d.ts +42 -0
  56. package/dist/participant-host.d.ts +6 -3
  57. package/dist/participant-host.js +44 -38
  58. package/dist/perception-projection.d.ts +6 -15
  59. package/dist/perception-projection.js +6 -26
  60. package/dist/plugins/opencode/delivery.js +9 -9
  61. package/dist/plugins/opencode/index.js +3 -3
  62. package/dist/ports.d.ts +156 -11
  63. package/dist/presentation-operations.d.ts +1 -1
  64. package/dist/presentation-operations.js +35 -44
  65. package/dist/presentation.d.ts +12 -19
  66. package/dist/presentation.js +33 -54
  67. package/dist/registry.d.ts +2 -0
  68. package/dist/registry.js +1 -1
  69. package/dist/routes.d.ts +7 -14
  70. package/dist/routes.js +34 -72
  71. package/dist/runtime.d.ts +12 -39
  72. package/dist/runtime.js +33 -164
  73. package/dist/square-actions.d.ts +11 -21
  74. package/dist/square-actions.js +171 -275
  75. package/dist/square-application.d.ts +31 -55
  76. package/dist/square-application.js +625 -141
  77. package/dist/square-core.d.ts +3 -94
  78. package/dist/square-core.js +8 -353
  79. package/dist/square-domain.d.ts +24 -0
  80. package/dist/square-domain.js +77 -0
  81. package/dist/square-facade.d.ts +360 -9
  82. package/dist/square-migration.d.ts +24 -0
  83. package/dist/square-migration.js +211 -0
  84. package/dist/square-projections.d.ts +2 -42
  85. package/dist/square-projections.js +1 -37
  86. package/dist/square-sqlite.d.ts +59 -0
  87. package/dist/square-sqlite.js +702 -0
  88. package/dist/stream.d.ts +3 -10
  89. package/dist/stream.js +81 -52
  90. package/dist/views.d.ts +27 -95
  91. package/dist/views.js +217 -87
  92. package/dist/wake-eligibility.d.ts +15 -5
  93. package/dist/wake-eligibility.js +32 -16
  94. package/dist/wakes.d.ts +3 -3
  95. package/dist/wakes.js +31 -27
  96. package/guides/application-facade-delivery-evidence.md +200 -0
  97. package/guides/application-facade-design.md +95 -0
  98. package/guides/change-waits.md +4 -4
  99. package/guides/migration.md +77 -0
  100. package/guides/postcommit-simplification-performance.md +36 -0
  101. package/guides/primitive-catch-consolidation.md +85 -0
  102. package/guides/primitive-history-consolidation.md +76 -0
  103. package/guides/primitive-status-consolidation.md +87 -0
  104. package/guides/primitive-storage-consolidation.md +128 -0
  105. package/guides/row-runtime-delivery-evidence.md +160 -0
  106. package/guides/row-storage-design.md +567 -0
  107. package/package.json +1 -1
  108. package/plugins/claude/.claude-plugin/plugin.json +1 -1
  109. package/plugins/codex/.codex-plugin/plugin.json +1 -1
  110. package/plugins/opencode/delivery.ts +11 -11
  111. package/plugins/opencode/index.ts +3 -3
  112. package/plugins/paseo/client/square-message.tsx +77 -64
  113. package/plugins/paseo/shared/message.ts +16 -0
  114. package/plugins/pi/square-pi.js +5 -1
  115. package/dist/activity.d.ts +0 -14
  116. package/dist/activity.js +0 -248
  117. package/dist/square-file-adapter.d.ts +0 -26
  118. package/dist/square-file-adapter.js +0 -85
  119. package/dist/square-state.d.ts +0 -6
  120. package/dist/square-state.js +0 -138
  121. package/dist/square-storage.d.ts +0 -14
  122. package/dist/square-storage.js +0 -188
  123. package/dist/square-wiring.d.ts +0 -33
  124. package/dist/square-wiring.js +0 -109
  125. package/dist/watch.d.ts +0 -8
  126. package/dist/watch.js +0 -252
@@ -0,0 +1,200 @@
1
+ # Shared application boundary: delivery evidence
2
+
3
+ Deliverer evidence, **not independent review or acceptance**. Design and the complete caller/deletion map are in [application-facade-design](application-facade-design.md).
4
+
5
+ ## Candidate coordinates
6
+
7
+ - Fixed baseline and observed target `main`: `52b58eb9f901f0458302e6120cd83b1079f8ba1c`.
8
+ - Production/test implementation commit: `69b0320031b112f220a80180f607c0deb1beeccd` — `Keep raw drafts independent of a failing application clock` (on top of the owner consolidation `8ecf99cd1e7f4eeb5399f1e9de12f5d901250e9c`).
9
+ - Measured on 2026-10-15 at 09:23 CST (Beijing time). This evidence is a documentation-only descendant of that implementation. The tender receipt identifies the final candidate; rerun the recipe on that candidate. Documentation does not enter this count.
10
+ - No unrelated target changes are included. The seven narrowly amended paths implement captured wake environment, build cancellation propagation, and retired-interface test migration only; no schema/framing/native-protocol changes.
11
+
12
+ The application factory now returns explicit `{data, projection}` outcomes (except the pull-based stream). This intentionally replaces its old return contract, not the supported SDK resource shapes or MCP wire envelopes. MCP serializes `data`, never the outcome envelope or private projection. SDK handles call shared semantic owners directly, without building application projections.
13
+
14
+ ## Exact committed production count
15
+
16
+ The Contract recipe was run against the committed implementation, including both new CLI files. Result: **110 production files, 13,934 physical lines, 733,438 bytes; line delta −7**. Bytes increased by 16,488; bytes are reported, not a separate gate. The negative margin is small; no larger reduction is claimed.
17
+
18
+ Exact recipe (git objects, no checkout edits):
19
+
20
+ ```python
21
+ import subprocess
22
+ from pathlib import PurePosixPath
23
+
24
+ BASE = '52b58eb9f901f0458302e6120cd83b1079f8ba1c'
25
+ CANDIDATE = 'HEAD' # Run on the committed integration candidate being reviewed.
26
+ EXCLUDED_DIRS = {
27
+ 'test', 'tests', '__tests__', 'fixture', 'fixtures', '__fixtures__',
28
+ 'script', 'scripts', 'dist', 'build', 'out', 'coverage',
29
+ 'vendor', 'vendors', 'node_modules', 'generated',
30
+ 'docs', 'doc', 'guides', 'skills', '.agents', '.keiyaku', '.git',
31
+ }
32
+ EXCLUDED_NAME_PARTS = ('.test.', '.spec.', '.generated.', '.gen.')
33
+
34
+ def production(name):
35
+ path = PurePosixPath(name)
36
+ return (
37
+ path.suffix in {'.ts', '.js', '.mjs'}
38
+ and not any(part in EXCLUDED_DIRS for part in path.parts[:-1])
39
+ and not any(part in path.name for part in EXCLUDED_NAME_PARTS)
40
+ )
41
+
42
+ def snapshot(revision):
43
+ names = subprocess.check_output([
44
+ 'git', 'ls-tree', '-r', '-z', '--name-only', revision,
45
+ ]).decode().split('\0')
46
+ result = {}
47
+ for name in names:
48
+ if name and production(name):
49
+ body = subprocess.check_output(['git', 'show', f'{revision}:{name}'])
50
+ lines = body.count(b'\n') + int(bool(body) and not body.endswith(b'\n'))
51
+ result[name] = (lines, len(body))
52
+ return result
53
+
54
+ before = snapshot(BASE)
55
+ after = snapshot(CANDIDATE)
56
+ for label, data in [('baseline', before), ('candidate', after)]:
57
+ print(label, 'files', len(data), 'lines', sum(v[0] for v in data.values()),
58
+ 'bytes', sum(v[1] for v in data.values()))
59
+ for name in sorted(before.keys() | after.keys()):
60
+ left = before.get(name, (0, 0))
61
+ right = after.get(name, (0, 0))
62
+ if left != right:
63
+ print(f'{right[0] - left[0]:+7d} lines {right[1] - left[1]:+9d} bytes {name}')
64
+ delta = sum(v[0] for v in after.values()) - sum(v[0] for v in before.values())
65
+ print('production line delta', delta)
66
+ if delta >= 0:
67
+ raise SystemExit('FAIL: production source is not net-negative against the fixed baseline')
68
+ ```
69
+
70
+ Exact stdout (including every changed production path):
71
+
72
+ ```text
73
+ baseline files 111 lines 13941 bytes 716950
74
+ candidate files 110 lines 13934 bytes 733438
75
+ -271 lines -13402 bytes activity.ts
76
+ +3 lines +167 bytes artifact.ts
77
+ +0 lines +5 bytes automatic-session.ts
78
+ +0 lines +7 bytes catch-decisions.ts
79
+ +0 lines +5 bytes claude-mod.ts
80
+ +68 lines +3581 bytes cli/catch-presentation.ts
81
+ -17 lines -726 bytes cli/context.ts
82
+ +206 lines +12163 bytes cli/express-presentation.ts
83
+ -1 lines +114 bytes cli/maintenance-commands.ts
84
+ +10 lines +1405 bytes cli/observation-commands.ts
85
+ -7 lines -32 bytes cli/program.ts
86
+ -150 lines -6582 bytes cli/square-commands.ts
87
+ +3 lines +181 bytes codex-queue.ts
88
+ -22 lines -273 bytes decisions.ts
89
+ -21 lines -511 bytes index.ts
90
+ -103 lines -3235 bytes list.ts
91
+ -29 lines -1998 bytes mcp.ts
92
+ +3 lines +243 bytes model.ts
93
+ +0 lines +46 bytes notifications.ts
94
+ +0 lines +5 bytes plugins/opencode/index.ts
95
+ -11 lines -280 bytes presentation.ts
96
+ +43 lines +1940 bytes square-actions.ts
97
+ +478 lines +24632 bytes square-application.ts
98
+ +233 lines +15186 bytes square-facade.ts
99
+ +1 lines +83 bytes square-file-adapter.ts
100
+ +0 lines +60 bytes square-storage.ts
101
+ -136 lines -6338 bytes square-wiring.ts
102
+ +23 lines +1407 bytes stream.ts
103
+ +18 lines +2606 bytes views.ts
104
+ +0 lines +90 bytes wakes.ts
105
+ -328 lines -14061 bytes watch.ts
106
+ production line delta -7
107
+ ```
108
+
109
+ ### What actually disappeared
110
+
111
+ - `square-wiring.ts` (136 lines) is deleted, not a forwarding shim. `Square` and participant resources live with the application owner.
112
+ - Root `activity.ts` (271 lines) and `watch.ts` (328 lines) are deleted. Their surviving draft/retry/rendering code is counted in the new CLI helpers (206 + 68 lines); moving renderers is not claimed as semantic deletion.
113
+ - CLI build/join/listener/lifecycle/history/status/catch no longer open storage for admission, before/after facts, projections or sweep coordination. `cli/context.ts` no longer constructs a ledger or discovers bindings during parsing. Application `selected` captures an actor per operation, not a mutable-binding cache.
114
+ - Catch has one leased quiet-wait owner; the old action absolute-idle loop and CLI heartbeat/revision/finish wrappers are removed. Selection carries records/ordinals/header facts in its receipt transaction. Optional nearby presence does not rehydrate the selected page.
115
+ - Express has one preparation/reentry and retry/commit owner. It selects the pending directed feed once, and uses commit-observed count/hold/cap facts rather than rebuilding that feed or issuing a duplicate post-success header query.
116
+ - MCP `publicResult`, stored-activity conversion and status-result policy are deleted. Private producers reuse the facade DTOs instead of maintaining parallel status/unread declarations.
117
+ - Deleted unused `Square.joinWithActivity`, `takeoverWithActivity`, `joinFacts`, `standingCount`; deleted `views.activityPresentation`, `standingCount`, `joinFacts`, `watchPresentation`, and `presentation.renderWatchOutput`. Focused `recoveryObservation` and optional `catchPresence` replace the displaced mixed queries. Supported SDK/session methods remain.
118
+ - `list.ts` no longer parses argv or writes process output; `stream.ts` no longer owns stdout/drain. The CLI owns those adaptations.
119
+
120
+ No minification, packed orchestration, bulk whitespace/comment deletion, excluded-path offloading, extension changes, vendor/symlink indirection or unrelated production deletion was used. Explicit DTOs, receipt observations, iterator disposal and cancellation propagation account for additions; the semantic removals above must be judged as well as the small negative total.
121
+
122
+ ## Reference and dependency evidence
123
+
124
+ Reference searches ran over every tracked production path selected by the recipe's `production` predicate. For each pattern, invocation was `subprocess.run(['rg', '-n', '--', pattern, *paths], text=True, capture_output=True)`. Adapter search restricted paths to `cli/**` and `mcp.ts`; contract search used `square-facade.ts`. Exit 1 below means no matches, not a hidden error.
125
+
126
+ ```text
127
+ ## deleted module imports
128
+ pattern: (?:from\s*|import\s*\(\s*)['"][^'"]*(?:square-wiring|/activity|/watch)\.js['"]
129
+ (no matches)
130
+ rg exit: 1
131
+
132
+ ## retired names
133
+ pattern: \b(?:joinWithActivity|takeoverWithActivity|joinFacts|activityPresentation|watchPresentation|renderWatchOutput|cmdListSquares|cmdStreamSquare|publicResult|publicActivity)\b
134
+ (no matches)
135
+ rg exit: 1
136
+
137
+ ## private action imports
138
+ pattern: from\s*['"][^'"]*square-actions\.js['"]
139
+ square-application.ts:14:import { catchUp, done, endOwnedSession, express, hold, ignore, implicitJoin, join, takeover, listen, listening, resume, retireEndedSessionRoutes, type ExpressCommittedResult } from './square-actions.js';
140
+ rg exit: 0
141
+
142
+ ## adapter direct private execution
143
+ pattern: (?:from\s*|import\s*\(\s*)['"][^'"]*(?:square-storage|square-file-adapter|square-actions|views|wakes|notifications|delivery-operations|registry|list|stream)\.js['"]
144
+ cli/program.ts:9:import { executeRegisteredCommand, findCommand } from './registry.js';
145
+ rg exit: 0
146
+
147
+ ## facade derived contracts
148
+ pattern: (?:ReturnType|Awaited)\s*<
149
+ (no matches)
150
+ rg exit: 1
151
+ ```
152
+
153
+ The adapter grep's sole match resolves to **`cli/registry.ts`**, the argv registry, not the root host-binding `registry.ts`. The AST dependency test resolves paths instead of mistaking equal basenames for equal ownership.
154
+
155
+ `test/architecture-boundary.test.js` passed the transitive adapter/helper traversal and its deliberate hidden-bypass fixtures. It checks all CLI roots, MCP and presentation helpers; permits only named pure bindings (core IDs, immutable held limit, model syntax/errors, identity formatting, search formatting) and closed protocol edges (harness, native hook I/O, MCP immutable `operationEnv`). It rejects private execution hidden through nested helpers, namespace/extra mixed-module bindings, an exceeded native exception and unbounded imports. These are not blanket directory exemptions. Existing storage-boundary/synchronous-capability tests also pass.
156
+
157
+ ## Closure map for pre-delivery findings
158
+
159
+ These are deliverer closures, not a reviewer verdict. Rows distinguish behavior tests from source inspection; passing a nearby test is not claimed to prove a different edge.
160
+
161
+ | Finding | Implementation and evidence |
162
+ | --- | --- |
163
+ | Status loses configured/discovered viewer | Application `status` resolves optional viewer without joining/claiming; `statusPresentation` settles perception. `application-boundary`: configured/discovered status viewer fixture compares directed bodies and unchanged ownership/artifact; `projections`: viewer perception and exact-spelling rejoin annotations. CLI uses that perception, not audience-law fallback. |
164
+ | Idle completion fabricates null cursor/zero remaining | `catchOwned.complete` uses committed selection data, or reads authoritative cursor/count only when no selection result exists. `application-boundary`: quiet expiry asserts the existing consumed cursor, including after an actual delivered say; `catch-id`: exact acknowledgement is repeatable and incompatible options do not consume. |
165
+ | Stream return hangs behind quiet next | Per-iterator disposal aborts before generator return; observer closes in finally. `application-boundary`: an outstanding quiet pull and `return()` both finish without activity or caller abort. `stream.ts` is pull-based and contains no stdout/drain. |
166
+ | Captured clock became loose Number conversion | `clockFor` retains parseInt + finite coded validation; injected clock wins. `application-boundary`: malformed and blank env clock refusal plus injected override. CLI relative-time decoding uses `app.now`. |
167
+ | Blank participant env stops discovery | Explicit context still validates; blank env falls through to the injected ledger. `application-boundary`: discovery fixture deliberately supplies `SQUARE_PARTICIPANT_NAME: ''` with a ledger outside the env root. History does not select an actor to choose its limit. |
168
+ | Selected/discovered actor lost in errors; generic operation masks express/catch | Named `selected` keeps this attempt's actor and preserves only matching operation detail; inner join enrichment retains canonical committed actor. `application-boundary`: real open failure after explicit/discovered selection proves `express/unsent/Alice`, no mutation. Catch filter/caller distinction has structured refusal assertions. Join actor propagation is also inspected in `selected`/`join`. |
169
+ | Actor discovery cached across binding changes | No actor cache. Reused-app fixture joins Alice, leaves, binds Bob, then expresses as current Bob without reentering Alice or claiming a second name. |
170
+ | Join count derived by racy pre-read arithmetic | `square-actions.join` returns known joined-or-done count from its authoritative join transaction; takeover returns the same fact from its atomic done+join transaction. `joinOwned` uses returned count, never adds to a pre-read. Verified by transaction/source inspection; existing concurrent-owner/join tests remain passing. Standing headers remain distinct. |
171
+ | Express cleanup/enrichment erases commit or calls it unsent | Resource close cannot replace a completed result. Action route/host publication is best effort after commit. Commit observation replaces duplicate post-read. Boundary fixtures prove postcommit host-publication failure returns the activity, projection-clock failure retains landed ID without replay, and selected-row corruption is unknown rather than proven unsent. Operation-cancellation has before-return commit abort coverage. |
172
+ | Catch completion/enrichment erases a committed page | Raw page, ordinals/count/cap/hold/terminal facts travel with receipt selection; completion never rereads them. Only optional `catchPresence` can be unavailable. `performance`: real selection hydrates exactly its page; presence/rendering adds no hydration/reads. Operation-cancellation preserves committed consumption after abort. |
173
+ | Replaced/cancelled waiter consumes later activity or releases new lease | Catch selection transaction checks lease ID. Finally cleanup is non-aborted and ID-fenced. Boundary fixtures prove replacement owns consumption, old waiter returns replaced, cancelled waiter releases lease, later attention stays pending. Hold/expiry and CLI watch-wait heartbeat fixtures pass. |
174
+ | SDK projection roundtrip / leaked observations | SDK express uses `prepareExpression` + `landExpression`, strips observation/waited and retains delivery; SDK catch uses `catchOwned` and returns only established CatchResult. SDK test asserts established fields and avoids application body projections. SDK Square history stays unbounded, Participant recent-ten; parity history fixture proves both, and projection test preserves detached delivered predicate. |
175
+ | Duplicate contracts, aliases and dead mixed views | Private status/unread producers import/re-export facade contracts; catch observation extends shared expression facts and enriched projection reuses it; required express participant replaces name alias. Retired helper search is empty. Recovery selects only gates/bounded unread summaries, not discarded feed/ordinals/perceptions. |
176
+ | Packed owner orchestration hides effects/count integrity | History, lifecycle branches, maintenance/discovery/recovery, catch conflict and SDK recognize are expanded into readable steps. Remaining one-line SDK delegates are supported simple resource calls, not packed async policy. Inspect implementation diff; all new source is included in count. |
177
+ | Invalid reply / missing reach / done repair regressions | Typed `invalid_reply` covers malformed and valid-but-absent IDs; typed reach/done reasons stay domain facts, CLI owns glyphs/flags. Express-recovery tests execute printed repaired commands, preserving raw drafts and other recipients; missing reach offers executable `--no-mention`; done ends scoped help. Unknown/landed effects offer reconciliation, never replay. |
178
+ | Failing application clock prevents draft creation | `executeExpression` uses `saveActivityDraft`'s transport-local `Date.now` default, never the failed owner clock. Focused `express-recovery` fixture supplies a throwing clock and landed error plus throwing recovery; exact CRLF raw is already saved at recovery invocation, landed ID remains in history reconciliation, and no replay is offered. |
179
+ | Captured default wake stops at adapter or executable selection | Amended `defaultWakeAdapters(env)` builds `CodexQueueAdapter({env})`; queue executable comes from explicit bin, else supplied env, never later ambient env. Boundary test uses a real isolated fake executable and captured child environment/queue destination after global mutation; injected port wins. No real native delivery. |
180
+ | Force-build ignores cancellation under lock | Amended build/create signal reaches existing lock retries and transaction boundaries; abort checked before public link, cleanup signal-free, no postcommit rejection. Real exclusive-lock fixture cancels, unlocks, and proves unchanged snapshot/no delayed rebuild/no temporary artifact. Separate published-link fixture aborts after commit and still gets the build result. |
181
+ | Removed helper tests / package contract | Obsolete consumers moved to actual application/renderer boundaries, not production stubs. Full suite includes packed ESM root import + TypeScript consumer + unsupported deep-import denial, native import migration, ownership/storage/migration and receipts. |
182
+
183
+ ## Verification on the implemented source
184
+
185
+ Both declared suites were run serially using repository scripts (sandbox preload), with no live native-session notification or new capacity probe.
186
+
187
+ | Command | Result | Local raw log |
188
+ | --- | --- | --- |
189
+ | `npm run test:cli-process` | 48 tests, 48 pass, 0 fail, 0 skip; 33,887.057125 ms | `/tmp/facade-process4.log` |
190
+ | `npm test` | 603 tests, 602 pass, 0 fail, 1 skip; 69,523.713167 ms | `/tmp/facade-full5.log` |
191
+
192
+ The only skipped test is `shipped Claude mod real runtime scheduling and lifecycle`, the existing opt-in real-runtime test. No cancellation, facade, storage or package coverage was skipped. The formal `verified` audit/delivery gate must run or attest both declarations on the final candidate; the journal receipt, not this document, records that attestation.
193
+
194
+ During integration, stale deleted-helper consumers were migrated to real owner/presentation paths. A captured-env failure and the locked build cancellation gap were fixed under explicit journal amendments. The last failed full run exposed one old core error-text assertion demanding a terminal glyph in domain output; it was updated to the neutral message while keeping requested-name/reason/no-other-name assertions. The full suite passed after that correction. Frozen-source inspection then found the draft timestamp's dependency on a failing owner clock; that dependency was removed and a focused raw-before-recovery/landed-ID regression added. Both suites were rerun successfully as reported above. No failure was hidden by narrowing the final commands.
195
+
196
+ ## Non-claims
197
+
198
+ - This document does not record independent review or acceptance. The holder/reviewer owns those acts; the deliverer does not self-review.
199
+ - Production line reduction does not imply byte reduction or establish architectural quality by itself.
200
+ - No artifact replacement support, native protocol redesign, schema change, capacity re-probe or live harness validation is claimed.
@@ -0,0 +1,95 @@
1
+ # One Square application boundary
2
+
3
+ **Status: implemented; deliverer verification and measurement are recorded in the delivery evidence. Independent review remains separate.**
4
+ Baseline: `52b58eb9f901f0458302e6120cd83b1079f8ba1c`. Delivery evidence and the exact size recipe live in [application-facade-delivery-evidence](application-facade-delivery-evidence.md).
5
+
6
+ ## Decision in brief
7
+
8
+ - `square-application.ts` is the sole runtime application owner. It captures the operation context, resolves location/participant, opens and closes resources, applies common defaults (reentry, quiet-wait, default wake transport, history page size), coordinates private actions, and composes projections.
9
+ - `square-facade.ts` stays type-only: it declares the operation contracts, the `{data, projection}` outcome, projection contracts and the SDK resource types. It is the source of every public contract name; the owner re-exports its types.
10
+ - CLI and MCP are transport adapters. Neither opens storage, reads private projections, executes admission/wait policy nor derives domain states from display text.
11
+ - SDK resource handles and the application share the same semantic owners (`prepareExpression`, `landExpression`, `catchOwned`); the handles do not round-trip through the application outcome/projection contract.
12
+ - `square-wiring.ts`, root `activity.ts` and root `watch.ts` are deleted. No forwarding stub, legacy factory or return-shape mode remains.
13
+ - The SDK resource API and its documented defaults are preserved, but they are a resource surface over the same owner functions, not a second implementation.
14
+
15
+ ## The application contract
16
+
17
+ Root factory (named, single):
18
+
19
+ ```ts
20
+ export function createSquareApplication(context: SquareApplicationContext): SquareApplication;
21
+ ```
22
+
23
+ Context (`cwd`, captured `env`, optional `squarePath`, `participant`, `clock`, `hostLedger`, `wakeTransport`) is snapshotted at creation. Location resolution uses the context and its `SQUARE_LOCATION`; participant selection is explicit context, then captured `SQUARE_PARTICIPANT_NAME`, then one unambiguous current-session binding from the selected/injected ledger. Explicit values win. A history read never discovers, joins or claims a participant just to select a default limit.
24
+
25
+ Every operation returns one composed outcome:
26
+
27
+ ```ts
28
+ export interface ApplicationOutcome<Data, Projection> {
29
+ readonly data: Data; // canonical structured result (the MCP wire fields are a subset)
30
+ readonly projection: Projection; // extra domain/presentation facts, never terminal copy
31
+ }
32
+ ```
33
+
34
+ `SquareApplication` exposes `now()`, `build`, `join`, `express`, `catch`, `history`, `listen`, `ignore`, `listening`, `hold`, `resume`, `done`, `status`, `participants`, `diagnose`, `migrate`, `discover`, `inbox`, `recovery` and `stream(options, control?)` (an abortable `AsyncIterable`, not a process writer). Read-only operations accept the same `OperationControl` (`signal` + typed progress).
35
+
36
+ This outcome contract **replaces** the previous factory return values; it is not source-compatible with them, and it does not select semantics or shapes by transport. In-repo consumers migrate together. There is no second factory, no overload that chooses a return shape, and no compatibility shim. The application result contract is recorded in the delivery evidence so it cannot be mistaken for the earlier factory contract.
37
+
38
+ Array-bearing results use object envelopes (`{activities}`, `{participants}`, `{listening}`), never arrays carrying hidden metadata. `data` never contains an artifact, transaction callback, SQL, lock or lease capability.
39
+
40
+ `ApplicationFailureDetail` supplements, never contradicts, authoritative `facts.activityUnsent`; the owner classifies express effects as before-attempt, proven-unsent (authoritative admission refusal), landed (committed activity + ID) or unknown (execution failure without refusal/result evidence).
41
+
42
+ ## Committed facts and projection sources
43
+
44
+ - Express takes its minimal count/header facts from the authoritative commit's own observation. It does not issue a later context read that could erase a successful say, and it does not build a second pending feed that would be discarded. The outcome `data` is the committed activity, `waited` and optional `replyAuthorNotHere`; the projection adds the pre-attempt directed feed, the reentry fact and delivery.
45
+ - Catch settles raw records, say ordinals and count/terminal facts inside the same receipt transaction as selection and marking seen. There is no duplicate post-receipt raw re-read: the application outcome adds the optional focused `catchPresence` read instead, and its unavailability is an explicit fact (`enrichmentUnavailable`).
46
+
47
+ ## SDK resources and preserved defaults
48
+
49
+ - `Square` and its participant handles live in `square-application.ts`; `index.ts` exports `Square` from there, not from a forwarding shim.
50
+ - SDK handles call the shared semantic owners directly, not through an application outcome/projection roundtrip:
51
+ - `Participant.express` = `prepareExpression` (reentry/caller resolution) + the shared `landExpression` retry/commit owner. It returns the established `ExpressResult` (including `delivery`) and drops the projection.
52
+ - `Participant.catch` = the shared `catchOwned` lease/wait/selection/sweep owner. It unwraps the receipt data into `CatchResult` (`activities`, `consumedThrough`, `idleExpired`, `remaining`).
53
+ - Listener, lifecycle and history methods call their shared owners directly; `snapshot().delivered` stays a detached receipt predicate.
54
+ - Retained supported `Square` methods: `at`, `build`, `inMemory`, `join`, `takeover`, `doneOwnedSession`, `implicitJoin`, `participants`, `snapshot`, `history`, `recognize`, `close`, `endOwnedSession`, `retireEndedSessionRoutes`. The unused `joinWithActivity`, `takeoverWithActivity`, `joinFacts` and `standingCount` glue is deleted.
55
+ - Preserved defaults are explicit at the SDK/application boundary, not a difference in transport defaults:
56
+ - `Square.history()` keeps its current **unbounded** archive default.
57
+ - `Participant.history()` keeps its current **recent-ten** default.
58
+ - Application, CLI and MCP ordinary history default to **ten**, independent of participant selection.
59
+ - In-memory resources stay in-memory: they do not invent file/native wake routes or build a default transport merely to express.
60
+
61
+ ## Module deletion map
62
+
63
+ | Path | New ownership | Disposition |
64
+ | --- | --- | --- |
65
+ | `square-wiring.ts` | `square-application.ts` | **Deleted.** `Square`/participant handles flattened into the owner; no re-export stub. |
66
+ | `activity.ts` | `app.express` + `cli/express-presentation.ts` | **Deleted.** Caller resolution, implicit join, attempt/uncertainty policy and default-transport construction moved to the owner; only draft/retry/render helpers survive in the CLI. |
67
+ | `watch.ts` | `app.catch` + `cli/catch-presentation.ts` | **Deleted.** Lease/heartbeat/revision loop and terminal policy moved to the owner; one renderer of returned classifications remains. |
68
+ | `square-application.ts` | — | **Owner.** Shared `prepareExpression`/`landExpression`/`catchOwned` semantic owners are the single implementation for application and SDK. No application -> SDK -> application chain; unused SDK glue (`joinWithActivity`, `takeoverWithActivity`, `joinFacts`, `standingCount`) deleted, supported methods retained. |
69
+ | `square-facade.ts` | — | Type-only contracts, `ApplicationOutcome`, projection/SDK contracts, explicit legacy name aliases. |
70
+ | `square-actions.ts` | `square-actions.ts` | Private mutation/ownership fences/delivery integration; called only by the owner. |
71
+ | `decisions.ts`, `catch-decisions.ts`, `wakes.ts` | unchanged files | Private implementations used by the owner. |
72
+ | `views.ts` | unchanged file | Private selected-row reads. `activityPresentation`, `standingCount`, `joinFacts` and `watchPresentation` retired; focused `recoveryObservation` and `catchPresence` added. Public projection types live in the facade. |
73
+ | `list.ts`, `stream.ts` | unchanged files | Internal data-returning discovery/observation; no process writers or argv recovery. |
74
+ | CLI operation paths (build, join, express, catch, history, listen/ignore/listening, hold/resume/done, status, participants, inbox, discover, doctor, migrate) | corresponding `app.*` | Direct storage opens, private projection imports, admission policy and duplicated wait loops removed. |
75
+ | `mcp.ts` | `app.*` | `publicResult`/stored-activity conversion deleted; serialize `outcome.data` only. |
76
+ | `index.ts` | owner + facade | Root `Square` from the owner; all facade contracts via one type-only star plus the supported legacy aliases. |
77
+ | `automatic-session.ts`, `claude-mod.ts`, `plugins/opencode/index.ts` | owner | Mechanical import migration only; native lifecycle protocols unchanged. |
78
+
79
+ ## Architecture edges
80
+
81
+ - **Adapter boundary.** CLI/MCP reach storage, actions, decisions, views, wakes, list, stream, diagnosis/migration, inbox and notification execution only through `square-application.ts`. Private concern helpers retain their existing typed ports and internal dependencies; they are not callable from adapter execution paths.
82
+ - **Facade.** `square-facade.ts` defines contracts; it must not derive contracts from `ReturnType`/`Awaited<ReturnType>` of private functions, and public activity IDs are formatted/parsed only by the existing core implementation.
83
+ - **CLI (`cli/**`).** Owns argv/stdin, scoped help, shell quoting, sensory rendering/recovery, drafts, stdout/stderr, exit codes, SIGINT -> `AbortSignal` and stream backpressure. It maps returned classifications to copy/exit status, and preserves query argv in continuation commands; it cannot derive admission, commit certainty, terminal states or pagination eligibility from display text. File path display and draft-file I/O are allowed; opening an artifact or resolving ownership is not path formatting.
84
+ - **MCP (`mcp.ts`).** Owns Zod schemas, registration, request-local `as`/`_meta.threadId`/session mapping, signal forwarding, JSON-RPC envelopes and stdio lifecycle. Request environment derivation stays immutable; no shared `process.env` writes and no invented session identity. Its method-name dispatch is a thin argument-to-method mapping, not a second policy dispatcher.
85
+ - **Closed exceptions.** Harness install/uninstall/doctor, scoped help/version, meta commands and native hook input/output keep their existing protocol owners; that exception does not cover join, expression, catch, history, status, participants, build, stream, discovery, inbox, artifact doctor or migrate. Native changes stay limited to the required owner import migration.
86
+ - **Storage/native scope.** SQLite schema/framing, artifact version, migration protocol, receipt model, ownership CAS, notification cancellation suppression and delivery eligibility rules are unchanged. Transactions stay synchronous and typed. The journaled amendment permits only build/create signal propagation through the existing adapter/storage/artifact retries and transactions, and captured-env propagation through default Codex wake construction/executable selection. A committed build is returned despite later cancellation; temporary-file cleanup does not reuse the aborted signal.
87
+
88
+ ## Shared behavior (all four land together)
89
+
90
+ 1. Application express reenters a roster-known departed participant through the same join/ownership path; a never-joined caller is refused. Takeover is never implicit.
91
+ 2. Application idle catch is one shared leased quiet wait (hold/heartbeat/replacement/terminal); omitted/zero idle is immediate; exact `id` stays immediate/idempotent and conflicts with idle/filter/limit/replace; a non-replaced current lease returns `already-active`.
92
+ 3. The default wake transport resolves lazily from the captured env, selected/injected ledger and clock, cached only for that application's lifetime; an injected transport prevents default construction.
93
+ 4. Application, CLI and MCP history default to ten; SDK `Square`/`Participant` defaults above are preserved.
94
+
95
+ Only these four deliberate common behavior changes, plus the additive explicit idle terminal statuses, alter existing behavior. All other SDK/CLI/MCP contracts, error codes and wire meanings are preserved.
@@ -4,7 +4,7 @@ Square's artifact and host-ledger adapters own change detection. Notifications a
4
4
 
5
5
  - A process shares a revision reader per canonical artifact and a filesystem watcher per containing directory. Subscribers have independent baselines, deadlines, and cancellation. The final release closes the watcher, reconciliation timer, and any outstanding read.
6
6
  - Directory notifications invalidate lightweight reads. A two-second reconciliation checks revisions/ledger metadata even when notifications are missing. Missing directories, unsupported watches, and watcher failures retain that fallback; directory replacement is detected during reconciliation. Normal notification latency is not a hard guarantee: a missed hint may wait for reconciliation, plus scheduling and lock contention.
7
- - The artifact revision remains authoritative. No new sidecar, broker, or persistent cache is introduced. Only changed projections load historical state. A missing artifact is a stable observation, not a repeated change: reconciliation remains quiet while it stays absent and detects its return without deleting its session bindings. Strict artifact reads still report absence as an error. Ledger metadata invalidates bindings and presentation projections; it is never treated as evidence of delivery.
7
+ - The artifact revision remains authoritative. No new sidecar, broker, or persistent cache is introduced. Changed projections read typed recipient facts and selected bodies, not the whole historical state. A missing artifact is a stable observation, not a repeated change: reconciliation remains quiet while it stays absent and detects its return without deleting its session bindings. Strict artifact reads still report absence as an error. Ledger metadata invalidates bindings and presentation projections; it is never treated as evidence of delivery.
8
8
  - Each Pi session owns a long-lived pending observer, including when it has no bindings yet. Presence and evidence changes update its subscriptions. There is no repeated thirty-second restart and no per-second binding scan. A failed injection waits for a substantive change; its own failed evidence write does not trigger a retry loop.
9
9
  - Blocking CLI catch waits for a revision or its next heartbeat/quiet deadline. A held catch keeps its lease alive and pauses quiet expiry. Core catch, NDJSON stream, and delivery-receipt waits use the same change detector. Held express also waits for changes; throttling still waits for its eligibility time.
10
10
  - Catch lease expiry, ledger retention/claim expiry, and cancellation are independent wake conditions. No filesystem write is required for a time-based eligibility change.
@@ -19,10 +19,10 @@ npm test
19
19
  npm run test:cli-process
20
20
  node --import ./test/sandbox-env.js scripts/benchmark-idle-wait.mjs --workers 100 --mode poll200
21
21
  node --import ./test/sandbox-env.js scripts/benchmark-idle-wait.mjs --workers 100 --mode events
22
- node --import ./test/sandbox-env.js scripts/benchmark-idle-wait.mjs --workers 100 --mode session
23
- node --import ./test/sandbox-env.js scripts/benchmark-idle-wait.mjs --workers 100 --mode session --active
22
+ node --import ./test/sandbox-env.js scripts/benchmark-idle-wait.mjs --workers 300 --mode session
23
+ node --import ./test/sandbox-env.js scripts/benchmark-idle-wait.mjs --workers 300 --mode session --active --no-hints
24
24
  ```
25
25
 
26
- The benchmark creates disposable synthetic history. poll200 reconstructs the preceding lightweight 200ms polling strategy; events measures revision waits. session includes binding and notification projection, but excludes initial setup. Active runs inject one bell and report committed-write-to-projection latency, not native Pi message landing. They allow up to twenty seconds so saturation is distinguishable from a lost wake. One hundred processes still have one hundred monitors: sharing is process-local, not a claim of cross-process deduplication.
26
+ The benchmark creates disposable synthetic history. poll200 measures 200ms revision polling; events measures revision waits. session includes binding and notification projection, but excludes initial setup. Active session runs compare 1,800 and 18,000 unrelated history rows, inject one bell without push, then catch concurrently. `--no-hints` disables filesystem hints only inside benchmark workers. Runs report committed-write-to-projection latency, not native Pi message landing, and retain the twenty-second discovery deadline as a probe bound rather than an SLA. Three hundred processes still have three hundred monitors: sharing is process-local, not cross-process deduplication. See [row runtime delivery evidence](row-runtime-delivery-evidence.md) for actual completion, hydration, CPU, lock contention and host-ledger costs.
27
27
 
28
28
  A long-running Pi process must reload/restart its Square extension to use rebuilt code.
@@ -0,0 +1,77 @@
1
+ # Migrating an existing square to row storage
2
+
3
+ Square stores authority in one versioned SQLite artifact. Version 1 kept the
4
+ whole history as one JSON snapshot; version 2 keeps typed rows — activities,
5
+ sparse receipts, catch leases, ordered routes and the small configuration
6
+ facts — in one in-place database.
7
+
8
+ Existing artifacts are **not** converted automatically. A normal read of a
9
+ version 1 artifact refuses with the exact command to run:
10
+
11
+ ```sh
12
+ square --location /path/to/SQUARE.square migrate
13
+ ```
14
+
15
+ That is the only migration command. There is no `--check`, `--backup`,
16
+ `--force`, bulk mode, sidecar, daemon or dual reader, and no operator
17
+ configuration to set.
18
+
19
+ ## What the command does
20
+
21
+ It converts the artifact **in place**, in **one transaction**:
22
+
23
+ 1. Reads the owned legacy framing before touching anything (application id,
24
+ format version, `DELETE` journal mode, the exact snapshot schema) and
25
+ refuses anything that is not an owned version 1 square.
26
+ 2. Takes `BEGIN IMMEDIATE`, re-checks that framing under the lock, and decodes
27
+ and validates the complete snapshot inside the lock.
28
+ 3. Creates the row schema and writes the preserved authority: activity indices
29
+ and their gaps, optional-field presence, raw receipt and lease owner keys,
30
+ route order and duplicates, string content and finite fractional timestamps.
31
+ 4. Rebuilds the derived participant, hold, attention and landed-audience facts
32
+ through the same single landing transition the runtime uses.
33
+ 5. Drops the snapshot table, sets the format version, and commits once.
34
+
35
+ The revision is preserved; migration never invents or advances it. Nothing is
36
+ published piecemeal, and the file keeps its path, inode and registry identity.
37
+
38
+ Two shapes are already fine and change nothing:
39
+
40
+ - an artifact that is already version 2 (reported as already format 2);
41
+ - an artifact converted by another process while this one waited for the lock.
42
+
43
+ ## What it refuses
44
+
45
+ Nothing is written when the input is not a normally persisted version 1 square:
46
+ a missing file, an unrelated SQLite database, an unsupported format version, a
47
+ different journal mode, an unknown snapshot schema, unreadable snapshot JSON, or
48
+ a route carrying a non-finite number (an exponent-overflow value such as
49
+ `1e999`, which the previous permissive check accepted and an ordinary JSON round
50
+ trip cannot carry) are all refused before any write. The refusal names the
51
+ offending route property.
52
+
53
+ Journal mode is never rewritten to make a migration possible.
54
+
55
+ ## Before you migrate
56
+
57
+ - Stop attached runtimes, or upgrade them together with the migration. An
58
+ in-flight remote delivery is not revoked by migration, and a version 1 writer
59
+ either commits before the conversion or is refused afterwards — it can never
60
+ overwrite converted rows.
61
+ - An offline backup is optional and, if you want one, ordinary: copy the file
62
+ while no writer is attached. The command does not manage backups.
63
+
64
+ ## Crash safety
65
+
66
+ Before `COMMIT`, SQLite's own journal recovers the complete version 1 artifact;
67
+ after it, the complete version 2 rows are there. A process killed mid-migration
68
+ therefore leaves one or the other, never a partial artifact, and re-running the
69
+ command finishes the job. A busy `COMMIT` retries the same transaction and never
70
+ re-runs the conversion.
71
+
72
+ ## Checking an artifact
73
+
74
+ `square --location <path> doctor` is read-only. On a legacy artifact it
75
+ recognizes version 1 and prints the migration command; it does not call the
76
+ artifact damaged. On version 2 it validates the rows and recomputes the derived
77
+ indices to compare them against the stored ones.
@@ -0,0 +1,36 @@
1
+ # Postcommit simplification: 300-process comparison
2
+
3
+ Measured on the same local host with Node v26.10.0. Baseline runtime: release 0.3.71 (`90478f8`). Candidate runtime: `03237aa`. The benchmark entrypoint repair in `2bfb68e` was used for both; it replaces imports of removed modules with current artifact/open-square exports, without changing the scenario or deadlines.
4
+
5
+ ```sh
6
+ npm run build
7
+ node --import ./test/sandbox-env.js scripts/benchmark-idle-wait.mjs --workers 300 --mode session --active --no-hints
8
+ ```
9
+
10
+ The command exercises both 1,800 and 18,000 unrelated historical activities. Each of 300 processes observes one bell, recognizes its participant, performs one consuming catch and one empty repeat. These are synthetic Pi bindings without callable native routes. Counts below aggregate all 300 processes; catch latency describes that entire per-process catch phase, not one standalone API call. MB means decimal bytes. Ledger bytes measure instrumented file reads/writes, not physical disk traffic.
11
+
12
+ | Measurement | Baseline, 1,800 | Candidate, 1,800 | Baseline, 18,000 | Candidate, 18,000 |
13
+ | --- | ---: | ---: | ---: | ---: |
14
+ | Ready / complete | 300 / 300 | 300 / 300 | 300 / 300 | 300 / 300 |
15
+ | Caught per process | 1 | 1 | 1 | 1 |
16
+ | Reconsumed total | 0 | 0 | 0 | 0 |
17
+ | Catch ledger MB | 229.248 | 95.520 | 229.248 | 95.520 |
18
+ | Catch ledger operations | 4,200 | 1,500 | 4,200 | 1,500 |
19
+ | Catch p50 seconds | 18.65 | 5.80 | 22.76 | 5.36 |
20
+ | Catch p95 seconds | 22.57 | 7.11 | 26.62 | 6.85 |
21
+ | Catch SQLite busy errors/retries | 174,082 | 45,555 | 221,701 | 45,028 |
22
+ | Catch CPU seconds, aggregate | 65.01 | 23.31 | 73.50 | 21.65 |
23
+ | Discovery p95 seconds | 1.870 | 1.877 | 1.877 | 1.897 |
24
+ | Five-second idle CPU seconds, aggregate | 3.181 | 3.241 | 3.594 | 3.088 |
25
+
26
+ These historical SQL/busy counts combined artifact SQL with host-ledger file-lock SQL; “busy errors/retries” counted thrown busy errors, not independently observed retries. They cannot be compared directly with the origin-separated counters now in the benchmark. Rerun both runtimes with the same new script. Its `ledgerSql` reports host-root SQL (including lock databases), separately from artifact SQL. Returned SQL string/blob bytes are not physical I/O or full JSON decode measurements; SQLite's zero instrumented filesystem bytes is a transport change, not a performance gain.
27
+
28
+ Idle body hydration and ledger bytes remained zero. Each discovery and catch phase hydrated 300 activity bodies. The original 20-second discovery deadline and derived phase guard were unchanged.
29
+
30
+ The candidate removes a discarded catch-completion sweep and combines postcommit identity publication around one fresh presence observation. Admission remains a separate ownership check. Source changes also consolidate duplicate native connection-option declarations; those type changes do not account for the performance result. Production TypeScript across the three changes is net -57 lines without formatting compression. The benchmark repair is separately net -1 tooling line.
31
+
32
+ Ledger bytes fell 58.3%, and ledger operation count fell 64.3%. The observed latency improvement is a single before/after local comparison, not an SLA or an isolated causal attribution: other agent work and verification occurred during the broader run, and host load was not controlled. The deterministic operation reduction supports the intended deletion of duplicate work. Idle discovery was not redesigned, and this does not measure callable-route publication or long-lived leased catch optimization.
33
+
34
+ Each change passed independent review and its declared verification before integration. Root CLI process checks passed all 48 cases; the native adapter package passed 42 cases with its existing Windows-only skip. Full root verification retained its existing skipped case.
35
+
36
+ Local raw reports: `/tmp/square-round2-baseline-300.json` and `/tmp/square-round2-final-300.json`. These temporary reports are diagnostic artifacts, not repository dependencies. No ledger storage migration or evidence GC change is included.
@@ -0,0 +1,85 @@
1
+ # Canonical catch selection — delivery evidence
2
+
3
+ Deliverer evidence only, **not independent review or acceptance**.
4
+
5
+ ## Coordinates and lane attribution
6
+
7
+ - Contract: `kei/one-canonical-catch-selection-36b2`.
8
+ - Fixed baseline: `501ddc27d5520717f7a9e4d9a5b97406ea72022f`.
9
+ - Implementation: `a2647054f45024ace2562001344285959fbecede`, following `d4df16e0db10d50c01b7ca6646b3c2bdb2871184`.
10
+ - Appointed worktree: `/Users/astrosheep/Developer/square/.keiyaku/wt/revolvingdoor`.
11
+ - Target checked and `git merge main` run at 2026-10-15 10:24 CST: already up to date, main still the fixed baseline. No storage/history/status lane changes are included in this implementation or its reduction claim. Later integration must preserve those lanes and rerun the declared scripts if production changes.
12
+ - This document is a documentation-only descendant of the implementation. The journal tender identifies the final candidate SHA.
13
+
14
+ ## Removed responsibilities and their owners
15
+
16
+ | Removed | Canonical owner / retained boundary |
17
+ | --- | --- |
18
+ | `CatchDecision`, its unused `changed`, and its all-full perception map | `CatchSelection` contains raw selected activities, participant, cursor/remaining, say ordinals, clock, count/hold/cap/terminal facts. Pure `decideCatch` selects and writes receipts through `SquareWrite`, then captures these facts in that transaction. |
19
+ | `CatchSelectionResult` combining public activities with a second raw observation | `catchUp` admits the owner, checks the lease ID and invokes `decideCatch` in one receipt transaction, publishes presence best effort, and returns that exact selection. It no longer performs public conversion. |
20
+ | `CatchSelectionObservation` and `WatchPresentation` | `catchOwned` carries the same selection through completion, alongside actual lifecycle stop, waitStarted and replaced facts. No second selected-record wrapper or public page is built inside the lifecycle. |
21
+ | Completion's separate empty-result construction | `observeCatchSelection` captures the same concrete contract using `SquareRead` without marking seen. Only a completion without a committed selection calls it; it does not reopen or rehydrate a committed page. Empty ordinals are `{}` without an unnecessary selector call. |
22
+ | SDK public-result strip/rebuild and application raw page duplication | `caughtResult` maps to the established `CatchResult` at SDK/application exits. The application alone adds its existing terminal status and necessary projection metadata. `CatchProjection` has no raw `activities` array and no repeated terminalStatus. Optional nearby presence remains separate. |
23
+ | CLI reverse lookup from public ID into raw projection | CLI renders each public activity directly. Existing event rendering accepts `Activity` or `StoredAct` using small ID/reply accessors; no reconstruction of StoredAct or third display-event model. Raw archive/read/actorless inputs still work. |
24
+
25
+ Directed selection guarantees full visibility: `facts.directed` selects the landed audience relation; its heads require a say with an actor. Exact-ID catch checks both say kind and `directedAt` before selection. `perceiveActivity` settles any directed say to `full`, including listening/reply/bell routes. Therefore the deleted map carried no information and public conversion can attach `perception: 'full'` directly. The case/rejoin audience fixture now verifies the actual perception predicate for selected records, rather than checking the deleted map.
26
+
27
+ Necessary abstractions remain: typed transaction capabilities, pure selection, owner admission, leased waiting, application outcome and CLI/MCP adapters are distinct. No schema, native protocol, build/resource construction, generic operation receipt, generic dispatcher or optional-field selection bag was added.
28
+
29
+ ## Preserved lifecycle and observation timing
30
+
31
+ - Lease acquisition retains its own transaction. Lease-ID validation, selection, markSeen, cursor, remaining and selected-page facts share the `catchUp` receipt transaction. A replaced waiter cannot insert a receipt in the gap after its heartbeat.
32
+ - Revision is still captured before evaluation. Heartbeats, hold-paused quiet expiry, replacement and ID-fenced signal-free cleanup remain unchanged. Already-active/replaced/capped/quorum remain distinct from empty-now/stale.
33
+ - Successful selection never falls back to a postcommit page/context read. Presence publication, lease release and notification enrichment remain best effort after authoritative consumption. Optional nearby presence can be unavailable without erasing the selected page.
34
+ - Empty terminal/quiet completion reads authoritative cursor and filtered remaining without markSeen. It never invents a null cursor after consumption. Seen holes, continuous cursor, historical catch and notification latest-join semantics remain unchanged.
35
+ - Public conversion now occurs later, at each API exit, rather than in the action/lifecycle. Selection facts still reflect the receipt transaction, not optional presence time. Empty completion's clock is captured when constructing that read-only selection; no selected body is hydrated. No SDK default or wire result changes are intended.
36
+
37
+ ## Lane-local source reduction
38
+
39
+ Classification is exactly the production predicate in `guides/application-facade-delivery-evidence.md`: handwritten `.ts/.js/.mjs`, excluding its listed test/generated/script/documentation/vendor directories and test/spec/generated filename markers. All new production files would count; this lane adds none.
40
+
41
+ Measured from git objects, fixed baseline to the implementation above:
42
+
43
+ | Snapshot | Production files | Physical lines | Bytes |
44
+ | --- | ---: | ---: | ---: |
45
+ | `501ddc2` | 110 | 13,926 | 732,940 |
46
+ | `a264705` (catch lane only) | 110 | 13,903 | 731,909 |
47
+ | Delta | 0 | **−23** | **−1,031** |
48
+
49
+ Exact production patch counts:
50
+
51
+ | Path | Added | Deleted | Net lines | Net bytes |
52
+ | --- | ---: | ---: | ---: | ---: |
53
+ | catch-decisions.ts | 30 | 17 | +13 | +820 |
54
+ | cli/catch-presentation.ts | 4 | 8 | −4 | −160 |
55
+ | presentation.ts | 22 | 13 | +9 | +369 |
56
+ | square-actions.ts | 9 | 33 | −24 | −1,274 |
57
+ | square-application.ts | 30 | 41 | −11 | −497 |
58
+ | square-facade.ts | 4 | 10 | −6 | −289 |
59
+ | **Total** | **99** | **122** | **−23** | **−1,031** |
60
+
61
+ Reproduce patch counts with `git diff --numstat 501ddc2 a264705 --` followed by those six production paths; reproduce snapshot totals with the referenced evidence document's Python recipe, setting BASE to `501ddc2` and CANDIDATE to `a2647054f45024ace2562001344285959fbecede`. Counts include every production change in this lane, not another lane's removals. This is real responsibility deletion, not a claim based on relocation, packed statements, comment/whitespace removal, excluded-path offloading or unrelated deletion.
62
+
63
+ ## Verification and concrete evidence
64
+
65
+ All test invocations use repository scripts or the `--import ./test/sandbox-env.js` preload. No live session notification or external runtime probe was used.
66
+
67
+ | Command / subject | Result | Raw local log |
68
+ | --- | --- | --- |
69
+ | Initial focused eight-file selection/lifecycle/renderer checks | 107 passed, 0 failed | `/tmp/catch-focused-1.log` |
70
+ | Focused page/fence/postcommit/public-render regressions | 39 passed, 0 failed | `/tmp/catch-focused-2.log` |
71
+ | `npm test` on `a264705` | 606 tests, 605 passed, 0 failed, 1 existing opt-in Claude runtime skip; 31,629.839875 ms | `/tmp/catch-full-2.log` |
72
+ | `npm run test:cli-process` on `a264705` | 48 tests, 48 passed, 0 failed, 0 skipped; 22,602.035709 ms | `/tmp/catch-cli-1.log` |
73
+
74
+ The first full run exposed an unnecessary `sayOrdinals([])` read on empty SDK completion. The existing SDK no-body-projection assertion was left intact; the observer now omits that empty selector call. The full scripts above passed after the fix. No failing test was hidden by narrowing the final commands.
75
+
76
+ Boundary evidence:
77
+
78
+ - `performance`: real raw selection hydrates only its bounded page; remaining uses directedCount; presence/rendering never rehydrates it. A new postcommit mutation fixture changes own count, hold and pending rows after selection and rejects any action-level read: returned ordinals/cursor/remaining/count/hold/clock still match the receipt transaction. A mismatched lease ID returns null without revision/receipt change.
79
+ - `application-boundary`: a real delivered receipt triggers failing host publication and a failing postcommit clock/presence read; catch still returns the consumed public page and its original projection facts, with enrichmentUnavailable and no raw activities projection. A later catch is empty. Existing real leased replacement, cancellation cleanup, hold/resume and quiet expiry fixtures pass, including the preserved consumed cursor after an actual say.
80
+ - `presentation`: public/raw rendering parity checks multiline body, activity ID, reply ID, mention metadata, done and listen; presence omits bodies. Raw read remains empty and actorless hold remains renderable.
81
+ - `row-domain`, `core`, `delivery`, `perception-projection`: filter-before-limit, exact repeat, original receipt timestamp, gap/cursor and latest-join differences remain tested. Obsolete changed assertions were replaced by actual receipts, or removed only where the immediately adjacent unchanged receiptAssignments equality already proves no write. No boundary assertion was weakened to preserve a retired mechanism.
82
+ - `operation-cancellation`, `square-facade`: commit survives response abort; SDK returns only its established CatchResult, no application body projections. CLI process coverage retains filtered continuation, mention/body visibility, stable IDs and lifecycle feedback. MCP continues serializing data only.
83
+ - Production reference search for `CatchDecision|CatchSelectionResult|CatchSelectionObservation|WatchPresentation|exposeCaught` returned no matches (excluding dist/node_modules); `git diff --check` passed. CLI has no `projection.activities.find` or raw reconstruction.
84
+
85
+ Formal audit and tender are journal acts; their receipts, not this deliverer document, establish Verification and waiting review. No self-review was performed.