@orkestrel/scaffold 0.0.67 → 0.0.69

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 (74) hide show
  1. package/dist/bin/main.js +67 -44
  2. package/dist/bin/main.js.map +1 -1
  3. package/dist/host/agents/templates/brief.md +9 -0
  4. package/dist/host/claude/agents/orkestrel.md +4 -4
  5. package/dist/host/claude/rules/names.md +15 -0
  6. package/dist/host/claude/rules/tests.md +33 -4
  7. package/dist/host/claude/rules/workspace.md +14 -2
  8. package/dist/host/dotfiles/prettierignore +3 -0
  9. package/dist/host/guides/README.md +65 -0
  10. package/dist/host/guides/abort.md +169 -0
  11. package/dist/host/guides/agent.md +1567 -0
  12. package/dist/host/guides/brief.md +1266 -0
  13. package/dist/host/guides/browser.md +2200 -0
  14. package/dist/host/guides/budget.md +196 -0
  15. package/dist/host/guides/codec.md +519 -0
  16. package/dist/host/guides/console.md +785 -0
  17. package/dist/host/guides/contract.md +1193 -0
  18. package/dist/host/guides/csv.md +541 -0
  19. package/dist/host/guides/database.md +2518 -0
  20. package/dist/host/guides/emitter.md +233 -0
  21. package/dist/host/guides/form.md +1791 -0
  22. package/dist/host/guides/html.md +717 -0
  23. package/dist/host/guides/indexeddb.md +505 -0
  24. package/dist/host/guides/interpret.md +1029 -0
  25. package/dist/host/guides/lsp.md +515 -0
  26. package/dist/host/guides/markdown.md +964 -0
  27. package/dist/host/guides/mcp.md +5554 -0
  28. package/dist/host/guides/middleware.md +927 -0
  29. package/dist/host/guides/msg.md +440 -0
  30. package/dist/host/guides/ndjson.md +120 -0
  31. package/dist/host/guides/ollama.md +380 -0
  32. package/dist/host/guides/pool.md +280 -0
  33. package/dist/host/guides/probe.md +1210 -0
  34. package/dist/host/guides/process.md +1620 -0
  35. package/dist/host/guides/program.md +1110 -0
  36. package/dist/host/guides/qualifier.md +854 -0
  37. package/dist/host/guides/queue.md +370 -0
  38. package/dist/host/guides/rater.md +330 -0
  39. package/dist/host/guides/reason.md +1122 -0
  40. package/dist/host/guides/relation.md +373 -0
  41. package/dist/host/guides/router.md +753 -0
  42. package/dist/host/guides/scaffold.md +192 -31
  43. package/dist/host/guides/sea.md +383 -0
  44. package/dist/host/guides/server.md +752 -0
  45. package/dist/host/guides/sqlite.md +330 -0
  46. package/dist/host/guides/sse.md +187 -0
  47. package/dist/host/guides/supervisor.md +4890 -0
  48. package/dist/host/guides/table.md +1556 -0
  49. package/dist/host/guides/template.md +280 -0
  50. package/dist/host/guides/terminal.md +1145 -0
  51. package/dist/host/guides/test.md +2969 -0
  52. package/dist/host/guides/timeout.md +252 -0
  53. package/dist/host/guides/tool.md +507 -0
  54. package/dist/host/guides/toolbox.md +1038 -0
  55. package/dist/host/guides/websocket.md +282 -0
  56. package/dist/host/guides/worker.md +615 -0
  57. package/dist/host/guides/workflow.md +1507 -0
  58. package/dist/host/guides/workspace.md +595 -0
  59. package/dist/host/manifest.json +1218 -10
  60. package/dist/host/tests/policy.test.ts +279 -2
  61. package/dist/host/tests/setupPolicy.ts +445 -6
  62. package/dist/src/core/index.cjs +38 -16
  63. package/dist/src/core/index.cjs.map +1 -1
  64. package/dist/src/core/index.d.cts +33 -9
  65. package/dist/src/core/index.d.ts +33 -9
  66. package/dist/src/core/index.js +37 -17
  67. package/dist/src/core/index.js.map +1 -1
  68. package/dist/src/server/index.cjs +1750 -1567
  69. package/dist/src/server/index.cjs.map +1 -1
  70. package/dist/src/server/index.d.cts +106 -24
  71. package/dist/src/server/index.d.ts +106 -24
  72. package/dist/src/server/index.js +1751 -1570
  73. package/dist/src/server/index.js.map +1 -1
  74. package/package.json +3 -3
@@ -0,0 +1,280 @@
1
+ # Pool
2
+
3
+ > A typed resource pool with optional bounded capacity, unique ownership, FIFO settlement,
4
+ > validated reuse, caller-owned cancellation, explicit cleanup failures, and a stable
5
+ > event-driven teardown barrier.
6
+
7
+ The pool has no warm floor, eviction timer, acquire timeout, or polling loop. Every wait parks
8
+ on a promise or a signal listener and wakes when a settlement reaches it, and the lifecycle
9
+ hooks are the caller's, so the engine itself performs no I/O.
10
+
11
+ ## Surface
12
+
13
+ `createPool` constructs the interface-oriented form; `Pool` exposes the same contract as a
14
+ class. Each created value receives an opaque ownership record, so duplicate primitives,
15
+ `undefined`, `NaN`, and repeated references are independent resources.
16
+
17
+ ### Create a pool
18
+
19
+ Construct a pool from create, destroy, and validate hooks, then acquire and release one token:
20
+
21
+ ```ts
22
+ import { createPool } from '@orkestrel/pool'
23
+
24
+ const pool = createPool<Connection>({
25
+ create: () => connect(),
26
+ destroy: (connection) => connection.close(),
27
+ validate: (connection) => connection.alive,
28
+ max: 8,
29
+ })
30
+
31
+ const token = await pool.acquire()
32
+ try {
33
+ await token.value.query('select 1')
34
+ } finally {
35
+ token.release()
36
+ }
37
+ ```
38
+
39
+ ### Factories
40
+
41
+ | API | Kind | Summary |
42
+ | ------------ | -------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
43
+ | `createPool` | function | Creates a distinct `PoolInterface` from resource lifecycle hooks, with optional bounded capacity, unique ownership, and FIFO settlement. |
44
+
45
+ ### Classes
46
+
47
+ | API | Kind | Summary |
48
+ | ----------- | ----- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
49
+ | `Pool` | class | Represents a capacity-aware resource pool whose opaque ownership records preserve FIFO settlement, cancellation, exact lease release, and deterministic teardown under concurrent hooks. |
50
+ | `PoolError` | class | Represents a stable, machine-readable pool failure that retains the original thrown value as its cause without unsafe coercion, alongside structured context. |
51
+
52
+ ### Guards
53
+
54
+ In a guard table a `Shape` cell holds the type the guard narrows to.
55
+
56
+ | API | Kind | Shape | Summary |
57
+ | -------------- | -------- | ------------- | ---------------------------------------------------------------------------------------------------------------- |
58
+ | `isPoolError` | function | `PoolError` | Tests whether an unknown value is a `PoolError`, returning `false` for hostile proxies. |
59
+ | `isPoolMax` | function | `number` | Tests whether a value is a positive safe integer, the only valid explicit pool maximum. |
60
+ | `isPoolSignal` | function | `AbortSignal` | Tests whether a value is a native `AbortSignal` for the acquire boundary, returning `false` for hostile proxies. |
61
+
62
+ ### Types
63
+
64
+ A `Shape` cell holds an interface's data members as bare names in braces, `?` marking an optional member and `plus` introducing its call-signature members, and a type alias's own type literal with a union's arms escaped as `\|`.
65
+
66
+ | API | Kind | Shape | Summary |
67
+ | ------------------ | --------- | -------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- |
68
+ | `PoolCode` | type | `'invalid' \| 'destroyed' \| 'create' \| 'cleanup'` | Names the machine-readable failure codes produced by `PoolError`. |
69
+ | `PoolContext` | interface | `{ value?, failures? }` | Represents the structured context attached to a `PoolError`: the rejected input, or the distinct destroy-hook failures an aggregate cleanup collected. |
70
+ | `PoolErrorOptions` | interface | `{ code, cause?, context? }` | Represents the construction options for `PoolError`: the stable code, an optional cause, and optional structured context. |
71
+ | `PoolEventMap` | type | `{ create, acquire, release, destroy }` | Represents the observable resource lifecycle events emitted by a `PoolInterface`. |
72
+ | `PoolToken` | interface | `{ value } plus release` | Represents a unique lease over one pool-owned resource record, exposing that record as a readonly `value` and returning it through an idempotent `release`. |
73
+ | `PoolOptions` | interface | `{ on?, error?, create, destroy?, validate?, max? }` | Represents the resource lifecycle options for `Pool` and `createPool`: creation, destruction, validation, capacity, and observation. |
74
+ | `PoolInterface` | interface | `{ emitter, size, idle, active } plus acquire, clear, destroy` | Represents a FIFO resource pool with optional bounded capacity and deterministic teardown, exposing its record counts and a typed lifecycle emitter. |
75
+
76
+ `size` counts every owned record, including records being validated or destroyed. `idle`
77
+ counts only immediately available records. `active` counts only leased records. An in-flight
78
+ create reservation claims capacity but is not yet an owned record and therefore is not part
79
+ of `size`.
80
+
81
+ ## Methods
82
+
83
+ The public call-signature members of `PoolInterface` and `PoolToken`; `Pool` implements the
84
+ `PoolInterface` list exactly.
85
+
86
+ #### `PoolInterface`
87
+
88
+ | Method | Returns | Summary |
89
+ | --------- | ----------------------- | ------------------------------------------------------------------------------------------------------------------------- |
90
+ | `acquire` | `Promise<PoolToken<T>>` | Queues the caller in FIFO order, validates an idle record or creates one, and settles queued acquires in that same order. |
91
+ | `clear` | `Promise<void>` | Destroys the records that are idle at this call's synchronous snapshot. |
92
+ | `destroy` | `Promise<void>` | Tears down the pool permanently and returns its stable completion barrier. |
93
+
94
+ #### `PoolToken`
95
+
96
+ The lease returned by `acquire`, with the operation that returns its record.
97
+
98
+ | Method | Returns | Summary |
99
+ | --------- | ------- | ------------------------------------------------------------------------------------------------------------------- |
100
+ | `release` | `void` | Gives this exact record back to the pool once; a repeat call, and a call after teardown took ownership, are no-ops. |
101
+
102
+ ## Contract
103
+
104
+ ### Capacity and FIFO
105
+
106
+ Every `acquire` receives its queue position before a create or validation hook starts. The
107
+ reentrancy-safe pump may assign several hook operations concurrently, but a head commit
108
+ barrier settles successes and failures in request order. A later fast create or validation
109
+ cannot overtake an earlier slow one. Capacity obeys:
110
+
111
+ ```text
112
+ owned records + create reservations <= max
113
+ ```
114
+
115
+ `max` must be a positive safe integer. Omit it for an unbounded pool; `Infinity`, fractions,
116
+ zero, negative values, and unsafe integers are invalid. Construction snapshots `max` once and
117
+ validates it before retention, then snapshots `on` and `error` once each.
118
+
119
+ Record phases are disjoint:
120
+
121
+ ```text
122
+ create reservation -> ready -> leased -> available -> validating -> ready
123
+ \-> destroying -> removed
124
+ ```
125
+
126
+ Invalid validation, whether `false` or a thrown value, claims and cleans the record before a
127
+ replacement capacity slot becomes available. Cleanup failure rejects that acquire with
128
+ `PoolError` code `cleanup`; successful cleanup lets the same FIFO waiter seek a replacement.
129
+ The bound outcome and replacement eligibility are established before synchronous `destroy`
130
+ observers can reenter acquisition. A create failure rejects its bound acquire with code
131
+ `create` and never strands later waiters.
132
+
133
+ ### Cancellation
134
+
135
+ `acquire` validates a native `AbortSignal` before queueing. An invalid signal throws a
136
+ code-`invalid` `PoolError` synchronously instead of returning a rejected promise. A
137
+ pre-aborted signal and every later abort preserve the caller's exact `signal.reason`. The
138
+ listener is attached, recorded, and followed by an aborted-state recheck, then detached on
139
+ every settlement. Aborting while create or validation work is assigned removes the waiter
140
+ exactly once; any late resource is returned to the live pump or cleaned during teardown. A
141
+ ready result waiting behind a slower head can likewise be aborted without leaking its record.
142
+ If cancelled validation later proves the record invalid and its cleanup fails, the acquire
143
+ still preserves the caller's abort reason while the cleanup failure is retained for the
144
+ eventual `destroy()` barrier.
145
+
146
+ ### Release and cleanup
147
+
148
+ A token captures its exact opaque record, so `release()` is correct even when multiple
149
+ records contain the same value. Release is idempotent and removes the lease synchronously.
150
+ With a waiter, the record is validated before handoff. Without an assignable waiter, it
151
+ becomes idle and emits `release`. Release after teardown ownership transferred is a no-op.
152
+
153
+ `clear()` synchronously snapshots idle records and installs one cleanup promise per record
154
+ before invoking the hook. Concurrent clears therefore own disjoint snapshots, and a lease
155
+ released after a snapshot is taken is not part of it. Every claimed record stays in `size` until its
156
+ hook attempt completes. Distinct failures are aggregated in a code-`cleanup` `PoolError`
157
+ whose `context.failures` retains the original thrown values.
158
+ Each claimed record's cleanup settlement independently wakes queued acquires after the
159
+ destroy ledger transition, whether its cleanup hook succeeded or failed; a failed `clear()`
160
+ still rejects its own aggregate cleanup barrier.
161
+
162
+ ### Destruction
163
+
164
+ `destroy()` is deliberately non-`async`: it installs and returns its exact promise before it
165
+ rejects waiters, emits events, or invokes cleanup. Reentrant and repeated calls return that
166
+ same object. Teardown invalidates idle, leased, and ready records, waits for create,
167
+ validation, existing clear cleanup, and new cleanup activity, and disposes every late
168
+ resource. Unresolved hooks keep the barrier pending without polling.
169
+
170
+ Cleanup already owned by an overlapping `clear()` is shared; its failure is reported to both
171
+ the clear call and the destroy aggregate. Create failures that produced no resource do not
172
+ fail destruction. The emitter is destroyed last, after every resource `destroy` event and
173
+ hook attempt, then the stable barrier resolves or rejects.
174
+
175
+ ### Errors
176
+
177
+ `PoolError.code` is stable and lowercase:
178
+
179
+ | Code | Owner |
180
+ | ----------- | ------------------------------------------------------------------------ |
181
+ | `invalid` | Invalid explicit `max`, invalid acquire signal, or an internal boundary. |
182
+ | `destroyed` | Acquire or clear attempted after terminal teardown began. |
183
+ | `create` | The create hook failed for its bound acquire. |
184
+ | `cleanup` | Invalid-handoff, clear, or destroy cleanup failed. |
185
+
186
+ The original thrown value is retained as `cause`; aggregate cleanup values are also in
187
+ `context.failures`. Message construction and `isPoolError` avoid unsafe string coercion and
188
+ return safely for hostile proxies.
189
+
190
+ ## Observing
191
+
192
+ The composed `Emitter` isolates listener throws through the optional `error` handler and
193
+ invokes listeners synchronously at each emission point. The `destroy` emission is deliberately
194
+ one microtask after cleanup settlement so bound outcomes precede observer reentry. Events
195
+ follow their ledger transitions:
196
+
197
+ | Event | Emission point |
198
+ | --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
199
+ | `create` | After a fresh resource is inserted into the ownership ledger. |
200
+ | `acquire` | After the waiter promise receives its token and the record is leased. |
201
+ | `release` | Only when the released or orphaned-ready record remains idle. |
202
+ | `destroy` | After the hook attempt and resource-ledger removal, one microtask after private cleanup settlement, while destroying ownership remains installed through the event. |
203
+
204
+ Because listeners may synchronously reenter or destroy the pool, the engine checks terminal
205
+ and waiter state after every awaited hook and every emit.
206
+
207
+ ```ts
208
+ import { createPool } from '@orkestrel/pool'
209
+
210
+ const pool = createPool({
211
+ create: () => connect(),
212
+ on: {
213
+ create: () => metrics.increment('pool.create'),
214
+ destroy: () => metrics.increment('pool.destroy'),
215
+ },
216
+ error: (error, event) => report(error, event),
217
+ })
218
+ ```
219
+
220
+ ## Patterns
221
+
222
+ ### Validate public boundaries
223
+
224
+ Check a candidate value or error against the public boundary guards before acting on it:
225
+
226
+ ```ts
227
+ import { PoolError, isPoolError, isPoolMax, isPoolSignal } from '@orkestrel/pool'
228
+
229
+ isPoolMax(4) // true
230
+ isPoolMax(Infinity) // false: omit max for unbounded capacity
231
+ isPoolSignal(new AbortController().signal) // true
232
+
233
+ const failure = new PoolError({ code: 'destroyed' })
234
+ if (isPoolError(failure)) console.error(failure.code)
235
+ ```
236
+
237
+ ### Always release and explicitly tear down
238
+
239
+ Release every acquired token and call `destroy()` explicitly after work finishes:
240
+
241
+ ```ts
242
+ import { Pool } from '@orkestrel/pool'
243
+
244
+ const pool = new Pool({ create: () => connect(), max: 4 })
245
+ const controller = new AbortController()
246
+ const token = await pool.acquire(controller.signal)
247
+ try {
248
+ await use(token.value)
249
+ } finally {
250
+ token.release()
251
+ }
252
+ await pool.clear()
253
+ await pool.destroy()
254
+ ```
255
+
256
+ ## Tests
257
+
258
+ - [`tests/src/core/Pool.test.ts`](../tests/src/core/Pool.test.ts) — canonical behavior:
259
+ validation, hostile errors, duplicate ownership, transitional counts, overlapping FIFO
260
+ hooks, create continuation, abort boundaries, abort-listener detachment, exclusive
261
+ invalid-cleanup waiter ownership, bounded and unbounded replacement, destroy-observer
262
+ reentry ordering, concurrent clear, stable reentrant destruction, late resources,
263
+ aggregate failures, emitter ordering, and high contention.
264
+ - [`tests/src/core/validators.test.ts`](../tests/src/core/validators.test.ts) — the public
265
+ boundary guards alone: accepted and rejected maxima, and native versus hostile signals.
266
+ - [`tests/src/core/factories.test.ts`](../tests/src/core/factories.test.ts) — factory
267
+ construction and instance identity only.
268
+ - [`tests/guides.test.ts`](../tests/guides.test.ts) — the `## Surface` ↔ `src/core` bijection
269
+ over value and type exports, the `PoolInterface` ↔ `Pool` and `PoolToken` method bijections,
270
+ fence-import and relative-link resolution, and the equality gate: every `Summary` cell against
271
+ its declaration's description paragraph, the titled `Create a pool` fence against the
272
+ `@example` block of that title (pinned so the titled pair cannot be retired silently), and the
273
+ README pitch against this guide's tagline. It also runs the boundary-guard fence and asserts
274
+ the values its comments claim.
275
+
276
+ ## See also
277
+
278
+ - [`emitter.md`](emitter.md) — the installed observation primitive.
279
+ - [`AGENTS.md`](../AGENTS.md) — repository coding and lifecycle rules.
280
+ - [`README.md`](README.md) — guide manifest.