stitchkit 0.103.8 → 0.103.10

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 (79) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/dist/agent-runtime/sandbox-process.d.ts +2 -2
  3. package/dist/agent-runtime/sandbox-process.d.ts.map +1 -1
  4. package/dist/agent-runtime/store-conformance-lifecycle.d.ts +10 -10
  5. package/dist/durability/contract.d.ts +3 -2
  6. package/dist/durability/contract.d.ts.map +1 -1
  7. package/dist/durability/effect.d.ts.map +1 -1
  8. package/dist/durability/engine.d.ts.map +1 -1
  9. package/dist/durability/json.d.ts.map +1 -1
  10. package/dist/entrypoints/agent-runtime/harness.js +2 -2
  11. package/dist/entrypoints/agent-runtime/sandbox.js +29 -81
  12. package/dist/entrypoints/agent-runtime.js +2 -2
  13. package/dist/entrypoints/application/diagnostic-journal.js +2 -1
  14. package/dist/entrypoints/cli.js +1 -1
  15. package/dist/entrypoints/files.d.ts +2 -0
  16. package/dist/entrypoints/files.d.ts.map +1 -1
  17. package/dist/entrypoints/files.js +14 -6
  18. package/dist/entrypoints/primitives.js +77 -57
  19. package/dist/entrypoints/process.d.ts +5 -0
  20. package/dist/entrypoints/process.d.ts.map +1 -0
  21. package/dist/entrypoints/process.js +20 -0
  22. package/dist/entrypoints/tools.js +12 -3
  23. package/dist/files/boundary.d.ts +19 -1
  24. package/dist/files/boundary.d.ts.map +1 -1
  25. package/dist/files/file-io.d.ts +5 -1
  26. package/dist/files/file-io.d.ts.map +1 -1
  27. package/dist/files/read.d.ts +13 -0
  28. package/dist/files/read.d.ts.map +1 -0
  29. package/dist/index-12m2v2a9.js +98 -0
  30. package/dist/index-6m6a9ty4.js +285 -0
  31. package/dist/index-8a9ksm91.js +95 -0
  32. package/dist/{index-90ppdx3q.js → index-9jb61j5a.js} +1 -1
  33. package/dist/{index-5vyd0fkb.js → index-ary5s7k0.js} +40 -61
  34. package/dist/index-c1jmtxa0.js +74 -0
  35. package/dist/index-ga597cvy.js +184 -0
  36. package/dist/index-mbnnw3f2.js +25 -0
  37. package/dist/index-nybn2err.js +213 -0
  38. package/dist/{index-v4a2fjtk.js → index-sybedc8b.js} +124 -55
  39. package/dist/internal/abort-race.d.ts +3 -0
  40. package/dist/internal/abort-race.d.ts.map +1 -0
  41. package/dist/internal/atomic-file.d.ts +20 -2
  42. package/dist/internal/atomic-file.d.ts.map +1 -1
  43. package/dist/internal/atomic-publication.d.ts +19 -0
  44. package/dist/internal/atomic-publication.d.ts.map +1 -0
  45. package/dist/internal/exclusive-lock.d.ts +2 -1
  46. package/dist/internal/exclusive-lock.d.ts.map +1 -1
  47. package/dist/internal/json-data.d.ts +8 -0
  48. package/dist/internal/json-data.d.ts.map +1 -0
  49. package/dist/internal/process-instance.d.ts +46 -9
  50. package/dist/internal/process-instance.d.ts.map +1 -1
  51. package/dist/internal/with-exclusive-lock.d.ts +4 -3
  52. package/dist/internal/with-exclusive-lock.d.ts.map +1 -1
  53. package/dist/primitives/canonical-json.d.ts +11 -0
  54. package/dist/primitives/canonical-json.d.ts.map +1 -0
  55. package/dist/primitives/index.d.ts +1 -0
  56. package/dist/primitives/index.d.ts.map +1 -1
  57. package/dist/process/command-owner.d.ts +13 -0
  58. package/dist/process/command-owner.d.ts.map +1 -0
  59. package/dist/process/command.d.ts +3 -0
  60. package/dist/process/command.d.ts.map +1 -0
  61. package/dist/process/contract.d.ts +45 -0
  62. package/dist/process/contract.d.ts.map +1 -0
  63. package/dist/process/group.d.ts +6 -0
  64. package/dist/process/group.d.ts.map +1 -0
  65. package/dist/process/leader-settlement.d.ts +4 -0
  66. package/dist/process/leader-settlement.d.ts.map +1 -0
  67. package/dist/tools/transfer/managed-file-error.d.ts.map +1 -1
  68. package/llms/files.txt +9 -1
  69. package/llms/primitives.txt +31 -1
  70. package/llms/process.txt +242 -0
  71. package/llms/stitchkit.txt +1 -0
  72. package/llms/tools.txt +18 -0
  73. package/llms-full.txt +292 -2
  74. package/llms.txt +6 -4
  75. package/native/darwin-arm64.node +0 -0
  76. package/native/darwin-x64.node +0 -0
  77. package/package.json +5 -1
  78. package/dist/index-7kxw1awn.js +0 -328
  79. package/dist/index-aan6hqb9.js +0 -65
package/llms-full.txt CHANGED
@@ -59,6 +59,7 @@ own, recorded as an ADR.
59
59
  | `stitchkit/tools/connections` | server (Bun or Node) | evolving | consume external MCP servers and a bounded OpenAPI subset — typed reauthorization, a per-request host fence and per-call credentials |
60
60
  | `stitchkit/cli` | server | stable | `createCli` — the CLI transport, light (no MCP SDK / `ai`) |
61
61
  | `stitchkit/remote` | browser **and** server | stable | peer-free `implementRemote` for thin HTTP proxy processes |
62
+ | `stitchkit/process` | server (Bun or Node, POSIX) | evolving | finite native commands, byte sinks, bounded capture and process-group cancellation |
62
63
  | `stitchkit/files` | server (Bun or Node) | stable | peer-free managed local-file boundary |
63
64
  | `stitchkit/telegram` | server (Bun or Node) | evolving | peer-free Telegram platform primitives — Mini App `initData` verification, send-failure classification, resumable broadcasts, the operator channel with dedupe, local Bot API files, webhook ownership and durable webhook update intake |
64
65
  | `stitchkit/telegram/html` | browser and server | evolving | Telegram's HTML as a tree — clean any markup to what Telegram accepts, cut long text into valid parts by what the reader sees, check markup before it is sent |
@@ -3872,6 +3873,10 @@ where both exist the runtime's wins, because the run is recorded in its ledger.
3872
3873
 
3873
3874
  #### An effect in another system — `effect`, at most once
3874
3875
 
3876
+ Standalone callers must hold an application-owned exclusive execution lease for the conversation/run
3877
+ through the whole effect call. Sharing a ledger or separate ledger adapters is not an atomic claim;
3878
+ the runtime supplies its run lease. Process-local coalescing only covers the same ledger object.
3879
+
3875
3880
  `step` records its result **after** the body, so a body cut short by a crash
3876
3881
  runs again. For sending a message or starting a turn at a provider, a repeat is
3877
3882
  worse than a loss. The engine's `effect` records the intent **before** it runs:
@@ -3894,6 +3899,20 @@ throws, or a `reconcile` that throws or overruns `reconcileTimeoutMs` (default
3894
3899
  call. The proof is JSON of at most 64 KiB — the identity the recipient assigned,
3895
3900
  not a payload. → [ADR 0200](../decisions/0200-an-effect-is-recorded-before-it-runs.md)
3896
3901
 
3902
+ Caller abort during reconcile releases the wait with `StepAbortedError`, leaves the intent and ignores
3903
+ a late result. A coalesced caller can cancel its own await without cancelling the shared owner;
3904
+ the first caller owns reconciliation handlers/deadline. `reconcileTimeoutMs` cannot exceed the native
3905
+ timer range (2147483647 ms). It does not turn cancellation into proof of absence. Neither `null` nor an absence digest
3906
+ proves that an earlier recipient request cannot complete later. Safe retries require recipient-side
3907
+ idempotency or a verified fence. See [ADR 0224](../decisions/0224-native-primitives-have-one-owner.md).
3908
+
3909
+ Ledger reads are paged at 10 000 and incremental in one engine; a fresh engine replays the conversation
3910
+ and retains its durable keys. This is not a bounded outstanding index/direct terminal receipt store.
3911
+ For application delivery, `defineDomainEventDelivery` in `stitchkit/primitives` composes a caller-owned
3912
+ atomic outbox claim with delivered/retryable/terminal/unknown states, bounded dispatch count (default
3913
+ 100). Storage retention, per-key lookup, recipient proof and transactions remain in that adapter;
3914
+ it is not an automatic cutover for a different reconciliation protocol.
3915
+
3897
3916
  ### Typed MCP call metadata
3898
3917
 
3899
3918
  Contract handlers, runtime-tool handlers/factories, lifecycle and tool hooks all
@@ -8002,6 +8021,223 @@ workspace-relative or canonical `/workspace/...` paths. Unsupported policies mus
8002
8021
  be refused explicitly by the backend.
8003
8022
 
8004
8023
 
8024
+ ==============================================================================
8025
+ # Guide: Native IO (docs/guide/native-io.md)
8026
+ ==============================================================================
8027
+
8028
+ ---
8029
+ title: Конечные команды и файловые гарантии
8030
+ description: Native IO для Bun и Node, с явно выбранной durability, безопасными bounds и caller lifetime.
8031
+ type: guide
8032
+ status: active
8033
+ created: 2026-10-01 20:44 +07:00
8034
+ updated: 2026-10-02 00:37 +07:00
8035
+ participants:
8036
+ - role: authored
8037
+ harness: Codex
8038
+ model: GPT-6
8039
+ at: 2026-10-01 20:44 +07:00
8040
+ - role: implemented
8041
+ harness: Codex
8042
+ model: GPT-6
8043
+ at: 2026-10-02 00:08 +07:00
8044
+ ---
8045
+
8046
+ # Native IO
8047
+
8048
+ Примеры используют публичные imports и одинаково исполняются в Bun и Node ≥22.
8049
+
8050
+ ## Запись файла
8051
+
8052
+ ```ts
8053
+ import { writeFileAtomic, AtomicFilePublicationError } from 'stitchkit/files'
8054
+
8055
+ try {
8056
+ await writeFileAtomic('/srv/app/receipt.json', JSON.stringify({ id: 'receipt-1' }), {
8057
+ replace: false,
8058
+ mode: 0o600,
8059
+ durability: 'directory',
8060
+ })
8061
+ } catch (error) {
8062
+ if (error instanceof AtomicFilePublicationError) {
8063
+ // target уже виден. Проверьте receipt, прежде чем решать о повторе.
8064
+ console.error(error.phase, error.cause)
8065
+ } else throw error
8066
+ }
8067
+ await writeFileAtomic('/srv/app/state.json', '{"version":2}', {
8068
+ replace: true, durability: 'directory',
8069
+ })
8070
+ ```
8071
+
8072
+ По умолчанию `replace: true`, `durability: 'file'`, `mode: 0o600`: existing вызовы сохраняют
8073
+ file-fsync и atomic replacement. `durability: 'none'` отключает sync; `'directory'` выполняет
8074
+ полную запись → exact descriptor chmod → file fsync → rename (replace) либо link (create) →
8075
+ удаление staging link → parent fsync. `writeFileAtomicSync` имеет те же options и порядок.
8076
+ Create отказывает с native `EEXIST` при существующем файле, symlink или concurrent winner.
8077
+ Никогда не переводите этот отказ в replace автоматически.
8078
+
8079
+ `AtomicFilePublicationError.published === true` отличает видимость от неподтверждённого
8080
+ acknowledgement. `phase` — `cleanup`, `directory-sync` или `directory-close`; первичная причина
8081
+ сохранена в `cause`. Ошибка до publish оставляет прежний target. Cleanup вторичен к первичной ошибке.
8082
+ При create кратко существует второй hardlink; strict single-link reader вправе отказать в этом окне.
8083
+
8084
+ Directory fsync — native POSIX/filesystem capability. Windows явно отказывает; иной filesystem
8085
+ может отказать при open/sync. Проверка на Linux не подтверждает поведение macOS, сетевой FS или
8086
+ сохранность при отключении питания. Состояние диска определяется гарантиями самой FS/ОС.
8087
+ `createManagedFileBoundary.write(..., { durable: true })` использует тот же publish owner и parent sync;
8088
+ его create по умолчанию остаётся create, а `replace: true` явно разрешает replacement.
8089
+
8090
+ ## Строгое чтение
8091
+
8092
+ ```ts
8093
+ import { createManagedFileBoundary } from 'stitchkit/files'
8094
+
8095
+ const files = await createManagedFileBoundary({ root: '/srv/app', maxReadBytes: 64 * 1024 })
8096
+ const source = await files.read('receipt.json', {
8097
+ rejectSymlinks: true, singleLink: true, stable: true, observe: true,
8098
+ })
8099
+ console.log(source.observation) // dev, ino, size, nlink, mtimeMs, ctimeMs
8100
+ const receipt = JSON.parse(new TextDecoder('utf-8', { fatal: true }).decode(source.bytes))
8101
+ // schema.parse(receipt) и проверка digest принадлежат приложению.
8102
+ ```
8103
+
8104
+ Без новых options ответ сохраняет `{ ref, bytes }`, допускает trusted in-root symlink и hardlink.
8105
+ `rejectSymlinks` запрещает requested leaf, `singleLink` проверяет `nlink` открытого descriptor,
8106
+ `stable` сравнивает dev/ino/size/mtime/ctime/nlink вокруг byte read; `observe` добавляет metadata.
8107
+ `FILE_NOT_FOUND`, `FILE_NOT_REGULAR`, `FILE_UNSAFE_LINK`, `FILE_TOO_LARGE`, `FILE_CHANGED`,
8108
+ `FILE_UNSUPPORTED` и `FILE_IO_ERROR` различаются. Abort сохраняет caller reason.
8109
+ Nonblocking open позволяет отказать FIFO без ожидания writer. Bytes ограничены во время чтения,
8110
+ включая рост файла, не только initial stat. Chunk allocation ≤ maxBytes+1+64 KiB, flatten ≤ maxBytes;
8111
+ FD закрывается при success, отказе, abort и IO error.
8112
+ Ошибка close сохраняет первичную ошибку чтения; после успешного чтения ошибка close возвращается caller.
8113
+
8114
+ Root и ancestors принадлежат trusted actor. Эти options не дают descriptor-relative containment
8115
+ при hostile concurrent ancestor replacement. Отдельного переключателя «считать ancestors безопасными»
8116
+ нет: portable owner не предоставляет такую capability. Metadata stability не доказывает immutable
8117
+ snapshot против произвольного hostile writer; используйте application lock/immutable publication.
8118
+
8119
+ ## Команды
8120
+
8121
+ ```ts
8122
+ import { runNativeCommand } from 'stitchkit/process'
8123
+
8124
+ const captured = await runNativeCommand({
8125
+ executable: '/usr/bin/git', args: ['rev-parse', 'HEAD'], cwd: '/srv/app',
8126
+ envPolicy: 'declared-only', env: { PATH: '/usr/bin:/bin' },
8127
+ capture: true, maxOutputBytes: 4096, timeoutMs: 5000,
8128
+ })
8129
+ console.log(captured.exitCode, new TextDecoder().decode(captured.stdout))
8130
+
8131
+ const lifetime = new AbortController()
8132
+ await runNativeCommand({
8133
+ executable: '/usr/bin/git', args: ['status'], signal: lifetime.signal,
8134
+ onOutput: async (bytes, channel, outputSignal) => {
8135
+ outputSignal.throwIfAborted()
8136
+ await output.write(bytes, channel, outputSignal) // application-owned bounded sink
8137
+ },
8138
+ })
8139
+ ```
8140
+
8141
+ Команда требует caller signal или finite `timeoutMs` (1–2147483647 ms: native timer range; большее значение отказывается, не превращается в 1 ms). Streaming имеет caller lifetime, без скрытого
8142
+ 60-second timeout или 1-MiB output limit. `capture` по умолчанию false; true требует
8143
+ `maxOutputBytes` для суммарных stdout+stderr. Лимит считает исходные bytes; API возвращает
8144
+ `Uint8Array`, не преобразует invalid UTF-8. Result содержит наблюдаемый `exitCode: number | null`
8145
+ и `signal: string | null`; signal termination не превращается в выдуманный exit code. `maxOutputBytes` может ограничивать и streaming.
8146
+ `stdin` — bytes с `maxStdinBytes` (default 1 MiB). `envPolicy` default `declared-only`: отсутствие env
8147
+ означает пустой environment; `ambient` явно разрешает наследование. Cwd/executable policy остаётся
8148
+ приложению; этот primitive запускает native executable и сам не создаёт shell.
8149
+
8150
+ Вывод читается с backpressure отдельно для stdout/stderr: один выполняющийся sink на канал плюс
8151
+ bounded native Readable buffer; накопления всей истории при streaming нет. Callback получает
8152
+ lifetime signal. Abort освобождает ожидание даже игнорирующего signal callback, но не способен
8153
+ отменить сторонние действия, которые сам callback продолжит после abort. Sink обязан отменять свои
8154
+ IO, не сохранять бесконечную историю и не изменять shared descriptor flags. После abort новых
8155
+ callbacks owner не запускает. Normal completion ждёт всех bytes и sinks.
8156
+
8157
+ Cleanup: POSIX process group, TERM, `killGraceMs` (default 100, maximum 10 000), затем KILL;
8158
+ `cleanupTimeoutMs` (default 2000, maximum 30 000) ограничивает ожидание close после сигналов.
8159
+ На Darwin временный `EPERM` при сигнале группе может означать zombies, ещё не убранные
8160
+ OS reaper. Повтор ограничен `cleanupTimeoutMs`; успех требует доставленного сигнала или
8161
+ `ESRCH`, постоянный отказ сохраняется в cause. Закрытие каждого owned pipe и выход leader
8162
+ наблюдаются отдельно, включая отсутствие общего `child.close` при teardown.
8163
+ Сохраняется caller/sink причина; failure cleanup — `NativeCommandError` с `COMMAND_CLEANUP` и
8164
+ AggregateError cause. Даже вышедший parent не исключает helper, удерживающий pipe. Windows
8165
+ отказывает с `COMMAND_UNAVAILABLE`; потомок, самостоятельно покинувший группу через setsid,
8166
+ лежит за границей этой capability. Это one-shot execution, не PTY, supervisor или daemon host.
8167
+
8168
+ ## Механическая адаптация
8169
+
8170
+ Atomic file wrapper заменяется одним вызовом `writeFileAtomic` с выбранными options. Bounded
8171
+ regular-file read заменяется `files.read`; JSON/schema, receipt conflicts, journal rotation и
8172
+ application locks сохраняются. Spawn/drain/capture/cancellation wrapper заменяется `runNativeCommand`;
8173
+ shell policy, command admission, логирование, redaction, bytes→text decoder и operator sink сохраняются.
8174
+ Длительные signal-only команды остаются streaming; bounded tar/capture получают свои явные limits.
8175
+ Импорт leaf не делает установку всего npm package маленькой; выбирайте dependency после измерения
8176
+ packed размера и dependency closure.
8177
+ ## Resource-scoped launchers and shared owners
8178
+
8179
+ `onLeaderSettled(event, signal)` observes leader exit before inherited stdout/stderr pipes
8180
+ close. A resource owner can stop its external scope there, allowing pipe drain to complete.
8181
+ The callback runs once: `event.kind === 'exit'` carries observed `exitCode`/`signal`; a terminal
8182
+ failure uses `kind: 'error'` and preserves its cause. Unavailable executables, output sink
8183
+ failure and caller cancellation settle through the same owner. `cleanupTimeoutMs` bounds
8184
+ the callback after settlement starts; it never becomes a deadline for signal-only execution.
8185
+ Honor the settlement signal; arbitrary user promises cannot be forcibly cancelled.
8186
+
8187
+ ```ts
8188
+ await runNativeCommand({
8189
+ executable: launcher,
8190
+ args,
8191
+ signal: scope.signal,
8192
+ onOutput: (bytes, channel, signal) => scope.write(bytes, channel, signal),
8193
+ onLeaderSettled: (event, signal) => scope.settle(event, signal),
8194
+ });
8195
+ ```
8196
+
8197
+ `observeProcessInstance(pid)` returns `observed` with a `ProcessInstance`, or `unavailable`
8198
+ with its cause. `probeProcessOwner(pid, recorded)` compares that evidence on the machine the
8199
+ caller established: `matched`, `different-boot`, `reused-pid`, `pid-gone`, `legacy` or
8200
+ `unavailable`. Missing/partial/denied evidence is not death. Supervisor tree fencing remains
8201
+ the caller's job; a PID lifetime is not proof that its whole workload stopped.
8202
+
8203
+ An exclusive lock applies exact requested permissions through its creating descriptor,
8204
+ independent of umask. Default `0600` stays private. Shared `0640` requires a common group and
8205
+ traversable directories; another UID also needs directory write permission to reclaim a
8206
+ proven-dead owner's file. Set `ownerlessGraceMs: null` to refuse every age-only reclaim,
8207
+ including ownerless reclaim guards. The default remains 5000 ms for existing clients.
8208
+ Восстановление stale reclaim guard использует тот же lock owner и следующий guard:
8209
+ проверка inode и удаление выполняются под ним. Конкурирующий writer не обходит guard,
8210
+ пока прежнее удаление приостановлено; live и unknown lifetime evidence остаются отказом.
8211
+
8212
+ ## Libraries with a Zod-only runtime
8213
+
8214
+ Public leaves keep optional peers out of their import closure. Installing `stitchkit` still
8215
+ installs the complete package and ky; selective imports alone do not avoid that installation.
8216
+ A library can use Stitchkit as a build dependency, bundle its selected public native imports,
8217
+ keep Zod external, and publish the resulting implementation with its library artifact.
8218
+
8219
+ ```ts
8220
+ // The library's build entry; all mechanisms remain owned by Stitchkit.
8221
+ export { canonicalJson } from 'stitchkit/primitives';
8222
+ export { writeFileAtomic, withExclusiveLock } from 'stitchkit/files';
8223
+ export { observeProcessInstance, probeProcessOwner, runNativeCommand } from 'stitchkit/process';
8224
+ ```
8225
+
8226
+ Bundle for Node-compatible execution with Zod external. Publish declarations from the same
8227
+ version: carry their reachable relative `.d.ts` closure, rather than emitting references to
8228
+ `stitchkit` that force clients to install it for types. A library exposing its own DTOs may
8229
+ instead emit declarations for only that DTO contract. Keep the library's manifest at runtime
8230
+ `dependencies: {}` and `peerDependencies: { zod: ... }` when that is its declared promise.
8231
+
8232
+ Darwin consumers need the published native binaries at the bundled loader's relative native
8233
+ directory. A JS-only bundle is not portable evidence. Qualify the packed library outside its
8234
+ build tree in Bun and Node, test its declarations, and check that importing an unbundled
8235
+ Stitchkit leaf fails there. A separate schema-only entry must not import the native entry.
8236
+
8237
+ This delivery removes a runtime kernel installation; it does not remove the build-time
8238
+ Stitchkit installation or create an independent lightweight npm package.
8239
+
8240
+
8005
8241
  ==============================================================================
8006
8242
  # Guide: Generic application primitives (docs/guide/primitives.md)
8007
8243
  ==============================================================================
@@ -8012,7 +8248,7 @@ description: Declare lifecycle, access, exact values, audit, delivery and export
8012
8248
  type: guide
8013
8249
  status: active
8014
8250
  created: 2026-09-01
8015
- updated: 2026-09-01
8251
+ updated: 2026-10-01 21:03 +07:00
8016
8252
  ---
8017
8253
 
8018
8254
  # Generic application primitives
@@ -8105,6 +8341,31 @@ of the application's existing async operation. The input, scope, metadata and to
8105
8341
  change. The application creates bytes and owns operation persistence; the managed-file boundary
8106
8342
  streams them.
8107
8343
 
8344
+ ## Canonical JSON
8345
+
8346
+ ```ts
8347
+ import { canonicalJson } from 'stitchkit/primitives'
8348
+
8349
+ const bytes = canonicalJson({ '2': 'two', '10': 'ten', optional: undefined, nested: [1, null] }, {
8350
+ maxDepth: 20, maxNodes: 10_000, maxBytes: 64 * 1024,
8351
+ })
8352
+ // {"10":"ten","2":"two","nested":[1,null]}
8353
+ // Native crypto or browser WebCrypto hashes these same UTF-8 bytes.
8354
+ ```
8355
+
8356
+ `canonicalJson` использует единый serializer исторических digest: object keys в UTF-16 code-unit
8357
+ order, включая integer-like keys; array order сохраняется. Optional object members с undefined
8358
+ опускаются. Top-level/array undefined, sparse arrays, functions/symbols/BigInt, non-finite numbers,
8359
+ negative zero, cycles, user prototypes, accessors, non-enumerable/symbol members отказаны до
8360
+ serialization. Приложение валидирует свою schema первым; canonical boundary не заменяет её.
8361
+
8362
+ Defaults: depth 100 (maximum 100), nodes 100 000, UTF-8 bytes 1 MiB. Превышение или не-JSON data —
8363
+ TypeError; неверные options — Zod validation error. Это browser-safe leaf без Node/Bun/crypto,
8364
+ agent-runtime/testing или optional peers. Native и browser используют один algorithm; hashing
8365
+ остаётся platform adapter. Переносите только serializer recursion, сохраняя proof schemas и
8366
+ verification boundary. Существующие внутренние historical normalization/digest fixtures не меняются;
8367
+ новый public boundary сознательно отказывает неоднозначным values вместо фиктивной совместимости.
8368
+
8108
8369
 
8109
8370
  ==============================================================================
8110
8371
  # Guide: Application migration recipes (docs/guide/application-migration-recipes.md)
@@ -18804,6 +19065,12 @@ schedules, transports and file generation remain application-owned.
18804
19065
 
18805
19066
  ---
18806
19067
 
19068
+ | Export | Kind | Purpose |
19069
+ |---|---|---|
19070
+ | `canonicalJson` | function | bounded plain JSON, UTF-16 key sort, optional object members omitted |
19071
+ | `CanonicalJsonOptions` | type | inferred depth/node/UTF-8 bytes limits |
19072
+
19073
+
18807
19074
  ## `stitchkit/server`
18808
19075
 
18809
19076
  Server-only. Builds and runs the HTTP server, and carries the server primitives.
@@ -20371,7 +20638,7 @@ available from `stitchkit/contract`.
20371
20638
  | `ManagedFileInspector` | _type_ | bounded-prefix read/write inspection callback with a finite cancellation signal that cannot own path or size |
20372
20639
  | `ManagedFileInspectionInput` / `ManagedFileInspection` | _type_ | inspector prefix/name/declared media/signal input and validated metadata-only result |
20373
20640
  | `writeFileAtomic` / `writeFileAtomicSync` / `WriteFileAtomicOptions` | function / _type_ | replace a file atomically: a random staging name created exclusively (never through a planted link), the mode set on the descriptor before the file is visible (default `0o600`, not masked by the umask), `fsync`, rename; a failure leaves the target and no staging file. The asynchronous form keeps the event loop running |
20374
- | `withExclusiveLock` / `ExclusiveLockOptions` / `ExclusiveLock` / `ExclusiveLockOwner` | function / _type_ | run work under an exclusive lock between processes — a file recording its owner (pid, host, machine identity, time and nullable kernel process identity); waits up to `timeoutMs` (default 10 s) and stops on `signal`; a dead owner on this machine is taken over, a live, slow or foreign one never is; an ownerless lock only after `ownerlessGraceMs` |
20641
+ | `withExclusiveLock` / `ExclusiveLockOptions` / `ExclusiveLock` / `ExclusiveLockOwner` | function / _type_ | run work under an exclusive lock between processes — a file recording its owner (pid, host, machine identity, time and nullable kernel process identity); waits up to `timeoutMs` (default 10 s) and stops on `signal`; a dead owner on this machine is taken over, a live, slow or foreign one never is; an ownerless lock only after `ownerlessGraceMs` (default 5000 ms, `null` disables age-based reclaim including guards); exact `mode` is independent of umask; shared readers need a common group and traversable directories |
20375
20642
  | `ExclusiveLockError` | class | `LOCK_TIMEOUT` naming the resource and its holder, or `LOCK_ABORTED` with the signal's reason |
20376
20643
  | `createChunkSpool` | function | the server half of a chunked upload: parts on disk under `owner` + client-minted `uploadId`, each with a size+sha256 receipt; idempotent `open` and `put`, the first writer of a part wins across processes, `assemble` in order once every part is in, `sweep` of untouched uploads — [guide](../guide/client.md#chunked-uploads) |
20377
20644
  | `ChunkSpool` / `ChunkSpoolConfig` / `ChunkSpoolKey` / `ChunkSpoolOpen` / `ChunkSpoolPart` / `ChunkSpoolAssembly` | _type_ | the spool, its directory, part size, file limit, meta schema and age; an upload's key; its declaration; one part; the assembled parts with a concatenating `stream()` |
@@ -20380,6 +20647,12 @@ available from `stitchkit/contract`.
20380
20647
 
20381
20648
  ---
20382
20649
 
20650
+ | Export | Kind | Purpose |
20651
+ |---|---|---|
20652
+ | `AtomicFilePublicationError` | class | published=true with cleanup/directory-sync/directory-close phase |
20653
+ | `FileObservation` | type | observed descriptor dev/ino/size/nlink/mtimeMs/ctimeMs |
20654
+
20655
+
20383
20656
  ## `stitchkit/telegram`
20384
20657
 
20385
20658
  Peer-free server-only Telegram platform primitives — the Bot API's own
@@ -20907,3 +21180,20 @@ AI-only peer boundary. Existing custom tool callbacks need no new import.
20907
21180
  | Export | Kind | Summary |
20908
21181
  |--------|------|---------|
20909
21182
  | `createAgentHarnessTools` / `AgentHarnessToolsConfig` | function / _type_ | async per-run full mount configuration (`services` plus all `AgentMountConfig` options); composes application lifecycle then runtime fence exactly once |
21183
+
21184
+
21185
+ ## `stitchkit/process`
21186
+
21187
+ Native POSIX Bun/Node one-shot command execution. See [native IO](../guide/native-io.md).
21188
+
21189
+ | Export | Kind | Purpose |
21190
+ |---|---|---|
21191
+ | `runNativeCommand` | function | caller-lifetime streaming or explicitly bounded binary capture |
21192
+ | `NativeCommandOptions` | type | executable/args, env policy, signal/deadline, bytes sink and finite cleanup limits |
21193
+ | `NativeCommandResult` | type | observed nullable exit code/signal and captured stdout/stderr bytes |
21194
+ | `NativeCommandError` | class | COMMAND_LIMIT, COMMAND_UNAVAILABLE or COMMAND_CLEANUP with internal cause |
21195
+
21196
+ | `NativeCommandSettlement` | type | observed leader `exit` or terminal `error`; `onLeaderSettled` runs once before drain, bounded by cleanupTimeoutMs, with a cancellable settlement signal |
21197
+ | `observeProcessInstance` / `ProcessInstanceObservation` | function / type | Linux/Darwin lifetime observation; observed identity or unavailable with its original cause, never guessed absence |
21198
+ | `ProcessInstanceSchema` / `ProcessInstance` | schema / type | platform, boot ID, namespace and process start identity from the shared native reader |
21199
+ | `probeProcessOwner` / `ProcessOwnerEvidence` | function / type | compare lifetimes on one caller-established machine; matched, boot change, reused PID, gone, legacy or unavailable with cause |
package/llms.txt CHANGED
@@ -9,18 +9,18 @@ Build with stitchkit: define a contract once, then `implement` it and serve it (
9
9
  Load the slice for each entrypoint your code imports — `import … from 'stitchkit/server'` → `llms/server.txt`; the root `stitchkit` import → `llms/stitchkit.txt`. A slice holds that entrypoint's API reference section and the guide pages whose home it is; every guide lives in exactly one slice, and a slice that needs another's guide names it under "Also read". Each file is at most 50.0 KB; a longer one continues in numbered parts, each naming the next at its top. Moving across versions: load `llms/upgrading.txt` and the range slices it lists between your version and the target. `llms-full.txt` inlines everything; it is far larger than a context window, so do not read it whole.
10
10
 
11
11
  ## Entrypoint slices
12
- - **stitchkit**: [llms/stitchkit.txt](llms/stitchkit.txt) 17.0 KB → [llms/stitchkit.2.txt](llms/stitchkit.2.txt) 45.2 KB → [llms/stitchkit.3.txt](llms/stitchkit.3.txt) 17.1 KB
12
+ - **stitchkit**: [llms/stitchkit.txt](llms/stitchkit.txt) 17.2 KB → [llms/stitchkit.2.txt](llms/stitchkit.2.txt) 45.2 KB → [llms/stitchkit.3.txt](llms/stitchkit.3.txt) 17.1 KB
13
13
  - **stitchkit/live**: [llms/live.txt](llms/live.txt) 21.6 KB
14
14
  - **stitchkit/react**: [llms/react.txt](llms/react.txt) 9.0 KB
15
15
  - **stitchkit/react/keyboard**: [llms/react-keyboard.txt](llms/react-keyboard.txt) 9.4 KB
16
- - **stitchkit/tools**: [llms/tools.txt](llms/tools.txt) 45.9 KB → [llms/tools.2.txt](llms/tools.2.txt) 26.9 KB → [llms/tools.3.txt](llms/tools.3.txt) 25.5 KB
16
+ - **stitchkit/tools**: [llms/tools.txt](llms/tools.txt) 47.4 KB → [llms/tools.2.txt](llms/tools.2.txt) 26.9 KB → [llms/tools.3.txt](llms/tools.3.txt) 25.5 KB
17
17
  - **stitchkit/tools/contract**: [llms/tools-contract.txt](llms/tools-contract.txt) 0.2 KB
18
18
  - **stitchkit/tools/invoker**: [llms/tools-invoker.txt](llms/tools-invoker.txt) 0.2 KB
19
19
  - **stitchkit/tools/connections**: [llms/tools-connections.txt](llms/tools-connections.txt) 3.1 KB
20
20
  - **stitchkit/cli**: [llms/cli.txt](llms/cli.txt) 43.6 KB → [llms/cli.2.txt](llms/cli.2.txt) 8.1 KB
21
21
  - **stitchkit/remote**: [llms/remote.txt](llms/remote.txt) 1.0 KB
22
22
  - **stitchkit/contract**: [llms/contract.txt](llms/contract.txt) 31.9 KB
23
- - **stitchkit/primitives**: [llms/primitives.txt](llms/primitives.txt) 9.3 KB
23
+ - **stitchkit/primitives**: [llms/primitives.txt](llms/primitives.txt) 11.2 KB
24
24
  - **stitchkit/server**: [llms/server.txt](llms/server.txt) 45.3 KB → [llms/server.2.txt](llms/server.2.txt) 14.6 KB → [llms/server.3.txt](llms/server.3.txt) 45.6 KB → [llms/server.4.txt](llms/server.4.txt) 38.1 KB → [llms/server.5.txt](llms/server.5.txt) 21.8 KB
25
25
  - **stitchkit/observability**: [llms/observability.txt](llms/observability.txt) 44.8 KB
26
26
  - **stitchkit/agent-runtime**: [llms/agent-runtime.txt](llms/agent-runtime.txt) 36.8 KB → [llms/agent-runtime.2.txt](llms/agent-runtime.2.txt) 46.7 KB → [llms/agent-runtime.3.txt](llms/agent-runtime.3.txt) 34.3 KB
@@ -39,7 +39,7 @@ Load the slice for each entrypoint your code imports — `import … from 'stitc
39
39
  - **stitchkit/application/schemas**: [llms/application-schemas.txt](llms/application-schemas.txt) 1.8 KB
40
40
  - **stitchkit/testing**: [llms/testing.txt](llms/testing.txt) 30.8 KB
41
41
  - **stitchkit/agent-runtime/sandbox**: [llms/agent-runtime-sandbox.txt](llms/agent-runtime-sandbox.txt) 8.1 KB
42
- - **stitchkit/files**: [llms/files.txt](llms/files.txt) 4.1 KB
42
+ - **stitchkit/files**: [llms/files.txt](llms/files.txt) 4.5 KB
43
43
  - **stitchkit/telegram**: [llms/telegram.txt](llms/telegram.txt) 26.9 KB
44
44
  - **stitchkit/telegram/html**: [llms/telegram-html.txt](llms/telegram-html.txt) 2.7 KB
45
45
  - **stitchkit/telegram/screens**: [llms/telegram-screens.txt](llms/telegram-screens.txt) 21.2 KB
@@ -55,6 +55,7 @@ Load the slice for each entrypoint your code imports — `import … from 'stitc
55
55
  - **stitchkit/agent-runtime/react**: [llms/agent-runtime-react.txt](llms/agent-runtime-react.txt) 1.0 KB
56
56
  - **stitchkit/agent-runtime/realtime**: [llms/agent-runtime-realtime.txt](llms/agent-runtime-realtime.txt) 1.8 KB
57
57
  - **stitchkit/agent-runtime/harness-tools**: [llms/agent-runtime-harness-tools.txt](llms/agent-runtime-harness-tools.txt) 1.3 KB
58
+ - **stitchkit/process**: [llms/process.txt](llms/process.txt) 15.9 KB
58
59
 
59
60
  ## Upgrading slices
60
61
  - **Upgrading — how to move across versions**: [llms/upgrading.txt](llms/upgrading.txt) 10.3 KB
@@ -75,6 +76,7 @@ Load the slice for each entrypoint your code imports — `import … from 'stitc
75
76
  - [Agent composition](https://github.com/max-listov/stitchkit/blob/master/docs/guide/agent-composition.md): tool factories, authorized realtime control, shared React views and exact-run behavior checks
76
77
  - [Managed application kernel](https://github.com/max-listov/stitchkit/blob/master/docs/guide/application-kernel.md): process-local resources, readiness, admission, schedules, projections and optional provider adapters
77
78
  - [Optional process sandbox](https://github.com/max-listov/stitchkit/blob/master/docs/guide/sandbox.md): Linux Bubblewrap sessions, durable workspace reconnect, network policy and host credential brokering
79
+ - [Native IO](https://github.com/max-listov/stitchkit/blob/master/docs/guide/native-io.md): finite commands, durable atomic publication and strict trusted-root file reads
78
80
  - [Generic application primitives](https://github.com/max-listov/stitchkit/blob/master/docs/guide/primitives.md): lifecycle transitions, owner scope, permissions, exact money and quantities, deadlines, audit, delivery and exports — declared, not persisted
79
81
  - [Application migration recipes](https://github.com/max-listov/stitchkit/blob/master/docs/guide/application-migration-recipes.md): executable database, poller, queue-consumer and operational publishing cutovers
80
82
  - [CLI](https://github.com/max-listov/stitchkit/blob/master/docs/guide/cli.md): contracts as a command-line program
Binary file
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "stitchkit",
3
- "version": "0.103.8",
3
+ "version": "0.103.10",
4
4
  "description": "Contract-first backend framework — one defineContract() into an HTTP API, MCP tools, AI-agent tools and a typed client. Bun and Node.",
5
5
  "keywords": [
6
6
  "bun",
@@ -233,6 +233,10 @@
233
233
  "./agent-runtime/harness-tools": {
234
234
  "types": "./dist/entrypoints/agent-runtime/harness-tools.d.ts",
235
235
  "import": "./dist/entrypoints/agent-runtime/harness-tools.js"
236
+ },
237
+ "./process": {
238
+ "types": "./dist/entrypoints/process.d.ts",
239
+ "import": "./dist/entrypoints/process.js"
236
240
  }
237
241
  },
238
242
  "publishConfig": {