stitchkit 0.105.2 → 0.106.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +30 -0
- package/dist/agent-runtime/coding-shell-process.d.ts.map +1 -1
- package/dist/agent-runtime/store-conformance-lifecycle.d.ts +10 -10
- package/dist/agent-runtime/store-conformance-support.d.ts +5 -5
- package/dist/entrypoints/agent-runtime/coding-tools.js +2 -2
- package/dist/entrypoints/agent-runtime/sandbox.js +2 -2
- package/dist/entrypoints/process.js +1 -1
- package/dist/{index-3s86a7kf.js → index-4q9jvqg7.js} +216 -51
- package/dist/{index-sevbwsnn.js → index-9bskshe3.js} +2 -4
- package/dist/process/cleanup.d.ts.map +1 -1
- package/dist/process/command-owner.d.ts.map +1 -1
- package/dist/process/contract.d.ts +80 -7
- package/dist/process/contract.d.ts.map +1 -1
- package/dist/process/group.d.ts +12 -0
- package/dist/process/group.d.ts.map +1 -1
- package/dist/process/launch.d.ts +5 -0
- package/dist/process/launch.d.ts.map +1 -1
- package/dist/process/output-drain.d.ts +14 -0
- package/dist/process/output-drain.d.ts.map +1 -0
- package/dist/process/owned-child.d.ts +9 -0
- package/dist/process/owned-child.d.ts.map +1 -1
- package/dist/process/terminate.d.ts +2 -0
- package/dist/process/terminate.d.ts.map +1 -1
- package/dist/process/transport.d.ts +5 -0
- package/dist/process/transport.d.ts.map +1 -1
- package/llms/process.txt +62 -17
- package/llms/stitchkit.txt +3 -3
- package/llms/{upgrading-0.37.0-0.50.0.txt → upgrading-0.37.0-0.53.0.txt} +25 -3
- package/llms/{upgrading-0.53.0-0.67.0.txt → upgrading-0.55.0-0.68.0.txt} +53 -25
- package/llms/{upgrading-0.68.0-0.94.0.txt → upgrading-0.69.0-0.95.0.txt} +45 -53
- package/llms/{upgrading-0.95.0-0.105.0.txt → upgrading-0.96.0-0.106.0.txt} +40 -45
- package/llms/upgrading.txt +4 -4
- package/llms-full.txt +102 -20
- package/llms.txt +5 -5
- package/package.json +1 -1
|
@@ -1,14 +1,56 @@
|
|
|
1
|
-
# Upgrading 0.
|
|
1
|
+
# Upgrading 0.69.0 → 0.95.0 — stitchkit docs slice
|
|
2
2
|
|
|
3
3
|
> Generated from the `docs/` tree by `bun run gen:llms`. The index of all slices is
|
|
4
4
|
> `llms.txt` in this package.
|
|
5
5
|
|
|
6
|
-
Contains: Guide: Upgrading, 0.
|
|
6
|
+
Contains: Guide: Upgrading, 0.69.0 → 0.95.0 (docs/guide/upgrading.md)
|
|
7
7
|
|
|
8
8
|
==============================================================================
|
|
9
|
-
# Guide: Upgrading, 0.
|
|
9
|
+
# Guide: Upgrading, 0.69.0 → 0.95.0 (docs/guide/upgrading.md)
|
|
10
10
|
==============================================================================
|
|
11
11
|
|
|
12
|
+
## Released migration: 0.95.0
|
|
13
|
+
|
|
14
|
+
One breaking change in `stitchkit/application`: the process lifecycle ledger
|
|
15
|
+
counts downtime as the window nobody answered in, and gains the `draining`
|
|
16
|
+
phase and the `startup-failed` outcome. A ledger file written by an earlier
|
|
17
|
+
version loads unchanged — the new `unavailableAt` reads as `null`.
|
|
18
|
+
|
|
19
|
+
1. **Read downtime from the ready fact.** **Who must act:** a project that
|
|
20
|
+
reads `downtimeMs` from a `started` fact. It is gone from `StartFact`; the
|
|
21
|
+
number it carried is `processGapMs`. The downtime now arrives with the new
|
|
22
|
+
run's readiness:
|
|
23
|
+
|
|
24
|
+
```ts
|
|
25
|
+
// before
|
|
26
|
+
ledger.subscribe((fact) => {
|
|
27
|
+
if (fact.type === 'started') report(fact.previousExit, fact.downtimeMs);
|
|
28
|
+
});
|
|
29
|
+
// after
|
|
30
|
+
ledger.subscribe((fact) => {
|
|
31
|
+
if (fact.type === 'started') previousExit = fact.previousExit;
|
|
32
|
+
if (fact.type === 'ready') report(previousExit, fact.downtimeMs);
|
|
33
|
+
});
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
2. **Handle the new values.** **Who must act:** a project that switches
|
|
37
|
+
exhaustively over `LifecycleTermination` (new: `draining`,
|
|
38
|
+
`startup-failed`), `PreviousExit` (new: `startup-failed`) or
|
|
39
|
+
`ProcessLifecycleFact` (new: `DrainingFact`, `type: 'draining'`). The type
|
|
40
|
+
checker names each switch. An open run is `active` or `draining`; a check
|
|
41
|
+
written as `termination === 'active'` to mean "still running" becomes
|
|
42
|
+
`termination === 'active' || termination === 'draining'`.
|
|
43
|
+
`TransitionReadyInput` is renamed `TransitionRunInput` — the same fields,
|
|
44
|
+
now also taken by `transitionProcessDraining`; rename the import.
|
|
45
|
+
|
|
46
|
+
3. **Record the drain and the readiness when driving the ledger by hand.**
|
|
47
|
+
**Who must act:** only a project that calls `createProcessLifecycleLedger`
|
|
48
|
+
methods itself instead of mounting `lifecycleLedgerResource`. Call
|
|
49
|
+
`recordDraining()` where the application stops admitting work, before it
|
|
50
|
+
drains; without it downtime is counted from the recorded stop. Call
|
|
51
|
+
`recordReady()` when the run serves; a run stopped without it now ends
|
|
52
|
+
`startup-failed`, not `clean`.
|
|
53
|
+
|
|
12
54
|
## Released migration: 0.94.0
|
|
13
55
|
|
|
14
56
|
One breaking minor that consolidates: tool options move into one group, and
|
|
@@ -1107,53 +1149,3 @@ else renderExistingRole(message)
|
|
|
1107
1149
|
|
|
1108
1150
|
No data migration is needed. The schema still accepts all earlier records, and applications that
|
|
1109
1151
|
do not exhaustively branch over these unions compile unchanged.
|
|
1110
|
-
|
|
1111
|
-
## Released migration: 0.68.0
|
|
1112
|
-
|
|
1113
|
-
### Make Unix transport selection explicit outside Bun
|
|
1114
|
-
|
|
1115
|
-
The legacy `unix` option remains a Bun convenience, but on Node or another
|
|
1116
|
-
runtime it now fails before dispatch. Replace it with the owned adapter and close
|
|
1117
|
-
that adapter with the application:
|
|
1118
|
-
|
|
1119
|
-
```ts
|
|
1120
|
-
// before — unsafe outside Bun: an unsupported fetch could dial baseUrl over TCP
|
|
1121
|
-
const http = createHttpClient({ baseUrl, unix: '/run/service.sock' })
|
|
1122
|
-
|
|
1123
|
-
// after — Bun and Node; every dispatch and redirect stays on the socket
|
|
1124
|
-
import { createUnixClientTransport } from 'stitchkit/server' // or stitchkit/node
|
|
1125
|
-
const transport = createUnixClientTransport({ socketPath: '/run/service.sock' })
|
|
1126
|
-
const http = createHttpClient({ baseUrl, fetch: transport.fetch })
|
|
1127
|
-
// during shutdown
|
|
1128
|
-
await transport.close()
|
|
1129
|
-
```
|
|
1130
|
-
|
|
1131
|
-
Do not automatically replay `possibly-dispatched`: a timeout or connection loss
|
|
1132
|
-
after bytes left the process does not prove that a write did not happen.
|
|
1133
|
-
|
|
1134
|
-
### Choose tolerant stream parsing explicitly
|
|
1135
|
-
|
|
1136
|
-
`parseNDJSON` and `parseSSE` now throw on malformed JSON, invalid UTF-8 and an
|
|
1137
|
-
over-limit line. The default line ceiling is 1 MiB. If a feed deliberately skips
|
|
1138
|
-
bad records, retain that policy explicitly:
|
|
1139
|
-
|
|
1140
|
-
```ts
|
|
1141
|
-
// before — malformed input disappeared implicitly
|
|
1142
|
-
parseNDJSON(response)
|
|
1143
|
-
|
|
1144
|
-
// after — ordinary fail-closed path
|
|
1145
|
-
parseNDJSON(response, { maxLineBytes: 256 * 1024 })
|
|
1146
|
-
|
|
1147
|
-
// after — deliberately tolerant path
|
|
1148
|
-
parseNDJSON(response, { onParseError: (raw, error) => report(raw, error) })
|
|
1149
|
-
```
|
|
1150
|
-
|
|
1151
|
-
### Extend exhaustive framework-error handling
|
|
1152
|
-
|
|
1153
|
-
If a switch makes `StitchErrorCode` exhaustive, add
|
|
1154
|
-
`STREAM_ITEM_INVALID`, `STREAM_FRAME_TOO_LARGE`,
|
|
1155
|
-
`STREAM_TERMINAL_MISSING` and `STREAM_LIFETIME_EXCEEDED`. A partial application
|
|
1156
|
-
status map needs no change (ADR 0105).
|
|
1157
|
-
|
|
1158
|
-
The admission/channel APIs and endpoint `stream` descriptor are additive; raw
|
|
1159
|
-
responses and raw `streamingRoute` remain supported.
|
|
@@ -1,14 +1,51 @@
|
|
|
1
|
-
# Upgrading 0.
|
|
1
|
+
# Upgrading 0.96.0 → 0.106.0 — stitchkit docs slice
|
|
2
2
|
|
|
3
3
|
> Generated from the `docs/` tree by `bun run gen:llms`. The index of all slices is
|
|
4
4
|
> `llms.txt` in this package.
|
|
5
5
|
|
|
6
|
-
Contains: Guide: Upgrading, 0.
|
|
6
|
+
Contains: Guide: Upgrading, 0.96.0 → 0.106.0 (docs/guide/upgrading.md)
|
|
7
7
|
|
|
8
8
|
==============================================================================
|
|
9
|
-
# Guide: Upgrading, 0.
|
|
9
|
+
# Guide: Upgrading, 0.96.0 → 0.106.0 (docs/guide/upgrading.md)
|
|
10
10
|
==============================================================================
|
|
11
11
|
|
|
12
|
+
## Released migration: 0.106.0
|
|
13
|
+
|
|
14
|
+
### a stopped leader settles as stopped
|
|
15
|
+
|
|
16
|
+
**Who must act:** code passed to `onLeaderSettled` of `runNativeCommand` (`stitchkit/process`) that
|
|
17
|
+
reads `kind: 'error'` as "the command was stopped". Code that only handles `kind: 'exit'`, or does
|
|
18
|
+
not pass `onLeaderSettled`, needs no change.
|
|
19
|
+
|
|
20
|
+
A command stopped by a caller abort, its `timeoutMs`, an exceeded output budget or a failing sink
|
|
21
|
+
used to settle at once as `{ kind: 'error', cause }`. It now waits for the stop signals and settles
|
|
22
|
+
as `{ kind: 'stopped', cause, exitCode, signal }`, with how the kernel reported the leader's end
|
|
23
|
+
([ADR 0248](../decisions/0248-a-stopped-leader-settles-with-its-exit-and-a-command-may-join-the-callers-group.md)).
|
|
24
|
+
`'error'` is left for a leader whose exit was never observed.
|
|
25
|
+
|
|
26
|
+
1. Where the hook handled a stop under `'error'`, handle `'stopped'` there, and take the exit from
|
|
27
|
+
the event instead of reading the child process:
|
|
28
|
+
|
|
29
|
+
```ts
|
|
30
|
+
// before
|
|
31
|
+
onLeaderSettled: (event) => {
|
|
32
|
+
if (event.kind === 'exit') record(event.exitCode, event.signal)
|
|
33
|
+
else stopped(event.cause)
|
|
34
|
+
}
|
|
35
|
+
// after
|
|
36
|
+
onLeaderSettled: (event) => {
|
|
37
|
+
if (event.kind === 'error') return failed(event.cause)
|
|
38
|
+
record(event.exitCode, event.signal)
|
|
39
|
+
if (event.kind === 'stopped') stopped(event.cause)
|
|
40
|
+
}
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Search pattern: `onLeaderSettled` together with `kind === 'error'` or `kind !== 'exit'`.
|
|
44
|
+
2. Type-check: an exhaustive `switch (event.kind)` without a `'stopped'` case fails on the new kind.
|
|
45
|
+
3. A hook that stops an external scope on a stopped command now runs once the leader is gone,
|
|
46
|
+
still bounded by `cleanupTimeoutMs`; no change is needed unless the leader waited for that scope
|
|
47
|
+
to exit (it gets KILL when the grace ends either way).
|
|
48
|
+
|
|
12
49
|
## Released migration: 0.105.0
|
|
13
50
|
|
|
14
51
|
### CLI publication has its own entrypoint
|
|
@@ -895,45 +932,3 @@ it; only a context built by hand needs it.
|
|
|
895
932
|
hand before `bot.stop()`. A project that wrote its own `getUpdates`
|
|
896
933
|
transformer for this (waiting on `app.admission` before returning a batch)
|
|
897
934
|
deletes it; keeping both waits twice and is harmless.
|
|
898
|
-
|
|
899
|
-
## Released migration: 0.95.0
|
|
900
|
-
|
|
901
|
-
One breaking change in `stitchkit/application`: the process lifecycle ledger
|
|
902
|
-
counts downtime as the window nobody answered in, and gains the `draining`
|
|
903
|
-
phase and the `startup-failed` outcome. A ledger file written by an earlier
|
|
904
|
-
version loads unchanged — the new `unavailableAt` reads as `null`.
|
|
905
|
-
|
|
906
|
-
1. **Read downtime from the ready fact.** **Who must act:** a project that
|
|
907
|
-
reads `downtimeMs` from a `started` fact. It is gone from `StartFact`; the
|
|
908
|
-
number it carried is `processGapMs`. The downtime now arrives with the new
|
|
909
|
-
run's readiness:
|
|
910
|
-
|
|
911
|
-
```ts
|
|
912
|
-
// before
|
|
913
|
-
ledger.subscribe((fact) => {
|
|
914
|
-
if (fact.type === 'started') report(fact.previousExit, fact.downtimeMs);
|
|
915
|
-
});
|
|
916
|
-
// after
|
|
917
|
-
ledger.subscribe((fact) => {
|
|
918
|
-
if (fact.type === 'started') previousExit = fact.previousExit;
|
|
919
|
-
if (fact.type === 'ready') report(previousExit, fact.downtimeMs);
|
|
920
|
-
});
|
|
921
|
-
```
|
|
922
|
-
|
|
923
|
-
2. **Handle the new values.** **Who must act:** a project that switches
|
|
924
|
-
exhaustively over `LifecycleTermination` (new: `draining`,
|
|
925
|
-
`startup-failed`), `PreviousExit` (new: `startup-failed`) or
|
|
926
|
-
`ProcessLifecycleFact` (new: `DrainingFact`, `type: 'draining'`). The type
|
|
927
|
-
checker names each switch. An open run is `active` or `draining`; a check
|
|
928
|
-
written as `termination === 'active'` to mean "still running" becomes
|
|
929
|
-
`termination === 'active' || termination === 'draining'`.
|
|
930
|
-
`TransitionReadyInput` is renamed `TransitionRunInput` — the same fields,
|
|
931
|
-
now also taken by `transitionProcessDraining`; rename the import.
|
|
932
|
-
|
|
933
|
-
3. **Record the drain and the readiness when driving the ledger by hand.**
|
|
934
|
-
**Who must act:** only a project that calls `createProcessLifecycleLedger`
|
|
935
|
-
methods itself instead of mounting `lifecycleLedgerResource`. Call
|
|
936
|
-
`recordDraining()` where the application stops admitting work, before it
|
|
937
|
-
drains; without it downtime is counted from the recorded stop. Call
|
|
938
|
-
`recordReady()` when the run serves; a run stopped without it now ends
|
|
939
|
-
`startup-failed`, not `clean`.
|
package/llms/upgrading.txt
CHANGED
|
@@ -11,10 +11,10 @@ Contains: Guide: Upgrading, general (docs/guide/upgrading.md)
|
|
|
11
11
|
|
|
12
12
|
Load this slice, then every range slice between your installed version and the target:
|
|
13
13
|
|
|
14
|
-
- 0.
|
|
15
|
-
- 0.
|
|
16
|
-
- 0.
|
|
17
|
-
- 0.37.0 → 0.
|
|
14
|
+
- 0.96.0 → 0.106.0: `llms/upgrading-0.96.0-0.106.0.txt`
|
|
15
|
+
- 0.69.0 → 0.95.0: `llms/upgrading-0.69.0-0.95.0.txt`
|
|
16
|
+
- 0.55.0 → 0.68.0: `llms/upgrading-0.55.0-0.68.0.txt`
|
|
17
|
+
- 0.37.0 → 0.53.0: `llms/upgrading-0.37.0-0.53.0.txt`
|
|
18
18
|
|
|
19
19
|
# Upgrading stitchkit
|
|
20
20
|
|
package/llms-full.txt
CHANGED
|
@@ -74,12 +74,12 @@ own, recorded as an ADR.
|
|
|
74
74
|
| `stitchkit/geo` | server (Bun or Node) | evolving | managed GeoIP reader generations, last-known-good reload and the optional MaxMind adapter |
|
|
75
75
|
| `stitchkit/oauth` | browser **and** server | evolving | provider-neutral Authorization Code + PKCE request and one-shot callback transaction mechanics |
|
|
76
76
|
| `stitchkit/google` | server (Bun or Node) | evolving | optional Google code exchange and verified OIDC identity adapter |
|
|
77
|
-
| `stitchkit/observability` | server | stable<br>_redefined in 2 of the
|
|
77
|
+
| `stitchkit/observability` | server | stable<br>_redefined in 2 of the 51 minors since 0.56.2, most recently 0.92.0_ | request/tool event projections — `createObservability`, trace context, sanitisation |
|
|
78
78
|
| `stitchkit/testing` | tests on Bun or Node | stable | in-process generated clients over a real Fetch handler, plus the managed-resource conformance kit |
|
|
79
79
|
| `stitchkit/declaration` | browser + build and deployment tooling (Bun or Node) | evolving | `ProjectDeclarationSchema` — the one machine-readable statement a repository makes about itself |
|
|
80
80
|
| `stitchkit/react` | browser + server rendering | stable | `createCursorQuery`, `createCacheBridge`, QueryClient and `ApiError` retry policy |
|
|
81
81
|
| `stitchkit/react/keyboard` | browser | evolving | which part of a screen gets a key — ordered layers, one Escape per level, list zones with real focus; see [keyboard guide](keyboard.md) |
|
|
82
|
-
| `stitchkit/agent-runtime` | server | evolving<br>_redefined in 23 of the
|
|
82
|
+
| `stitchkit/agent-runtime` | server | evolving<br>_redefined in 23 of the 51 minors since 0.56.2, most recently 0.105.0_ | optional durable conversation/run loop, history, models, prompts, fencing and events |
|
|
83
83
|
| `stitchkit/agent-runtime/sandbox` | server | evolving | optional Linux Bubblewrap sessions, durable workspaces and a host HTTP credential gateway; see [sandbox guide](sandbox.md) |
|
|
84
84
|
| `stitchkit/agent-runtime/testing` | tests on Bun or Node | evolving | credential-free replay, scripted provider faults, deterministic race controls and the agent-store conformance kit |
|
|
85
85
|
| `stitchkit/agent-runtime/harness` | server | evolving | resource-aware process-local facade over the canonical Agent runtime; supervision stays outside |
|
|
@@ -91,7 +91,7 @@ own, recorded as an ADR.
|
|
|
91
91
|
| `stitchkit/agent-runtime/sqlite/bun` | server (Bun) | evolving | durable built-in SQLite store for the agent runtime |
|
|
92
92
|
| `stitchkit/agent-runtime/sqlite/node` | server (Node ≥ 22.5) | evolving | durable built-in SQLite store for the agent runtime |
|
|
93
93
|
| `stitchkit-tui` | terminal (Bun) | evolving | optional official OpenTUI host over a caller-composed headless runtime |
|
|
94
|
-
| `stitchkit/application` | browser + server | evolving<br>_redefined in 13 of the
|
|
94
|
+
| `stitchkit/application` | browser + server | evolving<br>_redefined in 13 of the 51 minors since 0.56.2, most recently 0.105.0_ | managed resource graph, readiness, admission, schedules, subtree restart and bounded shutdown |
|
|
95
95
|
| `stitchkit/application/grammy` | server | evolving | a grammY bot as application resources — configuration, then polling with updates admitted by batch — and the webhook adapter |
|
|
96
96
|
| `stitchkit/application/opentelemetry` | server | evolving | maps application snapshots onto an injected OpenTelemetry `Meter` |
|
|
97
97
|
| `stitchkit/application/schemas` | browser + server | evolving | the application's snapshot, health and shutdown schemas alone, without the kernel |
|
|
@@ -8355,7 +8355,9 @@ command the same way, by its `stop` policy:
|
|
|
8355
8355
|
| `graceMs` | How long the leader (or the group) has to leave before the whole group gets KILL. 0 to 3 600 000 (one hour). Required. |
|
|
8356
8356
|
| `killOn` | Optional `AbortSignal`. Its abort stops the command with KILL to the whole group at once, also in the middle of a grace. |
|
|
8357
8357
|
|
|
8358
|
-
Omitting `stop` means `{ target: 'group', signal: 'SIGTERM', graceMs: 100 }
|
|
8358
|
+
Omitting `stop` means `{ target: 'group', signal: 'SIGTERM', graceMs: 100 }`; a command in the
|
|
8359
|
+
caller's group (`group: 'caller'`) stops its leader alone, so its default is `target: 'leader'`
|
|
8360
|
+
and a group target is refused (see [Terminal commands](#terminal-commands-inherited-stdio-and-the-callers-group)).
|
|
8359
8361
|
|
|
8360
8362
|
```ts
|
|
8361
8363
|
// Cooperative cancellation: the leader rolls its work back, its helpers are not asked.
|
|
@@ -8426,7 +8428,8 @@ await runNativeCommand({
|
|
|
8426
8428
|
})
|
|
8427
8429
|
```
|
|
8428
8430
|
|
|
8429
|
-
A command
|
|
8431
|
+
A command in the caller's group (`group: 'caller'`) has no group of its own: `descendants` is
|
|
8432
|
+
refused there and nothing is stopped after its leader exits. A command whose group this package did not create (a structural
|
|
8430
8433
|
launcher supplied by a host) has no group to stop, and `descendants` has nothing to act on there.
|
|
8431
8434
|
|
|
8432
8435
|
|
|
@@ -8442,26 +8445,68 @@ bounded tar or capture commands get their own explicit limits.
|
|
|
8442
8445
|
A child the caller holds until it exits is the same call. A guardian that forwards its own SIGTERM
|
|
8443
8446
|
passes an abort signal and `stop: { target: 'leader', signal: 'SIGTERM', graceMs }`. It records the
|
|
8444
8447
|
pid in `onLeaderStarted({ pid })`, which runs once right after the leader exists (a throw stops the
|
|
8445
|
-
command with that error),
|
|
8446
|
-
|
|
8447
|
-
|
|
8448
|
-
|
|
8449
|
-
`
|
|
8450
|
-
|
|
8451
|
-
|
|
8452
|
-
|
|
8453
|
-
terminal is stopped by the kernel (`SIGTTIN`), so an interactive re-execution stays a plain
|
|
8454
|
-
spawn in the caller's group. Importing one leaf does not make
|
|
8448
|
+
command with that error), and the leader's exit code and signal in `onLeaderSettled`: `'exit'`
|
|
8449
|
+
when the leader ended on its own, `'stopped'` with the same fields when the guardian stopped it.
|
|
8450
|
+
It reads stderr through `onOutput` or `capture` with `maxOutputBytes`. `drainTimeoutMs` bounds how
|
|
8451
|
+
long the output pipes may stay open after the leader exited: a holder that left the group with
|
|
8452
|
+
`setsid` keeps them open, and without the option the command waits for it until `timeoutMs` or
|
|
8453
|
+
the signal; with it the command ends with `COMMAND_CLEANUP` (a holder inside the group is already
|
|
8454
|
+
stopped by `descendants`). A worker whose whole group must stop on abort is the default
|
|
8455
|
+
`target: 'group'`. A command that uses the caller's terminal is the next section. Importing one leaf does not make
|
|
8455
8456
|
installing the whole npm package smaller; choose a dependency after measuring packed size and its
|
|
8456
8457
|
dependency closure.
|
|
8457
8458
|
|
|
8459
|
+
## Terminal commands: inherited stdio and the caller's group
|
|
8460
|
+
|
|
8461
|
+
An operator CLI that re-runs itself, or any command that prompts or prints in colour, needs the
|
|
8462
|
+
caller's terminal itself rather than pipes. Two options give it that:
|
|
8463
|
+
|
|
8464
|
+
```ts
|
|
8465
|
+
const { exitCode } = await runNativeCommand({
|
|
8466
|
+
executable: process.execPath, args: [cliPath, ...argv], envPolicy: 'ambient',
|
|
8467
|
+
signal: shutdown.signal,
|
|
8468
|
+
stdio: 'inherit', // the command's stdin, stdout and stderr are the caller's: a TTY stays a TTY
|
|
8469
|
+
group: 'caller', // it joins the caller's process group, so a Ctrl-C at the terminal reaches it
|
|
8470
|
+
})
|
|
8471
|
+
process.exitCode = exitCode ?? 1
|
|
8472
|
+
```
|
|
8473
|
+
|
|
8474
|
+
`stdio: 'inherit'` hands the caller's three descriptors to the command; its bytes never pass
|
|
8475
|
+
through this package, so `capture`, `onOutput`, `stdin`, `maxOutputBytes` and `drainTimeoutMs` are
|
|
8476
|
+
refused by name with it, and the result's buffers stay empty.
|
|
8477
|
+
|
|
8478
|
+
`group: 'caller'` keeps the command in the caller's process group instead of a group of its own.
|
|
8479
|
+
That is what an interactive command needs: the terminal sends Ctrl-C to its foreground group,
|
|
8480
|
+
and a command in a group of its own is a background group there, which the kernel stops
|
|
8481
|
+
(`SIGTTIN`) as soon as it reads the terminal. In the caller's group the command has no group of
|
|
8482
|
+
its own, so:
|
|
8483
|
+
|
|
8484
|
+
- a stop signals the leader alone: `stop.target` is `'leader'` (the default here is
|
|
8485
|
+
`{ target: 'leader', signal: 'SIGTERM', graceMs: 100 }`), and `target: 'group'` is refused,
|
|
8486
|
+
because a group signal would reach the caller;
|
|
8487
|
+
- `descendants` does not apply and is refused: what the leader leaves behind belongs to the
|
|
8488
|
+
caller's group, and `descendantsStopped` is always `false`;
|
|
8489
|
+
- a Ctrl-C reaches the caller too; handle `SIGINT` in the caller when it must outlive the command.
|
|
8490
|
+
|
|
8491
|
+
The two options are independent: `stdio: 'inherit'` alone keeps colour and `isatty` for a command
|
|
8492
|
+
that never reads the terminal, and `group: 'caller'` alone forwards Ctrl-C to a piped command.
|
|
8493
|
+
|
|
8458
8494
|
## Resource-scoped launchers and shared owners
|
|
8459
8495
|
|
|
8460
8496
|
`onLeaderSettled(event, signal)` observes leader exit before inherited stdout/stderr pipes
|
|
8461
8497
|
close. A resource owner can stop its external scope there, allowing pipe drain to complete.
|
|
8462
|
-
The callback runs once
|
|
8463
|
-
|
|
8464
|
-
|
|
8498
|
+
The callback runs once, with one of three events:
|
|
8499
|
+
|
|
8500
|
+
| `event.kind` | when | carries |
|
|
8501
|
+
|---|---|---|
|
|
8502
|
+
| `'exit'` | the leader ended on its own | `exitCode`, `signal` as the kernel reported them |
|
|
8503
|
+
| `'stopped'` | the command was stopped (caller abort, `timeoutMs`, output budget, failing sink) and the leader's exit after the stop signals was observed | the stop's `cause`, and the leader's `exitCode` and `signal` (for example `SIGTERM`, or `SIGKILL` once the grace ended) |
|
|
8504
|
+
| `'error'` | no exit of the leader was observed: it could not start, or its exit did not arrive within `cleanupTimeoutMs` | the `cause` |
|
|
8505
|
+
|
|
8506
|
+
A leader that ended on its own settles before the pipes drain; a stopped one settles after the
|
|
8507
|
+
stop sequence, once its exit is known. A stop that comes after the leader already exited (a
|
|
8508
|
+
deadline while a helper holds the pipe) does not change its `'exit'` event. Unavailable
|
|
8509
|
+
executables, output sink failure and caller cancellation settle through the same owner. Synchronous native launch
|
|
8465
8510
|
failures such as `E2BIG` also return a rejected result after this bounded settlement;
|
|
8466
8511
|
schema-invalid and already-aborted inputs refuse before native ownership and do not invoke
|
|
8467
8512
|
the hook. A failing hook preserves both the initial launch error and cleanup cause.
|
|
@@ -15533,6 +15578,43 @@ analytics policy belong to the application.
|
|
|
15533
15578
|
|
|
15534
15579
|
# Upgrading stitchkit
|
|
15535
15580
|
|
|
15581
|
+
## Released migration: 0.106.0
|
|
15582
|
+
|
|
15583
|
+
### a stopped leader settles as stopped
|
|
15584
|
+
|
|
15585
|
+
**Who must act:** code passed to `onLeaderSettled` of `runNativeCommand` (`stitchkit/process`) that
|
|
15586
|
+
reads `kind: 'error'` as "the command was stopped". Code that only handles `kind: 'exit'`, or does
|
|
15587
|
+
not pass `onLeaderSettled`, needs no change.
|
|
15588
|
+
|
|
15589
|
+
A command stopped by a caller abort, its `timeoutMs`, an exceeded output budget or a failing sink
|
|
15590
|
+
used to settle at once as `{ kind: 'error', cause }`. It now waits for the stop signals and settles
|
|
15591
|
+
as `{ kind: 'stopped', cause, exitCode, signal }`, with how the kernel reported the leader's end
|
|
15592
|
+
([ADR 0248](../decisions/0248-a-stopped-leader-settles-with-its-exit-and-a-command-may-join-the-callers-group.md)).
|
|
15593
|
+
`'error'` is left for a leader whose exit was never observed.
|
|
15594
|
+
|
|
15595
|
+
1. Where the hook handled a stop under `'error'`, handle `'stopped'` there, and take the exit from
|
|
15596
|
+
the event instead of reading the child process:
|
|
15597
|
+
|
|
15598
|
+
```ts
|
|
15599
|
+
// before
|
|
15600
|
+
onLeaderSettled: (event) => {
|
|
15601
|
+
if (event.kind === 'exit') record(event.exitCode, event.signal)
|
|
15602
|
+
else stopped(event.cause)
|
|
15603
|
+
}
|
|
15604
|
+
// after
|
|
15605
|
+
onLeaderSettled: (event) => {
|
|
15606
|
+
if (event.kind === 'error') return failed(event.cause)
|
|
15607
|
+
record(event.exitCode, event.signal)
|
|
15608
|
+
if (event.kind === 'stopped') stopped(event.cause)
|
|
15609
|
+
}
|
|
15610
|
+
```
|
|
15611
|
+
|
|
15612
|
+
Search pattern: `onLeaderSettled` together with `kind === 'error'` or `kind !== 'exit'`.
|
|
15613
|
+
2. Type-check: an exhaustive `switch (event.kind)` without a `'stopped'` case fails on the new kind.
|
|
15614
|
+
3. A hook that stops an external scope on a stopped command now runs once the leader is gone,
|
|
15615
|
+
still bounded by `cleanupTimeoutMs`; no change is needed unless the leader waited for that scope
|
|
15616
|
+
to exit (it gets KILL when the grace ends either way).
|
|
15617
|
+
|
|
15536
15618
|
## Released migration: 0.105.0
|
|
15537
15619
|
|
|
15538
15620
|
### CLI publication has its own entrypoint
|
|
@@ -22646,12 +22728,12 @@ Native POSIX Bun/Node one-shot command execution. See [native IO](../guide/nativ
|
|
|
22646
22728
|
| Export | Kind | Purpose |
|
|
22647
22729
|
|---|---|---|
|
|
22648
22730
|
| `runNativeCommand` | function | caller-lifetime streaming or explicitly bounded binary capture |
|
|
22649
|
-
| `NativeCommandOptions` | type | executable/args, env policy, signal/deadline, bytes sink, finite cleanup limits, the `stop` policy and `descendants` (`'terminate-after-leader'`, the default: stop the group after the leader exits, or `'leave'`); `onLeaderStarted({ pid })` (once, after the leader exists), `drainTimeoutMs` (bound on the pipes staying open after the leader exited, `COMMAND_CLEANUP`); an unknown key is refused by name, a removed one (`killGraceMs`) with its replacement |
|
|
22731
|
+
| `NativeCommandOptions` | type | executable/args, env policy, signal/deadline, bytes sink, finite cleanup limits, the `stop` policy and `descendants` (`'terminate-after-leader'`, the default: stop the group after the leader exits, or `'leave'`); `stdio` (`'pipe'`, or `'inherit'` for the caller's descriptors, refusing the pipe-only options) and `group` (`'own'`, or `'caller'`: joins the caller's process group, stops only the leader, refuses `descendants` and a group stop); `onLeaderStarted({ pid })` (once, after the leader exists), `drainTimeoutMs` (bound on the pipes staying open after the leader exited, `COMMAND_CLEANUP`); an unknown key is refused by name, a removed one (`killGraceMs`) with its replacement |
|
|
22650
22732
|
| `NativeCommandStopPolicy` | type | how a cancelled command stops: `target` `'group'` (signal every member) or `'leader'` (signal only the leader; its exit ends the grace), `signal` (default `SIGTERM`), `graceMs` (at most one hour) before KILL to the group, and `killOn`, an `AbortSignal` that skips the grace; default `{ target: 'group', signal: 'SIGTERM', graceMs: 100 }` |
|
|
22651
22733
|
| `NativeCommandResult` | type | observed nullable exit code/signal, `descendantsStopped` (members left in the group after the leader exited were stopped) and captured stdout/stderr bytes |
|
|
22652
22734
|
| `NativeCommandError` | class | COMMAND_LIMIT with machine reason `deadline` or `output-budget`; COMMAND_UNAVAILABLE / COMMAND_CLEANUP have no limit reason. Preserves internal cause and existing constructor; caller-created limits without supplied reason remain unclassified |
|
|
22653
22735
|
|
|
22654
|
-
| `NativeCommandSettlement` | type |
|
|
22736
|
+
| `NativeCommandSettlement` | type | `exit` (the leader ended on its own), `stopped` (the command was stopped and the leader's exit after the stop observed: the stop's `cause` with `exitCode`/`signal`) or `error` (no exit observed), including synchronous native launch failure; `onLeaderSettled` runs once before drain, bounded by cleanupTimeoutMs, with a cancellable settlement signal; schema/pre-abort refusal creates no settlement obligation |
|
|
22655
22737
|
| `observeProcessInstance` / `ProcessInstanceObservation` | function / type | Linux/Darwin lifetime observation; observed identity or unavailable with its original cause, never guessed absence |
|
|
22656
22738
|
| `ProcessInstanceSchema` / `ProcessInstance` | schema / type | platform, boot ID, namespace and process start identity from the shared native reader |
|
|
22657
22739
|
| `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
|
@@ -56,15 +56,15 @@ Load the slice for each entrypoint your code imports — `import … from 'stitc
|
|
|
56
56
|
- **stitchkit/node**: [llms/node.txt](llms/node.txt) 3.1 KB
|
|
57
57
|
- **stitchkit/agent-runtime/react**: [llms/agent-runtime-react.txt](llms/agent-runtime-react.txt) 1.0 KB
|
|
58
58
|
- **stitchkit/agent-runtime/realtime**: [llms/agent-runtime-realtime.txt](llms/agent-runtime-realtime.txt) 2.6 KB
|
|
59
|
-
- **stitchkit/process**: [llms/process.txt](llms/process.txt)
|
|
59
|
+
- **stitchkit/process**: [llms/process.txt](llms/process.txt) 39.4 KB
|
|
60
60
|
- **stitchkit/files/packaging**: [llms/files-packaging.txt](llms/files-packaging.txt) 2.8 KB
|
|
61
61
|
|
|
62
62
|
## Upgrading slices
|
|
63
63
|
- **Upgrading — how to move across versions**: [llms/upgrading.txt](llms/upgrading.txt) 10.3 KB
|
|
64
|
-
- **Upgrading 0.
|
|
65
|
-
- **Upgrading 0.
|
|
66
|
-
- **Upgrading 0.
|
|
67
|
-
- **Upgrading 0.37.0 → 0.
|
|
64
|
+
- **Upgrading 0.96.0 → 0.106.0**: [llms/upgrading-0.96.0-0.106.0.txt](llms/upgrading-0.96.0-0.106.0.txt) 46.6 KB
|
|
65
|
+
- **Upgrading 0.69.0 → 0.95.0**: [llms/upgrading-0.69.0-0.95.0.txt](llms/upgrading-0.69.0-0.95.0.txt) 46.6 KB
|
|
66
|
+
- **Upgrading 0.55.0 → 0.68.0**: [llms/upgrading-0.55.0-0.68.0.txt](llms/upgrading-0.55.0-0.68.0.txt) 47.0 KB
|
|
67
|
+
- **Upgrading 0.37.0 → 0.53.0**: [llms/upgrading-0.37.0-0.53.0.txt](llms/upgrading-0.37.0-0.53.0.txt) 32.6 KB
|
|
68
68
|
|
|
69
69
|
## Guide (web)
|
|
70
70
|
- [Getting started](https://github.com/max-listov/stitchkit/blob/master/docs/guide/getting-started.md): install, entrypoints, and a first contract → server → client app
|
package/package.json
CHANGED