@orkestrel/scaffold 0.0.92 → 0.0.93

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.
@@ -361,7 +361,7 @@ These invariants hold across `src/core` / `src/browser` / `src/server` ↔
361
361
  stated earlier.
362
362
  22. **Streaming both ways.** `buildRequest` streams a body-carrying method's
363
363
  message into the `Request` through a manual `ReadableStream` pump — a `for
364
- await` loop over the `IncomingMessage` enqueueing each chunk, with
364
+ await` loop over the `IncomingMessage` enqueueing each chunk, with
365
365
  `duplex: 'half'` set as Node's fetch implementation requires for a
366
366
  streamed request body; `sendResponse` streams a non-`null` `Response`
367
367
  body back to the `ServerResponse` chunk by chunk, ending the target when
@@ -164,10 +164,14 @@ These invariants hold across `src/core` ↔ `worker.md`:
164
164
  `null` reaches Queue or Pool validation. Queue's integer timeout contract is preserved:
165
165
  `timeout` must be in `0..2_147_483_647` milliseconds, and `0` disables the deadline.
166
166
  Queue is constructed successfully before the
167
- pool option is read, and every declared pool member (`max`, `on`, `error`, `create`,
168
- `destroy`, `validate`) is then captured once by direct access, preserving inherited and
169
- non-enumerable structural options. Pool `max` still defaults to concurrency, so resources
170
- match the jobs in flight by default. `stop` / `abort` / `clear` return the
167
+ pool option is read, and every declared pool member (`max`, `min`, `restarts`, `watch`,
168
+ `on`, `error`, `create`, `destroy`, `validate`) is then captured once by direct access,
169
+ preserving inherited and non-enumerable structural options. Pool validates the forwarded
170
+ members. Pool `max` defaults to concurrency only when both `max` and `min` are absent.
171
+ With `min`, Pool defaults `max` to `min` and refuses unequal explicit values or a missing
172
+ `restarts` bound. The worker starts the pool at construction, so a floor warms before
173
+ work arrives and can exceed queue concurrency. A spent floor's startup rejection is
174
+ observed internally; acquire reports the pool failure to jobs. `stop` / `abort` / `clear` return the
171
175
  queue's exact cleanup barriers. `destroy` installs one stable barrier before it invokes
172
176
  queue teardown (including synchronous abort-event reentry), awaits queue then pool
173
177
  settlement serially, aggregates the queue's failure and the pool's in that order, and
@@ -195,7 +199,7 @@ These invariants hold across `src/core` ↔ `worker.md`:
195
199
  `TResult` infer from the `input` and `result` guards, so a call site needs no type
196
200
  argument. The structured-clone boundary is crossed with no `as`: a `Dispatch` narrows each reply
197
201
  value through `options.result` (a value that fails it rejects with `'reply did not
198
- satisfy result guard'`), and the worker side narrows each payload through
202
+ satisfy result guard'`), and the worker side narrows each payload through
199
203
  `options.input` (a bad input replies `'input did not satisfy input guard'`) —
200
204
  `TInput` / `TResult` are reconstructed by validation, never asserted. A throwing
201
205
  caller guard is contained and rejects only that job; the pooled worker remains usable.
@@ -383,6 +387,33 @@ See [queue.md](queue.md) / [pool.md](pool.md) for the underlying
383
387
  listener's throw never prevents a sibling listener, and the throw reaches the emitter's
384
388
  `error` handler, so a buggy worker observer leaves the inner queue and pool intact.
385
389
 
390
+ ## Pool options
391
+
392
+ The `pool` option takes Pool's resource options and refuses the `capacity` option, so each
393
+ resource serves one job at a time. Pool owns validation of the forwarded options:
394
+
395
+ | Member | Behavior |
396
+ | ---------- | ---------------------------------------------------------------------------------------------------- |
397
+ | `create` | Creates a resource on demand or while filling a configured floor. |
398
+ | `destroy` | Disposes each resource during pool cleanup or loss. |
399
+ | `validate` | Checks an idle resource before reuse. |
400
+ | `max` | Caps pool capacity; defaults to `concurrency` only when `min` is absent. |
401
+ | `min` | Sets a positive safe integer warm floor; Pool defaults `max` to it and requires equality. |
402
+ | `restarts` | Sets the required non-negative safe integer refill bound with `min`; invalid without `min`. |
403
+ | `watch` | Observes each created resource; settlement declares loss while live, and disposal aborts its signal. |
404
+ | `on` | Installs initial pool lifecycle listeners. |
405
+ | `error` | Receives pool listener failures and live watch rejections or throws. |
406
+
407
+ Pool `start()` fills the floor when the worker is constructed. Without `min`, resources remain
408
+ lazy. A `restarts: 1` bound permits another create after the first failure and spends the
409
+ floor after the second failure. Jobs then receive Pool's `create` error with the last cause.
410
+ A resource lost while idle adds a strike even if it served a job before its last release.
411
+ With `min: 1` and `restarts: 0`, that loss spends the floor, and the next job rejects with
412
+ Pool's `create` error without creating a replacement.
413
+ Worker `start()` restarts queue loops only; it does not reset a spent pool's restart bound.
414
+ See [Pool](pool.md), under “Warm floor and loss”, for refill, retained
415
+ cleanup failures, and watch listener cleanup.
416
+
386
417
  ## Patterns
387
418
 
388
419
  ### A resource-backed worker
@@ -479,8 +510,9 @@ Follow these practices when you run a worker in production:
479
510
  - **Honour `context.signal`** — pass it through to the resource's operation and bail
480
511
  out when it fires, so timeouts and aborts actually stop work rather than abandoning
481
512
  its result.
482
- - **Size the pool through `concurrency`** — the pool's `max` defaults to it; override
483
- `pool.max` explicitly only when the resource cap must diverge from the job cap.
513
+ - **Size the pool through `concurrency`** — when neither `pool.max` nor `pool.min` is given,
514
+ the pool's `max` defaults to it. Set `pool.max` for a separate lazy resource cap, or
515
+ `pool.min` with `pool.restarts` for a warm floor independent of queue concurrency.
484
516
  Concurrency must be a positive safe integer; invalid values are rejected by Queue and
485
517
  are never normalized.
486
518
  - **`abort` is terminal** — a worker-level abort cancels in-flight work and stops the
@@ -524,6 +556,10 @@ These tests pin the behaviour this guide documents:
524
556
  returns the queue's cleanup barriers; constructor options and every declared pool option are
525
557
  captured once (including inherited / non-enumerable structural options), only explicit
526
558
  `undefined` defaults, runtime `null` reaches the Queue/Pool diagnostic,
559
+ the pool option type excludes `capacity`, `min` warms before work with Pool's `max` default,
560
+ `restarts` bounds failed creates and loss of a previously used idle resource,
561
+ `watch` receives each resource and an abort signal before disposal, conflicting `min`
562
+ and `max` values refuse at construction with Pool's error,
527
563
  and invalid Queue concurrency wins before the pool option is read; strict concurrency
528
564
  rejects zero, negative, fractional, `NaN`, and infinite values instead of normalizing
529
565
  them; `destroy` keeps one
@@ -34,7 +34,7 @@
34
34
  "storage": "agents/skills/enterprise-bootstrap/references/bootstrap-reference.md",
35
35
  "destination": ".agents/skills/enterprise-bootstrap/references/bootstrap-reference.md",
36
36
  "executable": false,
37
- "digest": "08336f02280eef5c7266052bc3cbe4d85c4268eb82dbb198b680940dd62d83ed"
37
+ "digest": "5fe9a1fc675fa566e44816cedf0a8421f387a5276409000ea20c98c876e3ac80"
38
38
  },
39
39
  {
40
40
  "storage": "agents/skills/enterprise-bootstrap/references/color-modes.md",
@@ -70,13 +70,13 @@
70
70
  "storage": "agents/skills/enterprise-bootstrap/references/responsive-layout.md",
71
71
  "destination": ".agents/skills/enterprise-bootstrap/references/responsive-layout.md",
72
72
  "executable": false,
73
- "digest": "44e709e8df187495e6343048891ca9ff1ff9d3f30d86e00ad8cbd97c8e29bf20"
73
+ "digest": "f401dd3aa97b1098a6d97c8862bc7be7713a8a98ae1546a918abb66ee25cd8ad"
74
74
  },
75
75
  {
76
76
  "storage": "agents/skills/enterprise-bootstrap/references/utilities.md",
77
77
  "destination": ".agents/skills/enterprise-bootstrap/references/utilities.md",
78
78
  "executable": false,
79
- "digest": "8cec05a193672bc543439a3aa46cf7b4ffc5573527b3fe047ad575fbe73f4a2c"
79
+ "digest": "84a7c3eec5d280ba67b103418a69b4643434b9fa9fe39ee8c1b305f1ba4f94c0"
80
80
  },
81
81
  {
82
82
  "storage": "agents/skills/orkestrel-align/SKILL.md",
@@ -322,7 +322,7 @@
322
322
  "storage": "agents/skills/orkestrel-journey/references/statechart.md",
323
323
  "destination": ".agents/skills/orkestrel-journey/references/statechart.md",
324
324
  "executable": false,
325
- "digest": "89e53c15a8f02dfa335611b45c39d05cc3509e390156d6e569582227f0487802"
325
+ "digest": "b5866b5a756e2b42feb24e7ea2bdcb7c2c0ecc8d9863488263aeddffb63a44da"
326
326
  },
327
327
  {
328
328
  "storage": "agents/skills/orkestrel-journey/references/styles.md",
@@ -496,7 +496,7 @@
496
496
  "storage": "claude/agents/orkestrel.md",
497
497
  "destination": ".claude/agents/orkestrel.md",
498
498
  "executable": false,
499
- "digest": "36afc2242e9becbb7662aeece1b0f81a12162aacfd360a48a07a3ec7eaf7d639"
499
+ "digest": "7c081ea4deffe54305f4a43685adbde2a5941d4f69c3ed386690ab409372a638"
500
500
  },
501
501
  {
502
502
  "storage": "claude/agents/planner.md",
@@ -580,7 +580,7 @@
580
580
  "storage": "claude/rules/styles.md",
581
581
  "destination": ".claude/rules/styles.md",
582
582
  "executable": false,
583
- "digest": "ae1c97f23d71c53ef117b2cd661df6258712988ec86de6c60a1cbad4670eb996"
583
+ "digest": "156572b7c26740411e64726255f76e0f6e6e4e55e800a26262a923210866eb77"
584
584
  },
585
585
  {
586
586
  "storage": "claude/rules/tests.md",
@@ -826,7 +826,7 @@
826
826
  "storage": "dotfiles/oxlintrc.json",
827
827
  "destination": ".oxlintrc.json",
828
828
  "executable": false,
829
- "digest": "043a5c3eb0fb52d6cd841590e77c94ce03797b4b6a742fd57127bc9b9242153c"
829
+ "digest": "c3777d98a2c48a4007397ef90912b2530d7e40bc4d2f85155830e6d1135dc241"
830
830
  },
831
831
  {
832
832
  "storage": "dotfiles/prettierignore",
@@ -862,7 +862,7 @@
862
862
  "storage": "guides/browser.md",
863
863
  "destination": "guides/browser.md",
864
864
  "executable": false,
865
- "digest": "deec731bfc8733f880021cbf9a8cf450e51a93bc23f2f963fb3e1bf750554ba8"
865
+ "digest": "dfeb5feef6751bac487cf0205736a6763995b259ef1ee9bee8a606bb12f50e33"
866
866
  },
867
867
  {
868
868
  "storage": "guides/budget.md",
@@ -952,7 +952,7 @@
952
952
  "storage": "guides/mcp.md",
953
953
  "destination": "guides/mcp.md",
954
954
  "executable": false,
955
- "digest": "8cc580a9819d11771b585e8a915fcc6b7bd3ff4a575b6c6482cd76c501367664"
955
+ "digest": "d7363cdbde8cde24503915b0fdc78e30543e3b81e68e105500dfda3ffee7702e"
956
956
  },
957
957
  {
958
958
  "storage": "guides/middleware.md",
@@ -982,13 +982,13 @@
982
982
  "storage": "guides/pool.md",
983
983
  "destination": "guides/pool.md",
984
984
  "executable": false,
985
- "digest": "c49d3d2d3d5a2dc4518a8cebb94c82ba2dbcdc03222d5ad3885df13c46dfe8e2"
985
+ "digest": "a8bbdd91006afeb577d9e43a3f04ffe37cae989db954058b2e67197a3ca62572"
986
986
  },
987
987
  {
988
988
  "storage": "guides/probe.md",
989
989
  "destination": "guides/probe.md",
990
990
  "executable": false,
991
- "digest": "8082bfb642ba16d64e06aba0e1c5d0774ecebd77443d500821e4482bb0916cbe"
991
+ "digest": "11ddbf59ab6dd29e24f25ad1076dd6976b6e3bcdda1d95cb5186871b082ce560"
992
992
  },
993
993
  {
994
994
  "storage": "guides/process.md",
@@ -1036,7 +1036,7 @@
1036
1036
  "storage": "guides/router.md",
1037
1037
  "destination": "guides/router.md",
1038
1038
  "executable": false,
1039
- "digest": "73c88d2692d756c7f902424e75ba45c09c64c3ba78bdad5e800c6abe18551f26"
1039
+ "digest": "890c46d9749875a48f5ec1981e9a8da90c93ad961b2ed092549172d83546f4e9"
1040
1040
  },
1041
1041
  {
1042
1042
  "storage": "guides/scaffold.md",
@@ -1126,7 +1126,7 @@
1126
1126
  "storage": "guides/worker.md",
1127
1127
  "destination": "guides/worker.md",
1128
1128
  "executable": false,
1129
- "digest": "b72964712b7187a987e4ba08bec95d72487c4afeb6e4c43c631d14b4c3cbff63"
1129
+ "digest": "441c0c0a3a5b425fb91034d953e2e6a1d05d3dcb29702c600a43e048bac24afd"
1130
1130
  },
1131
1131
  {
1132
1132
  "storage": "guides/workflow.md",
@@ -1168,7 +1168,7 @@
1168
1168
  "storage": "tests/config.test.ts",
1169
1169
  "destination": "tests/config.test.ts",
1170
1170
  "executable": false,
1171
- "digest": "ac12462cfc786b77c23e8996c0a050f9719d870db08abe7f3a8994cbbf778e2d"
1171
+ "digest": "6d5079e1eed5b45c74ef788c966527e336444f32dc15afde19b7ae360e046854"
1172
1172
  },
1173
1173
  {
1174
1174
  "storage": "tests/policy.test.ts",
@@ -2144,5 +2144,5 @@
2144
2144
  ]
2145
2145
  }
2146
2146
  ],
2147
- "digest": "09b047e9598599db3dca2e26b55b897293e600defd7c35147dbab8a771816c0b"
2147
+ "digest": "561d787211d1f705e038c6ae37fb2ceaf3d9aa147444ec06d90a129ca9c46966"
2148
2148
  }
@@ -2595,7 +2595,7 @@ createSomething({
2595
2595
  const pattern = readConfigRecord(patternValue)
2596
2596
  const message = pattern.message
2597
2597
  if (typeof message !== 'string') throw new Error('Missing pattern message')
2598
- const sources: ReadonlyArray<readonly [string, boolean]> = message.includes('URL schemes')
2598
+ let sources: ReadonlyArray<readonly [string, boolean]> = message.includes('URL schemes')
2599
2599
  ? [
2600
2600
  ['https://host/x', true],
2601
2601
  ['data:text/plain,x', true],
@@ -2661,6 +2661,24 @@ createSomething({
2661
2661
  true,
2662
2662
  ],
2663
2663
  ]
2664
+ if (message.includes('another styles face')) {
2665
+ const face =
2666
+ typeof pattern.regex === 'string'
2667
+ ? /@src\/(bootstrap|tailwindcss|styles)\(/u.exec(pattern.regex)?.[1]
2668
+ : undefined
2669
+ if (face === undefined) throw new Error('Missing styles face in restriction pattern')
2670
+ sources = [
2671
+ [`@src/${face}`, true],
2672
+ [`@src/${face}?raw`, true],
2673
+ [`@orkestrel/x/${face}`, true],
2674
+ [`../${face}/index.js`, true],
2675
+ [`../src/${face}/index.js`, true],
2676
+ [`../../src/${face}/index.js`, true],
2677
+ ['@src/browser', false],
2678
+ [`@src/${face}x`, false],
2679
+ [`../${face}.ext/index.js`, false],
2680
+ ]
2681
+ }
2664
2682
  const owner =
2665
2683
  Array.isArray(block.files) && typeof block.files[0] === 'string'
2666
2684
  ? block.files[0].split('/**')[0]
@@ -2730,6 +2748,9 @@ createSomething({
2730
2748
  'src/vue',
2731
2749
  'app/vue',
2732
2750
  'src/browser',
2751
+ 'src/bootstrap',
2752
+ 'src/tailwindcss',
2753
+ 'src/styles',
2733
2754
  'app/browser',
2734
2755
  'src/core',
2735
2756
  'app/core',
@@ -2737,7 +2758,7 @@ createSomething({
2737
2758
  'app/server',
2738
2759
  'src/bin',
2739
2760
  ]) {
2740
- const refused = owner.endsWith('/vue')
2761
+ const refused: Array<string | readonly [string, string]> = owner.endsWith('/vue')
2741
2762
  ? [
2742
2763
  'node:fs',
2743
2764
  '@src/server',
@@ -2773,6 +2794,24 @@ createSomething({
2773
2794
  : []),
2774
2795
  ]
2775
2796
  : ['@src/core']
2797
+ if (owner === 'src/core') refused.push('@src/browser', './index.css')
2798
+ if (['src/bootstrap', 'src/tailwindcss', 'src/styles'].includes(owner)) {
2799
+ refused.push('node:fs', '@src/server', '../server/index.js', '@app/core')
2800
+ for (const face of ['bootstrap', 'tailwindcss', 'styles']) {
2801
+ if (owner === `src/${face}`) continue
2802
+ refused.push(
2803
+ `@src/${face}`,
2804
+ `@orkestrel/x/${face}`,
2805
+ `../${face}/index.js`,
2806
+ `../src/${face}/index.js`,
2807
+ `../../src/${face}/index.js`,
2808
+ ['export * from', `@src/${face}`],
2809
+ ['import type * as boundary from', `@src/${face}`],
2810
+ )
2811
+ admitted.push(`@src/${face}x`, `../${face}.ext/index.js`)
2812
+ }
2813
+ admitted.push('@src/browser', './sheet.js', '@orkestrel/contract')
2814
+ }
2776
2815
  for (const [sources, refusal] of [
2777
2816
  [
2778
2817
  [
@@ -2799,7 +2838,11 @@ createSomething({
2799
2838
  mkdirSync(dirname(resolve(scratch, file)), { recursive: true })
2800
2839
  writeFileSync(
2801
2840
  resolve(scratch, file),
2802
- 'import * as boundary from ' + JSON.stringify(source) + '\nvoid boundary\ndebugger\n',
2841
+ typeof source === 'string'
2842
+ ? 'import * as boundary from ' +
2843
+ JSON.stringify(source) +
2844
+ '\nvoid boundary\ndebugger\n'
2845
+ : source[0] + ' ' + JSON.stringify(source[1]) + '\ndebugger\n',
2803
2846
  )
2804
2847
  expected.set(file, refusal)
2805
2848
  }
@@ -4,7 +4,7 @@ let _orkestrel_template = require("@orkestrel/template");
4
4
  let _orkestrel_emitter = require("@orkestrel/emitter");
5
5
  var package_default = {
6
6
  name: "@orkestrel/scaffold",
7
- version: "0.0.92",
7
+ version: "0.0.93",
8
8
  description: "Scaffold workspaces with commands: new, audit, repair, catalog, and overwrite.",
9
9
  keywords: [
10
10
  "audit",
@@ -103,16 +103,16 @@ var package_default = {
103
103
  "@orkestrel/template": "^0.0.9"
104
104
  },
105
105
  devDependencies: {
106
- "@microsoft/api-extractor": "^7.59.3",
107
- "@orkestrel/browser": "^0.0.24",
106
+ "@microsoft/api-extractor": "^7.59.4",
107
+ "@orkestrel/browser": "^0.0.26",
108
108
  "@orkestrel/guide": "^0.0.24",
109
109
  "@orkestrel/html": "^0.0.12",
110
- "@orkestrel/probe": "^0.0.20",
110
+ "@orkestrel/probe": "^0.0.21",
111
111
  "@orkestrel/test": "^0.0.24",
112
112
  "@types/node": "^26.6.4",
113
113
  "@vitest/browser-playwright": "^4.1.11",
114
- "oxfmt": "^0.71.0",
115
- "oxlint": "^1.86.0",
114
+ "oxfmt": "^0.72.0",
115
+ "oxlint": "^1.87.0",
116
116
  "playwright": "^1.63.0",
117
117
  "typescript": "^6.0.3",
118
118
  "vite": "^8.3.2",