@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
+ # Template
2
+
3
+ > A named, versionable template layer: `{{name}}` tokens in a `content`
4
+ > string, resolved against a values record by a single-pass fill engine, and
5
+ > registered and looked up by id through a self-owning `TemplateManager`.
6
+
7
+ `validate` predicts `fill`'s `'error'`-policy outcome exactly — a token it
8
+ reports `missing` is precisely a token that would throw. Every fill lookup is
9
+ prototype-pollution-safe: any field-path segment in `UNSAFE_FIELD_SEGMENTS`
10
+ (`__proto__`, `constructor`, `prototype`) is refused before `resolveField` is
11
+ ever called. Source: [`src/core`](../src/core). Surfaced through the
12
+ `@src/core` barrel.
13
+
14
+ ## Surface
15
+
16
+ Create a template, fill it against a values record, then register it in a
17
+ manager for id-keyed lookup:
18
+
19
+ ```ts
20
+ import { createTemplate, createTemplateManager } from '@orkestrel/template'
21
+
22
+ const greeting = createTemplate({ name: 'greeting', content: 'Hi {{name}}' })
23
+ greeting.fill({ name: 'Ada' }) // 'Hi Ada'
24
+
25
+ const templates = createTemplateManager({ templates: [greeting] })
26
+ templates.fill(greeting.id, { name: 'Grace' }) // 'Hi Grace'
27
+ ```
28
+
29
+ An unresolved required placeholder is governed by `TemplateFillOptions.missing`
30
+ (default `'error'`, throwing a `TemplateError` coded `MISSING`); `'empty'`
31
+ substitutes `''`, `'literal'` re-emits the original `{{name}}` token. An
32
+ escaped `\{{` always emits a literal `{{`, regardless of policy.
33
+
34
+ ### Types
35
+
36
+ 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 `\|`. An extended interface's name comes before `plus`, with the members it adds after.
37
+
38
+ | Type | Kind | Shape | Summary |
39
+ | -------------------------- | --------- | --------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
40
+ | `MissingPolicy` | type | `'error' \| 'empty' \| 'literal'` | Names how `TemplateInterface#fill` handles an unresolved required placeholder. |
41
+ | `TemplateFillValues` | type | `Readonly<Record<string, unknown>>` | Represents the values a `TemplateInterface#fill` / `#validate` call resolves placeholders against. |
42
+ | `TemplateManagerEventMap` | type | `{ register, remove, clear }` | Declares the push observation surface of a `TemplateManagerInterface` — an id-keyed registry, so `register` / `remove` are the events (never ordered-list `append`/`prepend`). |
43
+ | `TemplateErrorCode` | type | `'MISSING' \| 'NOTFOUND' \| 'INVALID' \| 'CONFLICT'` | Names the coded misuse / failure conditions thrown as a `TemplateError`. |
44
+ | `TemplatePlaceholder` | interface | `{ name, path?, required?, fallback?, description? }` | Represents one placeholder a `TemplateDefinition`'s `content` declares — its lookup name, an optional field path into the values record, whether it is required, and a literal fallback. |
45
+ | `TemplateDefinition` | interface | `{ id, name, content, placeholders, summary?, description?, category?, tags? }` | Represents a named, versionable template record — pure data, no behavior. |
46
+ | `TemplateFillOptions` | interface | `{ missing?, locale? }` | Carries the per-call options for `TemplateInterface#fill` / `TemplateManagerInterface#fill`. |
47
+ | `TemplateFillContext` | interface | `TemplateFillOptions plus { placeholders? }` | Carries the full option bag `fillTemplate` takes — the per-call `TemplateFillOptions` plus the declared placeholders tokens resolve against. |
48
+ | `TemplateTokenResolution` | interface | `{ value, declared, required }` | Represents one `{{name}}` token's resolution — the single token rule `fillTemplate` and `TemplateInterface#validate` share. |
49
+ | `TemplateRegisterOptions` | interface | `{ replace? }` | Carries the options for `TemplateManagerInterface#register`. |
50
+ | `TemplateValidationResult` | interface | `{ valid, missing, extra }` | Reports the outcome of `TemplateInterface#validate` — which required placeholders are unresolved, and which supplied values are unused. |
51
+ | `TemplateOptions` | interface | `{ id?, name, content, placeholders?, summary?, description?, category?, tags?, missing?, locale? }` | Carries the options for `createTemplate` / the `Template` constructor. |
52
+ | `TemplateQuery` | interface | `{ name?, category?, tag? }` | Represents a query for `TemplateManagerInterface#find` — every supplied field must match. |
53
+ | `TemplateInterface` | interface | `{ id, name, content, placeholders, summary?, description?, category?, tags? } plus definition, fill, validate, parameters` | Declares the template contract a consumer holds — the readonly template record and the `definition`, `fill`, `validate`, and `parameters` calls over it. |
54
+ | `TemplateManagerOptions` | interface | `{ templates?, missing?, locale?, on?, error? }` | Carries the options for `createTemplateManager` / the `TemplateManager` constructor. |
55
+ | `TemplateManagerInterface` | interface | `{ emitter, count } plus register, template, templates, find, has, remove, clear, destroy, fill, validate, parameters` | Declares the registry contract a consumer holds — a self-owning, id-keyed record-holder with singular and plural accessors over the templates it registers. |
56
+
57
+ ### Constants
58
+
59
+ A `Shape` cell holds the constant's declared type.
60
+
61
+ | API | Kind | Shape | Summary |
62
+ | ------------------------ | ----- | ------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
63
+ | `FILL_PATTERN` | const | `RegExp` | Holds the single-pass `{{name}}` substitution pattern shared by `Template#fill` and `Template#validate`. |
64
+ | `DEFAULT_MISSING_POLICY` | const | `MissingPolicy` | Holds `'error'`, the default `missing` policy for `Template#fill` / `TemplateManager#fill` when unspecified. |
65
+ | `DEFAULT_LOCALE` | const | `'en-US'` | Holds `'en-US'`, the default `locale` for `Template#fill` / `TemplateManager#fill` when unspecified. |
66
+ | `UNSAFE_FIELD_SEGMENTS` | const | `readonly string[]` | Lists the prototype-pollution-unsafe field-path segments `'__proto__'`, `'constructor'`, and `'prototype'` — a fill lookup refuses to resolve a path containing one of them, treating the placeholder as unresolved. |
67
+
68
+ ```ts
69
+ import {
70
+ DEFAULT_LOCALE,
71
+ DEFAULT_MISSING_POLICY,
72
+ FILL_PATTERN,
73
+ UNSAFE_FIELD_SEGMENTS,
74
+ } from '@orkestrel/template'
75
+
76
+ DEFAULT_MISSING_POLICY // 'error'
77
+ DEFAULT_LOCALE // 'en-US'
78
+ UNSAFE_FIELD_SEGMENTS // ['__proto__', 'constructor', 'prototype']
79
+ FILL_PATTERN.source // the `{{name}}` / `\{{` substitution pattern
80
+ ```
81
+
82
+ ### Errors
83
+
84
+ | API | Kind | Summary |
85
+ | ----------------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
86
+ | `TemplateError` | class | Represents an error thrown by the template layer — a machine-readable `TemplateErrorCode` and an optional `context` record naming the offending id or placeholder name. |
87
+ | `isTemplateError` | function | Narrows an unknown caught value to a `TemplateError`. |
88
+
89
+ ```ts
90
+ import { isTemplateError, TemplateError } from '@orkestrel/template'
91
+
92
+ try {
93
+ throw new TemplateError('NOTFOUND', 'Unknown template id: missing', { id: 'missing' })
94
+ } catch (error) {
95
+ if (isTemplateError(error)) error.code // 'NOTFOUND'
96
+ }
97
+ ```
98
+
99
+ ### Helpers
100
+
101
+ Pure, exported utility functions — the referentially-transparent leaves behind
102
+ `Template#fill` / `#validate`.
103
+
104
+ | API | Kind | Summary |
105
+ | ------------------ | -------- | ------------------------------------------------------------------------------------------------------------------------ |
106
+ | `formatValue` | function | Formats a resolved fill value for substitution into a template's `content`. |
107
+ | `resolveSafeField` | function | Resolves a field path against a fill-values record, refusing any path that touches a prototype-pollution-unsafe segment. |
108
+ | `resolveToken` | function | Resolves one `{{name}}` token against the declared placeholders and the fill-values record. |
109
+ | `fillTemplate` | function | Substitutes every `{{name}}` token in `content` in a single pass. |
110
+
111
+ ```ts
112
+ import { fillTemplate, formatValue, resolveSafeField, resolveToken } from '@orkestrel/template'
113
+
114
+ formatValue(5010, 'en-US') // '5,010'
115
+ formatValue(null, 'en-US') // 'null'
116
+ resolveSafeField({ a: { b: 1 } }, ['a', 'b']) // 1
117
+ resolveSafeField({}, ['__proto__', 'polluted']) // undefined
118
+ resolveToken({ name: 'Ada' }, [], 'name').value // 'Ada'
119
+ resolveToken({}, [{ name: 'nickname', required: false }], 'nickname').required // false
120
+ fillTemplate('Hi {{name}}', { name: 'Ada' }) // 'Hi Ada'
121
+ fillTemplate('Limit {{limit}}', { limit: 5010 }, { missing: 'empty' }) // 'Limit 5,010'
122
+ ```
123
+
124
+ ### Shapers
125
+
126
+ The `@orkestrel/contract` shape values built from declared template data —
127
+ above the helper leaves, consuming them and never consumed by them.
128
+
129
+ | API | Kind | Summary |
130
+ | ------------------ | -------- | -------------------------------------------------------------------------------------------- |
131
+ | `placeholderShape` | function | Builds the `@orkestrel/contract` object shape describing a template's declared placeholders. |
132
+
133
+ ```ts
134
+ import { placeholderShape } from '@orkestrel/template'
135
+
136
+ placeholderShape([{ name: 'city' }]) // an object ContractShape with a `city` string field
137
+ ```
138
+
139
+ ### Factories
140
+
141
+ | API | Kind | Summary |
142
+ | ----------------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------- |
143
+ | `createTemplate` | function | Creates a working `TemplateInterface` from a `TemplateOptions` bag, backed by the `Template` class. |
144
+ | `createTemplateManager` | function | Creates a working `TemplateManagerInterface`, optionally seeded with the templates the options carry, backed by the `TemplateManager` class. |
145
+
146
+ #### Create a template and a registry
147
+
148
+ Builds a template and fills it directly, then seeds a registry with several templates and queries them by category and id.
149
+
150
+ ```ts
151
+ import { createTemplate, createTemplateManager } from '@orkestrel/template'
152
+
153
+ const greeting = createTemplate({ name: 'greeting', content: 'Hi {{name}}' })
154
+ greeting.fill({ name: 'Ada' }) // 'Hi Ada'
155
+
156
+ const templates = createTemplateManager({
157
+ templates: [
158
+ { id: 'greeting', name: 'greeting', content: 'Hi {{name}}', category: 'mail' },
159
+ { id: 'farewell', name: 'farewell', content: 'Bye {{name}}', category: 'mail' },
160
+ { id: 'alert', name: 'alert', content: 'Alert: {{reason}}', category: 'ops' },
161
+ ],
162
+ })
163
+ templates.fill('greeting', { name: 'Ada' }) // 'Hi Ada'
164
+ templates.find({ category: 'mail' }).map((one) => one.id) // ['greeting', 'farewell']
165
+ templates.has('alert') // true
166
+ templates.has('missing') // false
167
+ ```
168
+
169
+ ### Classes
170
+
171
+ | API | Kind | Summary |
172
+ | ----------------- | ----- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
173
+ | `Template` | class | Represents a named, versionable template — `{{name}}` tokens in `content`, filled against a values record — implementing `TemplateInterface` exactly. |
174
+ | `TemplateManager` | class | Represents the template registry — a self-owning, id-keyed record-holder for the `TemplateInterface` instances a consumer registers, looks up, fills, and validates by id — implementing `TemplateManagerInterface` exactly. |
175
+
176
+ ## Methods
177
+
178
+ The public methods of each behavioral interface — one table per type, keyed
179
+ by its backticked name, every call-signature member listed (the `readonly`
180
+ data members — `id` / `name` / `content` / `placeholders` / catalog metadata
181
+ on `Template`; `emitter` / `count` on `TemplateManager` — stay off the method
182
+ tables). Each implementing class exposes exactly its interface's methods, so
183
+ this doubles as the per-instance method surface.
184
+
185
+ #### `TemplateInterface`
186
+
187
+ | Method | Returns | Summary |
188
+ | ------------ | -------------------------------------- | --------------------------------------------------------------------------------------------- |
189
+ | `definition` | `TemplateDefinition` | Returns the plain, JSON-serializable template data. |
190
+ | `fill` | `string` | Substitutes every `{{name}}` token in `content` against `values`. |
191
+ | `validate` | `TemplateValidationResult` | Reports which required placeholders would stay unresolved, and which `values` keys go unused. |
192
+ | `parameters` | `Record<string, unknown> \| undefined` | Projects the declared placeholders to the open tool-parameters record shape. |
193
+
194
+ ```ts
195
+ import { createTemplate } from '@orkestrel/template'
196
+
197
+ const greeting = createTemplate({
198
+ name: 'greeting',
199
+ content: 'Hi {{name}}',
200
+ placeholders: [{ name: 'name' }],
201
+ })
202
+ greeting.definition().name // 'greeting'
203
+ greeting.fill({ name: 'Ada' }) // 'Hi Ada'
204
+ greeting.validate({}).missing // ['name']
205
+ greeting.parameters() // the compiled parameters record, or undefined
206
+ ```
207
+
208
+ #### `TemplateManagerInterface`
209
+
210
+ The by-id calls split on what an unknown id means to each: the `template`
211
+ accessor returns `undefined`, while `fill`, `validate`, and `parameters` throw
212
+ a `TemplateError` coded `NOTFOUND`, because each needs a template to proceed.
213
+ A duplicate id throws a `TemplateError` coded `CONFLICT` unless
214
+ `options.replace` is `true`, and one absent id turns a batch `remove`'s answer
215
+ `false` while the present ids still remove.
216
+
217
+ | Method | Returns | Summary |
218
+ | ------------ | -------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- |
219
+ | `register` | `TemplateInterface` | Registers one template, or overwrites the entry sharing its id when `options.replace` is `true`, and emits `register`. |
220
+ | `template` | `TemplateInterface \| undefined` | Returns one registered template by id, or `undefined` when the id is unregistered. |
221
+ | `templates` | `readonly TemplateInterface[]` | Lists every registered template. |
222
+ | `find` | `readonly TemplateInterface[]` | Filters registered templates by `name`, `category`, and `tag` — every supplied field must match. |
223
+ | `has` | `boolean` | Reports whether a template with the given id is registered. |
224
+ | `remove` | `boolean` (or `void`) | Removes the listed templates by id, one template by id, or every registered template, emitting `remove` once per removed template. |
225
+ | `clear` | `void` | Removes every registered template, emitting `clear`. |
226
+ | `destroy` | `void` | Tears the registry down: drops every registered template and destroys the owned emitter. Idempotent. |
227
+ | `fill` | `string` | Fills a registered template by id. |
228
+ | `validate` | `TemplateValidationResult` | Validates values against a registered template by id. |
229
+ | `parameters` | `Record<string, unknown> \| undefined` | Projects a registered template's parameters by id. |
230
+
231
+ ```ts
232
+ import { createTemplateManager } from '@orkestrel/template'
233
+
234
+ const templates = createTemplateManager()
235
+ const greeting = templates.register({ id: 'greeting', name: 'greeting', content: 'Hi {{name}}' })
236
+ templates.has('greeting') // true
237
+ templates.template('greeting') // the registered TemplateInterface, or undefined
238
+ templates.templates() // every registered template
239
+ templates.find({ name: 'greeting' }) // [greeting]
240
+ templates.fill('greeting', { name: 'Ada' }) // 'Hi Ada'
241
+ templates.validate('greeting', {}).missing // ['name']
242
+ templates.parameters('greeting') // the compiled parameters record, or undefined
243
+ templates.remove('greeting') // true
244
+ templates.clear()
245
+ templates.destroy()
246
+ ```
247
+
248
+ ## Tests
249
+
250
+ - [`tests/guides.test.ts`](../tests/guides.test.ts) — the `## Surface` ↔ `src/core`
251
+ bijection (value and type exports), the `TemplateInterface` ↔ `Template` and
252
+ `TemplateManagerInterface` ↔ `TemplateManager` method bijections, and the equality
253
+ gate: every `Summary` cell against its declaration's description paragraph, the titled
254
+ `Create a template and a registry` fence against the `@example` block of that title
255
+ (pinned so the titled pair cannot be retired silently), and the README pitch against
256
+ this guide's tagline. It also runs the flagship fences and asserts the values their
257
+ comments claim.
258
+ - [`tests/src/core/templates/Template.test.ts`](../tests/src/core/templates/Template.test.ts) —
259
+ construction validation, `definition` / `fill` / `validate` / `parameters`.
260
+ - [`tests/src/core/templates/TemplateManager.test.ts`](../tests/src/core/templates/TemplateManager.test.ts) —
261
+ `register` / `template` / `templates` / `find` / `has` / `remove` / `clear` /
262
+ `destroy` / `fill` / `validate` / `parameters`, including the `CONFLICT` / `NOTFOUND`
263
+ error paths and the apply-each-and-report batch `remove`.
264
+ - [`tests/src/core/factories.test.ts`](../tests/src/core/factories.test.ts) —
265
+ `createTemplate` / `createTemplateManager` return working instances backed
266
+ by real `Template` / `TemplateManager`.
267
+ - [`tests/src/core/helpers.test.ts`](../tests/src/core/helpers.test.ts) —
268
+ `formatValue` / `resolveSafeField` / `resolveToken` / `fillTemplate`,
269
+ including bare interpolation with no declared placeholders, the `{`-in-token
270
+ pattern limit, missing policies, fallback precedence, and
271
+ prototype-pollution-unsafe paths.
272
+ - [`tests/src/core/shapers.test.ts`](../tests/src/core/shapers.test.ts) —
273
+ `placeholderShape` over required, optional, and described placeholders.
274
+
275
+ ## See also
276
+
277
+ - [`AGENTS.md`](../AGENTS.md) — the rules.
278
+ - [`guide.md`](guide.md) — the mirrored guide for `@orkestrel/guide`, the
279
+ devDependency powering this repo's guides-parity test suite.
280
+ - [`README.md`](README.md) — the guides index.