@orkestrel/scaffold 0.0.3 → 0.0.4

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.
@@ -0,0 +1,12 @@
1
+ {
2
+ "mcpServers": {
3
+ "codex": {
4
+ "command": "codex",
5
+ "args": ["mcp-server"]
6
+ },
7
+ "claude": {
8
+ "command": "claude",
9
+ "args": ["mcp", "serve"]
10
+ }
11
+ }
12
+ }
@@ -0,0 +1,8 @@
1
+ {
2
+ "mcpServers": {
3
+ "codex": {
4
+ "command": "codex",
5
+ "args": ["mcp-server"]
6
+ }
7
+ }
8
+ }
@@ -90,6 +90,11 @@
90
90
  "destination": ".claude/agents/grok.md",
91
91
  "executable": false
92
92
  },
93
+ {
94
+ "storage": "claude/agents/implementer.md",
95
+ "destination": ".claude/agents/implementer.md",
96
+ "executable": false
97
+ },
93
98
  {
94
99
  "storage": "claude/agents/orkestrel.md",
95
100
  "destination": ".claude/agents/orkestrel.md",
@@ -215,6 +220,11 @@
215
220
  "destination": ".codex/agents/implementer.toml",
216
221
  "executable": false
217
222
  },
223
+ {
224
+ "storage": "codex/agents/opus.toml",
225
+ "destination": ".codex/agents/opus.toml",
226
+ "executable": false
227
+ },
218
228
  {
219
229
  "storage": "codex/agents/orkestrel.toml",
220
230
  "destination": ".codex/agents/orkestrel.toml",
@@ -240,6 +250,11 @@
240
250
  "destination": ".codex/config.toml",
241
251
  "executable": false
242
252
  },
253
+ {
254
+ "storage": "cursor/mcp.json",
255
+ "destination": ".cursor/mcp.json",
256
+ "executable": false
257
+ },
243
258
  {
244
259
  "storage": "dotfiles/editorconfig",
245
260
  "destination": ".editorconfig",
@@ -255,6 +270,11 @@
255
270
  "destination": ".gitignore",
256
271
  "executable": false
257
272
  },
273
+ {
274
+ "storage": "dotfiles/mcp.json",
275
+ "destination": ".mcp.json",
276
+ "executable": false
277
+ },
258
278
  {
259
279
  "storage": "dotfiles/oxfmtrc.json",
260
280
  "destination": ".oxfmtrc.json",
@@ -347,6 +367,7 @@
347
367
  ".claude/skills/orkestrel-harden-package",
348
368
  ".codex",
349
369
  ".codex/agents",
370
+ ".cursor",
350
371
  "guides",
351
372
  "guides/src",
352
373
  "scripts",
@@ -13,6 +13,7 @@ export const CENTRAL_SOURCE_FILES: readonly string[] = Object.freeze([
13
13
  'factories.ts',
14
14
  'helpers.ts',
15
15
  'handlers.ts',
16
+ 'inferers.ts',
16
17
  'middlewares.ts',
17
18
  'parsers.ts',
18
19
  'relations.ts',
@@ -33,6 +34,7 @@ export const FUNCTION_SOURCE_FILES: readonly string[] = Object.freeze([
33
34
  'factories.ts',
34
35
  'handlers.ts',
35
36
  'helpers.ts',
37
+ 'inferers.ts',
36
38
  'middlewares.ts',
37
39
  'parsers.ts',
38
40
  'relations.ts',
@@ -100,6 +102,23 @@ export function isDirectCallback(node: ts.ArrowFunction | ts.FunctionExpression)
100
102
  )
101
103
  }
102
104
 
105
+ /**
106
+ * Whether an arrow/function expression is returned directly as a factory or combinator result.
107
+ *
108
+ * @param node - The function expression to inspect
109
+ * @returns `true` when the node is a direct return value, including one parenthesized layer
110
+ */
111
+ export function isDirectReturn(node: ts.ArrowFunction | ts.FunctionExpression): boolean {
112
+ const parent = node.parent
113
+ if (ts.isReturnStatement(parent)) return true
114
+ if (ts.isArrowFunction(parent) && parent.body === node) return true
115
+ if (!ts.isParenthesizedExpression(parent)) return false
116
+ const container = parent.parent
117
+ return (
118
+ ts.isReturnStatement(container) || (ts.isArrowFunction(container) && container.body === parent)
119
+ )
120
+ }
121
+
103
122
  /** Whether a function expression is assigned by one module-scope variable declaration. */
104
123
  export function isModuleFunction(node: ts.ArrowFunction | ts.FunctionExpression): boolean {
105
124
  const declaration = node.parent
@@ -113,6 +132,18 @@ export function isModuleFunction(node: ts.ArrowFunction | ts.FunctionExpression)
113
132
  )
114
133
  }
115
134
 
135
+ /**
136
+ * Format a syntax node's source position as a one-based line and character.
137
+ *
138
+ * @param node - The syntax node whose starting position to format
139
+ * @returns The node's one-based `line:character` position
140
+ */
141
+ export function formatPolicyPosition(node: ts.Node): string {
142
+ const source = node.getSourceFile()
143
+ const position = source.getLineAndCharacterOfPosition(node.getStart())
144
+ return `${String(position.line + 1)}:${String(position.character + 1)}`
145
+ }
146
+
116
147
  /** Whether a property signature belongs to a centralized interface or type alias contract. */
117
148
  export function isContractProperty(node: ts.PropertySignature): boolean {
118
149
  let parent: ts.Node = node.parent
@@ -162,10 +193,10 @@ export function inspectCodingNode(path: string, node: ts.Node, violations: strin
162
193
  ts.isTypeAssertionExpression(node) ||
163
194
  ts.isNonNullExpression(node)
164
195
  ) {
165
- violations.push(`${path}:${node.getStart()} forbids type/non-null assertions`)
196
+ violations.push(`${path}:${formatPolicyPosition(node)} forbids type/non-null assertions`)
166
197
  }
167
198
  if (node.kind === ts.SyntaxKind.AnyKeyword) {
168
- violations.push(`${path}:${node.getStart()} forbids any`)
199
+ violations.push(`${path}:${formatPolicyPosition(node)} forbids any`)
169
200
  }
170
201
  if (
171
202
  (ts.isImportDeclaration(node) || ts.isExportDeclaration(node)) &&
@@ -173,14 +204,14 @@ export function inspectCodingNode(path: string, node: ts.Node, violations: strin
173
204
  ts.isStringLiteral(node.moduleSpecifier) &&
174
205
  isUnsupportedModuleSpecifier(node.moduleSpecifier.text)
175
206
  ) {
176
- violations.push(`${path}:${node.getStart()} forbids non-Node URL module specifiers`)
207
+ violations.push(`${path}:${formatPolicyPosition(node)} forbids non-Node URL module specifiers`)
177
208
  }
178
209
  if (
179
210
  ts.isPropertySignature(node) &&
180
211
  isContractProperty(node) &&
181
212
  !hasModifier(node, ts.SyntaxKind.ReadonlyKeyword)
182
213
  ) {
183
- violations.push(`${path}:${node.getStart()} requires readonly contract properties`)
214
+ violations.push(`${path}:${formatPolicyPosition(node)} requires readonly contract properties`)
184
215
  }
185
216
  if (
186
217
  ts.isCallExpression(node) &&
@@ -188,7 +219,7 @@ export function inspectCodingNode(path: string, node: ts.Node, violations: strin
188
219
  (node.arguments.length !== 1 || !node.arguments.every(ts.isStringLiteral))
189
220
  ) {
190
221
  violations.push(
191
- `${path}:${node.getStart()} requires dynamic imports to use string literals so import policy remains enforceable`,
222
+ `${path}:${formatPolicyPosition(node)} requires dynamic imports to use string literals so import policy remains enforceable`,
192
223
  )
193
224
  }
194
225
  if (
@@ -198,17 +229,18 @@ export function inspectCodingNode(path: string, node: ts.Node, violations: strin
198
229
  node.arguments.every(ts.isStringLiteral) &&
199
230
  isUnsupportedModuleSpecifier(node.arguments[0]?.text ?? '')
200
231
  ) {
201
- violations.push(`${path}:${node.getStart()} forbids non-Node URL module specifiers`)
232
+ violations.push(`${path}:${formatPolicyPosition(node)} forbids non-Node URL module specifiers`)
202
233
  }
203
234
  if (ts.isFunctionDeclaration(node) && !ts.isSourceFile(node.parent)) {
204
- violations.push(`${path}:${node.getStart()} forbids nested function declarations`)
235
+ violations.push(`${path}:${formatPolicyPosition(node)} forbids nested function declarations`)
205
236
  }
206
237
  if (
207
238
  (ts.isArrowFunction(node) || ts.isFunctionExpression(node)) &&
208
239
  !isDirectCallback(node) &&
240
+ !isDirectReturn(node) &&
209
241
  !isModuleFunction(node)
210
242
  ) {
211
- violations.push(`${path}:${node.getStart()} forbids hidden function assignments`)
243
+ violations.push(`${path}:${formatPolicyPosition(node)} forbids hidden function assignments`)
212
244
  }
213
245
  ts.forEachChild(node, (child) => inspectCodingNode(path, child, violations))
214
246
  }
@@ -290,14 +322,18 @@ export function inspectCodingLaw(path: string, content: string): readonly string
290
322
  !ts.isIdentifier(declaration.name) ||
291
323
  !/^[A-Z][A-Z0-9_]*$/u.test(declaration.name.text)
292
324
  ) {
293
- violations.push(`${path}:${declaration.getStart()} requires UPPER_SNAKE_CASE constants`)
325
+ violations.push(
326
+ `${path}:${formatPolicyPosition(declaration)} requires UPPER_SNAKE_CASE constants`,
327
+ )
294
328
  }
295
329
  if (
296
330
  declaration.initializer !== undefined &&
297
331
  (ts.isArrayLiteralExpression(declaration.initializer) ||
298
332
  ts.isObjectLiteralExpression(declaration.initializer))
299
333
  ) {
300
- violations.push(`${path}:${declaration.getStart()} freezes collection constants`)
334
+ violations.push(
335
+ `${path}:${formatPolicyPosition(declaration)} freezes collection constants`,
336
+ )
301
337
  }
302
338
  }
303
339
  }
@@ -321,7 +357,7 @@ export function inspectCodingLaw(path: string, content: string): readonly string
321
357
  }
322
358
  for (const member of classes[0]?.members ?? []) {
323
359
  if (hasModifier(member, ts.SyntaxKind.PrivateKeyword)) {
324
- violations.push(`${path}:${member.getStart()} uses runtime # privacy`)
360
+ violations.push(`${path}:${formatPolicyPosition(member)} uses runtime # privacy`)
325
361
  }
326
362
  }
327
363
  }
@@ -119,6 +119,8 @@ var HOST_PATHS = Object.freeze([
119
119
  ".claude/settings.json",
120
120
  ".codex/agents",
121
121
  ".codex/config.toml",
122
+ ".cursor/mcp.json",
123
+ ".mcp.json",
122
124
  "scripts/deps.sh",
123
125
  "scripts/cursor.sh",
124
126
  "scripts/codex.sh",
@@ -216,7 +218,7 @@ var DEFAULT_VERSION = "0.0.1";
216
218
  /** The `engines.node` range the `blueprint` builder fills. */
217
219
  var DEFAULT_ENGINES = `>=${MINIMUM_NODE_VERSION}`;
218
220
  /** The devDependency range generated packages pin `@orkestrel/scaffold` at. */
219
- var SCAFFOLD_RANGE = "^0.0.2";
221
+ var SCAFFOLD_RANGE = "^0.0.4";
220
222
  /** Tooling versions shared by scaffold and every generated workspace. */
221
223
  var BASE_DEV_DEPENDENCIES = Object.freeze({
222
224
  "@microsoft/api-extractor": "^7.58.12",