mustflow 2.114.12 → 2.115.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.
@@ -15,6 +15,7 @@ const TEMPLATE_SKILL_ROOT = 'templates/default/locales/en/.mustflow/skills';
15
15
  const TEMPLATE_ROUTES_PATH = 'templates/default/locales/en/.mustflow/skills/routes.toml';
16
16
  const TEMPLATE_MANIFEST_PATH = 'templates/default/manifest.toml';
17
17
  const TEMPLATE_I18N_PATH = 'templates/default/i18n.toml';
18
+ const MANIFEST_LOCK_PATH = '.mustflow/config/manifest.lock.toml';
18
19
  const SKILL_PATH_PATTERN = /^\.mustflow\/skills\/([^/]+)\/SKILL\.md$/u;
19
20
  function normalizePath(value) {
20
21
  return value.replace(/\\/gu, '/');
@@ -163,6 +164,27 @@ function readTemplateManifest(projectRoot, issues) {
163
164
  return { creates: [], profileEntries: [] };
164
165
  }
165
166
  }
167
+ function readActiveInstallProfile(projectRoot, issues) {
168
+ try {
169
+ if (!existsSync(path.join(projectRoot, ...MANIFEST_LOCK_PATH.split('/')))) {
170
+ return null;
171
+ }
172
+ const parsed = readMustflowOwnedTomlFile(projectRoot, MANIFEST_LOCK_PATH);
173
+ const profile = isRecord(parsed) && isRecord(parsed.template) && typeof parsed.template.profile === 'string'
174
+ ? parsed.template.profile.trim()
175
+ : '';
176
+ if (profile.length === 0) {
177
+ issues.push(`${MANIFEST_LOCK_PATH} does not declare a non-empty [template].profile value`);
178
+ return null;
179
+ }
180
+ return profile;
181
+ }
182
+ catch (error) {
183
+ const message = error instanceof Error ? error.message : String(error);
184
+ issues.push(`Could not read ${MANIFEST_LOCK_PATH}: ${message}`);
185
+ return null;
186
+ }
187
+ }
166
188
  function readI18nDocuments(projectRoot, issues) {
167
189
  const documents = new Map();
168
190
  try {
@@ -211,6 +233,77 @@ function compareSetPresence(findings, left, right, options) {
211
233
  function createInputHash(reportInput) {
212
234
  return sha256(JSON.stringify(reportInput));
213
235
  }
236
+ function hasFindingCodePrefix(findings, prefixes) {
237
+ return findings.some((finding) => prefixes.some((prefix) => finding.code.startsWith(prefix)));
238
+ }
239
+ function hasIssueMention(issues, paths) {
240
+ return issues.some((issue) => paths.some((pathValue) => issue.includes(pathValue)));
241
+ }
242
+ function createResolution(inventory, findings, issues, activeInstallProfile) {
243
+ const localPartial = hasIssueMention(issues, [SOURCE_SKILL_ROOT, SOURCE_INDEX_PATH, SOURCE_ROUTES_PATH]);
244
+ const localIssues = hasFindingCodePrefix(findings, ['skill_', 'route_', 'index_', 'frontmatter_']);
245
+ const templateAvailable = inventory.template_skills.length > 0 ||
246
+ inventory.manifest_skill_creates.length > 0 ||
247
+ inventory.manifest_profile_skills.length > 0 ||
248
+ inventory.i18n_skill_documents.length > 0;
249
+ const templatePartial = hasIssueMention(issues, [TEMPLATE_SKILL_ROOT, TEMPLATE_ROUTES_PATH, TEMPLATE_MANIFEST_PATH, TEMPLATE_I18N_PATH]);
250
+ const templateIssues = hasFindingCodePrefix(findings, ['template_', 'manifest_', 'i18n_']);
251
+ const activeInstallPartial = hasIssueMention(issues, [MANIFEST_LOCK_PATH]);
252
+ const activeInstallIssues = findings.some((finding) => finding.code === 'route_without_skill' || finding.code === 'index_without_skill');
253
+ const activeInstallStatus = activeInstallPartial
254
+ ? 'partial'
255
+ : activeInstallProfile === null
256
+ ? 'not_available'
257
+ : activeInstallIssues
258
+ ? 'issues_found'
259
+ : 'ok';
260
+ return {
261
+ local_registry: {
262
+ status: localPartial ? 'partial' : localIssues ? 'issues_found' : 'ok',
263
+ profile: null,
264
+ skill_root: SOURCE_SKILL_ROOT,
265
+ route_metadata: SOURCE_ROUTES_PATH,
266
+ index: SOURCE_INDEX_PATH,
267
+ manifest: null,
268
+ i18n: null,
269
+ note: 'Local registry status compares the installed skill files, routes.toml, and INDEX.md inside mustflow_root.',
270
+ },
271
+ packaged_template_registry: {
272
+ status: templatePartial ? 'partial' : !templateAvailable ? 'not_available' : templateIssues ? 'issues_found' : 'ok',
273
+ profile: null,
274
+ skill_root: TEMPLATE_SKILL_ROOT,
275
+ route_metadata: TEMPLATE_ROUTES_PATH,
276
+ index: null,
277
+ manifest: TEMPLATE_MANIFEST_PATH,
278
+ i18n: TEMPLATE_I18N_PATH,
279
+ note: 'Packaged template status compares source skills with the default install template, manifest creates, profiles, and i18n metadata.',
280
+ },
281
+ shared_workspace_registry: {
282
+ status: 'not_evaluated',
283
+ profile: null,
284
+ skill_root: null,
285
+ route_metadata: null,
286
+ index: null,
287
+ manifest: null,
288
+ i18n: null,
289
+ note: 'This script-pack audits the current mustflow_root only; agents in nested repositories must separately inspect any parent shared workspace skill registry named by AGENTS.md.',
290
+ },
291
+ active_install_profile: {
292
+ status: activeInstallStatus,
293
+ profile: activeInstallProfile,
294
+ skill_root: SOURCE_SKILL_ROOT,
295
+ route_metadata: SOURCE_ROUTES_PATH,
296
+ index: SOURCE_INDEX_PATH,
297
+ manifest: MANIFEST_LOCK_PATH,
298
+ i18n: null,
299
+ note: activeInstallProfile === null
300
+ ? `No active install profile was found in ${MANIFEST_LOCK_PATH}; use local_registry for current files and packaged_template_registry for built-in template coverage.`
301
+ : activeInstallIssues
302
+ ? `Active install profile is "${activeInstallProfile}". Route or index entries reference skills absent from the current .mustflow/skills install surface; compare packaged_template_registry and shared_workspace_registry before treating a related skill as missing from mustflow.`
303
+ : `Active install profile is "${activeInstallProfile}". Current route and index entries resolve to local skill files for this installed profile.`,
304
+ },
305
+ };
306
+ }
214
307
  export function auditSkillRoutes(projectRoot) {
215
308
  const root = path.resolve(projectRoot);
216
309
  const issues = [];
@@ -225,6 +318,7 @@ export function auditSkillRoutes(projectRoot) {
225
318
  const manifestCreateSkillNames = uniqueSorted(manifest.creates.map((entry) => skillFromSkillPath(entry)).filter(Boolean));
226
319
  const i18nDocuments = readI18nDocuments(root, issues);
227
320
  const i18nSkillNames = uniqueSorted([...i18nDocuments.keys()].map((id) => id.replace(/^skill\./u, '')));
321
+ const activeInstallProfile = readActiveInstallProfile(root, issues);
228
322
  const findings = [];
229
323
  compareSetPresence(findings, sourceSkillNames, routeSkillNames, {
230
324
  missingCode: 'skill_without_route',
@@ -320,6 +414,7 @@ export function auditSkillRoutes(projectRoot) {
320
414
  manifest_profile_skills: manifestProfileSkills,
321
415
  i18n_skill_documents: i18nSkillNames,
322
416
  };
417
+ const resolution = createResolution(inventory, findings, issues, activeInstallProfile);
323
418
  const status = issues.length > 0 ? 'partial' : findings.length > 0 ? 'issues_found' : 'ok';
324
419
  return {
325
420
  schema_version: '1',
@@ -337,7 +432,7 @@ export function auditSkillRoutes(projectRoot) {
337
432
  template_manifest: TEMPLATE_MANIFEST_PATH,
338
433
  template_i18n: TEMPLATE_I18N_PATH,
339
434
  },
340
- input_hash: createInputHash({ inventory, findings, issues }),
435
+ input_hash: createInputHash({ inventory, resolution, findings, issues }),
341
436
  counts: {
342
437
  source_skills: sourceSkillNames.length,
343
438
  index_routes: indexSkillNames.length,
@@ -348,6 +443,7 @@ export function auditSkillRoutes(projectRoot) {
348
443
  i18n_skill_documents: i18nSkillNames.length,
349
444
  },
350
445
  inventory,
446
+ resolution,
351
447
  findings,
352
448
  issues,
353
449
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mustflow",
3
- "version": "2.114.12",
3
+ "version": "2.115.0",
4
4
  "description": "Agent workflow documents and CLI for mustflow repository roots.",
5
5
  "type": "module",
6
6
  "license": "MIT-0",
package/schemas/README.md CHANGED
@@ -164,7 +164,8 @@ Current schemas:
164
164
  rewriting `.mustflow/config/manifest.lock.toml`
165
165
  - `skill-route-audit-report.schema.json`: output of
166
166
  `mf script-pack run repo/skill-route-audit audit --json`, containing source skill, route metadata,
167
- skill index, default template skill copy, manifest profile, and i18n metadata drift findings
167
+ skill index, default template skill copy, manifest profile, i18n metadata drift findings, and
168
+ local/template/shared-workspace/active-profile registry resolution status
168
169
  - `repo-version-source-report.schema.json`: output of
169
170
  `mf script-pack run repo/version-source inspect --json`, containing detected version sources,
170
171
  release-versioning preference status, source authority counts, and missing-source findings
@@ -254,8 +254,43 @@
254
254
  { "type": "null" }
255
255
  ]
256
256
  },
257
+ "safety_contract": {
258
+ "$ref": "#/$defs/safetyContract"
259
+ },
257
260
  "run_hint": { "type": "string" }
258
261
  }
262
+ },
263
+ "safetyContract": {
264
+ "type": "object",
265
+ "additionalProperties": false,
266
+ "required": [
267
+ "authority_class",
268
+ "execution_mode",
269
+ "command_authority",
270
+ "run_hint_authority",
271
+ "input_scope",
272
+ "output_scope",
273
+ "cannot_satisfy_intents",
274
+ "forbidden_actions"
275
+ ],
276
+ "properties": {
277
+ "authority_class": { "const": "advisory_evidence" },
278
+ "execution_mode": { "const": "suggestion_only" },
279
+ "command_authority": { "const": "requires_configured_intent" },
280
+ "run_hint_authority": { "const": "not_authority" },
281
+ "input_scope": { "const": "explicit_or_changed_paths" },
282
+ "output_scope": { "const": "bounded_report" },
283
+ "cannot_satisfy_intents": {
284
+ "type": "array",
285
+ "items": { "type": "string" },
286
+ "minItems": 1
287
+ },
288
+ "forbidden_actions": {
289
+ "type": "array",
290
+ "items": { "type": "string" },
291
+ "minItems": 1
292
+ }
293
+ }
259
294
  }
260
295
  }
261
296
  }
@@ -93,6 +93,41 @@
93
93
  { "type": "string", "pattern": "^[a-z0-9-]+\\.schema\\.json$" },
94
94
  { "type": "null" }
95
95
  ]
96
+ },
97
+ "safety_contract": {
98
+ "$ref": "#/$defs/safetyContract"
99
+ }
100
+ }
101
+ },
102
+ "safetyContract": {
103
+ "type": "object",
104
+ "additionalProperties": false,
105
+ "required": [
106
+ "authority_class",
107
+ "execution_mode",
108
+ "command_authority",
109
+ "run_hint_authority",
110
+ "input_scope",
111
+ "output_scope",
112
+ "cannot_satisfy_intents",
113
+ "forbidden_actions"
114
+ ],
115
+ "properties": {
116
+ "authority_class": { "const": "advisory_evidence" },
117
+ "execution_mode": { "const": "suggestion_only" },
118
+ "command_authority": { "const": "requires_configured_intent" },
119
+ "run_hint_authority": { "const": "not_authority" },
120
+ "input_scope": { "const": "explicit_or_changed_paths" },
121
+ "output_scope": { "const": "bounded_report" },
122
+ "cannot_satisfy_intents": {
123
+ "type": "array",
124
+ "items": { "type": "string" },
125
+ "minItems": 1
126
+ },
127
+ "forbidden_actions": {
128
+ "type": "array",
129
+ "items": { "type": "string" },
130
+ "minItems": 1
96
131
  }
97
132
  }
98
133
  }
@@ -152,8 +152,43 @@
152
152
  { "type": "null" }
153
153
  ]
154
154
  },
155
+ "safety_contract": {
156
+ "$ref": "#/$defs/safetyContract"
157
+ },
155
158
  "run_hint": { "type": "string" }
156
159
  }
160
+ },
161
+ "safetyContract": {
162
+ "type": "object",
163
+ "additionalProperties": false,
164
+ "required": [
165
+ "authority_class",
166
+ "execution_mode",
167
+ "command_authority",
168
+ "run_hint_authority",
169
+ "input_scope",
170
+ "output_scope",
171
+ "cannot_satisfy_intents",
172
+ "forbidden_actions"
173
+ ],
174
+ "properties": {
175
+ "authority_class": { "const": "advisory_evidence" },
176
+ "execution_mode": { "const": "suggestion_only" },
177
+ "command_authority": { "const": "requires_configured_intent" },
178
+ "run_hint_authority": { "const": "not_authority" },
179
+ "input_scope": { "const": "explicit_or_changed_paths" },
180
+ "output_scope": { "const": "bounded_report" },
181
+ "cannot_satisfy_intents": {
182
+ "type": "array",
183
+ "items": { "type": "string" },
184
+ "minItems": 1
185
+ },
186
+ "forbidden_actions": {
187
+ "type": "array",
188
+ "items": { "type": "string" },
189
+ "minItems": 1
190
+ }
191
+ }
157
192
  }
158
193
  }
159
194
  }
@@ -18,6 +18,7 @@
18
18
  "input_hash",
19
19
  "counts",
20
20
  "inventory",
21
+ "resolution",
21
22
  "findings",
22
23
  "issues"
23
24
  ],
@@ -45,6 +46,7 @@
45
46
  "input_hash": { "$ref": "#/$defs/sha256" },
46
47
  "counts": { "$ref": "#/$defs/counts" },
47
48
  "inventory": { "$ref": "#/$defs/inventory" },
49
+ "resolution": { "$ref": "#/$defs/resolution" },
48
50
  "findings": {
49
51
  "type": "array",
50
52
  "items": { "$ref": "#/$defs/finding" }
@@ -107,6 +109,40 @@
107
109
  "i18n_skill_documents": { "$ref": "#/$defs/stringArray" }
108
110
  }
109
111
  },
112
+ "registryStatus": {
113
+ "enum": ["ok", "issues_found", "partial", "not_available", "not_evaluated"]
114
+ },
115
+ "registryScope": {
116
+ "type": "object",
117
+ "additionalProperties": false,
118
+ "required": ["status", "profile", "skill_root", "route_metadata", "index", "manifest", "i18n", "note"],
119
+ "properties": {
120
+ "status": { "$ref": "#/$defs/registryStatus" },
121
+ "profile": { "type": ["string", "null"] },
122
+ "skill_root": { "type": ["string", "null"] },
123
+ "route_metadata": { "type": ["string", "null"] },
124
+ "index": { "type": ["string", "null"] },
125
+ "manifest": { "type": ["string", "null"] },
126
+ "i18n": { "type": ["string", "null"] },
127
+ "note": { "type": "string" }
128
+ }
129
+ },
130
+ "resolution": {
131
+ "type": "object",
132
+ "additionalProperties": false,
133
+ "required": [
134
+ "local_registry",
135
+ "packaged_template_registry",
136
+ "shared_workspace_registry",
137
+ "active_install_profile"
138
+ ],
139
+ "properties": {
140
+ "local_registry": { "$ref": "#/$defs/registryScope" },
141
+ "packaged_template_registry": { "$ref": "#/$defs/registryScope" },
142
+ "shared_workspace_registry": { "$ref": "#/$defs/registryScope" },
143
+ "active_install_profile": { "$ref": "#/$defs/registryScope" }
144
+ }
145
+ },
110
146
  "finding": {
111
147
  "type": "object",
112
148
  "additionalProperties": false,
@@ -291,9 +291,44 @@
291
291
  { "type": "null" }
292
292
  ]
293
293
  },
294
+ "safety_contract": {
295
+ "$ref": "#/$defs/safetyContract"
296
+ },
294
297
  "run_hint": { "type": "string" }
295
298
  }
296
299
  },
300
+ "safetyContract": {
301
+ "type": "object",
302
+ "additionalProperties": false,
303
+ "required": [
304
+ "authority_class",
305
+ "execution_mode",
306
+ "command_authority",
307
+ "run_hint_authority",
308
+ "input_scope",
309
+ "output_scope",
310
+ "cannot_satisfy_intents",
311
+ "forbidden_actions"
312
+ ],
313
+ "properties": {
314
+ "authority_class": { "const": "advisory_evidence" },
315
+ "execution_mode": { "const": "suggestion_only" },
316
+ "command_authority": { "const": "requires_configured_intent" },
317
+ "run_hint_authority": { "const": "not_authority" },
318
+ "input_scope": { "const": "explicit_or_changed_paths" },
319
+ "output_scope": { "const": "bounded_report" },
320
+ "cannot_satisfy_intents": {
321
+ "type": "array",
322
+ "items": { "type": "string" },
323
+ "minItems": 1
324
+ },
325
+ "forbidden_actions": {
326
+ "type": "array",
327
+ "items": { "type": "string" },
328
+ "minItems": 1
329
+ }
330
+ }
331
+ },
297
332
  "candidate": {
298
333
  "type": "object",
299
334
  "additionalProperties": false,
@@ -221,9 +221,44 @@
221
221
  { "type": "null" }
222
222
  ]
223
223
  },
224
+ "safety_contract": {
225
+ "$ref": "#/$defs/safetyContract"
226
+ },
224
227
  "run_hint": { "type": "string" }
225
228
  }
226
229
  },
230
+ "safetyContract": {
231
+ "type": "object",
232
+ "additionalProperties": false,
233
+ "required": [
234
+ "authority_class",
235
+ "execution_mode",
236
+ "command_authority",
237
+ "run_hint_authority",
238
+ "input_scope",
239
+ "output_scope",
240
+ "cannot_satisfy_intents",
241
+ "forbidden_actions"
242
+ ],
243
+ "properties": {
244
+ "authority_class": { "const": "advisory_evidence" },
245
+ "execution_mode": { "const": "suggestion_only" },
246
+ "command_authority": { "const": "requires_configured_intent" },
247
+ "run_hint_authority": { "const": "not_authority" },
248
+ "input_scope": { "const": "explicit_or_changed_paths" },
249
+ "output_scope": { "const": "bounded_report" },
250
+ "cannot_satisfy_intents": {
251
+ "type": "array",
252
+ "items": { "type": "string" },
253
+ "minItems": 1
254
+ },
255
+ "forbidden_actions": {
256
+ "type": "array",
257
+ "items": { "type": "string" },
258
+ "minItems": 1
259
+ }
260
+ }
261
+ },
227
262
  "classification": {
228
263
  "type": "object",
229
264
  "additionalProperties": false,
@@ -778,6 +778,12 @@ source_locale = "en"
778
778
  revision = 4
779
779
  translations = {}
780
780
 
781
+ [documents."skill.nestjs-code-change"]
782
+ source = "locales/en/.mustflow/skills/nestjs-code-change/SKILL.md"
783
+ source_locale = "en"
784
+ revision = 1
785
+ translations = {}
786
+
781
787
  [documents."skill.react-code-change"]
782
788
  source = "locales/en/.mustflow/skills/react-code-change/SKILL.md"
783
789
  source_locale = "en"
@@ -316,6 +316,10 @@ refer to `AGENTS.md` and `.mustflow/config/commands.toml` to implement the most
316
316
  extensions, middleware, Tower or Tower-HTTP layers, CORS, cookies, headers, Tokio tasks or locks,
317
317
  SQLx pools, rejections, error responses, body limits, WebSockets, or Rust HTTP API tests are
318
318
  created, changed, reviewed, or upgraded.
319
+ - Use `nestjs-code-change` as a primary route when NestJS modules, controllers, providers,
320
+ dependency injection, guards, pipes, interceptors, filters, OpenAPI metadata, adapters,
321
+ lifecycle hooks, queues, schedulers, WebSockets, microservices, or Nest-backed HTTP API tests are
322
+ created, changed, reviewed, or upgraded.
319
323
  - Use `godot-code-change` as a primary route when Godot projects, scenes, nodes, GDScript, C#
320
324
  scripts, Resources, Autoloads, signals, groups, save/load systems, rendering, physics, UI,
321
325
  input, exports, plugins, editor tools, or Godot version migrations are created, changed, reviewed,
@@ -598,6 +602,7 @@ routes. Event routes stay inactive until their event occurs.
598
602
  | Godot projects, scenes, nodes, GDScript, C# scripts, Resources, Autoloads, signals, groups, save/load systems, rendering, physics, UI, input, exports, plugins, editor tools, or Godot version migrations are created, changed, reviewed, or upgraded | `.mustflow/skills/godot-code-change/SKILL.md` | Godot version, renderer, platform targets, project settings, input map, autoloads, addons, affected scenes, scripts, Resources, save/load participants, export presets, profiler evidence when performance is claimed, and command contract entries | Godot scenes, nodes, GDScript or C# scripts, Resources, Autoloads, signals, groups, save/load systems, rendering, physics, UI, input, exports, plugins, editor tools, tests, and docs examples | stale Godot version claim, scene-tree reach-through, global-state sprawl, shared Resource mutation, hidden signal flow, save corruption, thread-unsafe SceneTree access, renderer regression, target-device drift, export preset drift, or stale migration advice | `changes_status`, `changes_diff_summary`, `lint`, `build`, `test_related`, `test`, `docs_validate_fast`, `mustflow_check` | Godot version, renderer, scene, node, signal, Resource, Autoload, save/load, rendering, physics, UI, input, export, verification, and remaining Godot risk |
599
603
  | Dart source, pub package metadata, null safety, Futures, Streams, isolates, analyzer lints, tests, CLI entry points, or public package APIs are created or changed | `.mustflow/skills/dart-code-change/SKILL.md` | Pub metadata, analyzer config, public exports, async ownership, package layout, changed files, and command contract entries | Dart source, pub metadata, exports, async code, tests, examples, and docs | null-safety bypass, discarded Future, uncanceled Stream, isolate ownership drift, or public API breakage | `changes_status`, `changes_diff_summary`, `lint`, `build`, `test_related`, `test`, `docs_validate_fast`, `mustflow_check` | Nullability, async, stream, isolate, and API boundary checked, verification, and remaining Dart risk |
600
604
  | Hono apps, route chains, middleware order, validators, RPC or typed clients, OpenAPI schema generation, runtime bindings, context variables, auth, CORS, cookie, header, streaming, WebSocket, cache, static asset, or Cloudflare/Bun/Node/Deno/serverless adapter boundaries are created or changed | `.mustflow/skills/hono-code-change/SKILL.md` | App entry, runtime adapter, route modules, middleware order, binding and variable types, schemas, validators, OpenAPI setup, RPC or SDK client types, response contract, changed files, and command contract entries | Hono routes, middleware, validators, bindings, context variables, RPC types, OpenAPI or SDK surfaces, runtime entry files, tests, and docs examples | route-order shadowing, runtime API mixing, middleware order bug, auth/CORS/cookie/header gap, body parser drift, OpenAPI/RPC type drift, response envelope drift, streaming or WebSocket cancellation leak, cache or static path leak, adapter header drift, or broken typed route inference | `changes_status`, `changes_diff_summary`, `lint`, `build`, `test_related`, `test`, `docs_validate_fast`, `mustflow_check` | Runtime, adapter, route-order, middleware, validation, auth/CORS/cookie/header, OpenAPI/RPC/SDK, streaming/cache/static, and response boundary checked, verification, and remaining Hono risk |
605
+ | NestJS modules, controllers, providers, dependency injection, pipes, guards, interceptors, filters, decorators, OpenAPI metadata, adapters, lifecycle hooks, queues, schedulers, WebSockets, microservices, or Nest-backed HTTP API tests are created, changed, reviewed, or upgraded | `.mustflow/skills/nestjs-code-change/SKILL.md` | Nest package and adapter evidence, app bootstrap, modules, controllers, providers, DTOs, guards, pipes, interceptors, filters, middleware, OpenAPI setup, generated clients, changed files, and command contract entries | Nest modules, controllers, providers, DI tokens, dynamic modules, DTOs, validation pipes, guards, interceptors, filters, middleware, adapter-specific code, OpenAPI metadata, tests, and docs examples | hidden global module dependency, DI token drift, casual `forwardRef`, request-local singleton mutation, provider-scope performance bug, validation transform mismatch, auth or guard bypass, inconsistent error envelope, Express/Fastify adapter drift, OpenAPI/runtime drift, lifecycle leak, queue ack bug, or dishonest test-module override | `changes_status`, `changes_diff_summary`, `lint`, `build`, `test_related`, `test`, `docs_validate_fast`, `mustflow_check` | Module, provider, DI token, scope, lifecycle, route, DTO, validation, guard, interceptor, filter, adapter, OpenAPI, verification, and remaining NestJS risk |
601
606
  | Elysia routes, schemas, Standard Schema validators, plugins, decorators, derives, resolves, guards, macros, auth, error handling, OpenAPI or Scalar docs, Eden Treaty clients, streaming, WebSocket, or Bun-backed server behavior are created or changed | `.mustflow/skills/elysia-code-change/SKILL.md` | Server entry, route modules, schemas, plugins, auth, cookies, CORS, lifecycle hooks, OpenAPI or Eden surface, streaming/WebSocket config, deploy settings, changed files, and command contract entries | Elysia routes, schemas, plugins, generated clients, docs UI or raw OpenAPI config, tests, deploy config, and docs examples | schema/type drift, context inference loss, lifecycle scope gap, auth gap, CORS or OpenAPI exposure, inconsistent error envelope, stale OpenAPI/Eden output, streaming timeout gap, WebSocket backpressure gap, or route path SDK drift | `changes_status`, `changes_diff_summary`, `lint`, `build`, `test_related`, `test`, `docs_validate_fast`, `mustflow_check` | Schema, validation, type inference, lifecycle, auth, error, OpenAPI/Eden, runtime/deploy impact checked, verification, and remaining Elysia risk |
602
607
  | Source anchors are added, revised, reviewed, or used to mark a module boundary | `.mustflow/skills/source-anchor-authoring/SKILL.md` | Target files, anchor reason, nearby anchors, source-anchor policy, and validation surface | Source anchors and directly related workflow docs or comments | comment bloat, authority drift, false verification claims, or hidden module pressure | `mustflow_check`, `docs_validate_fast` | Anchor placement decision, field choices, module-boundary handoff, and verification |
603
608
  | Changed files need risk classification and verification selection | `.mustflow/skills/diff-risk-review/SKILL.md` | Changed-file list, diff summary, and task goal | Changed surfaces and verification report | under- or over-verification | `changes_status`, `changes_diff_summary`, `test`, `test_related`, `test_audit`, `lint`, `build`, `docs_validate`, `mustflow_check` | Risk level, verification choice, rollback notes |
@@ -0,0 +1,141 @@
1
+ ---
2
+ mustflow_doc: skill.nestjs-code-change
3
+ locale: en
4
+ canonical: true
5
+ revision: 1
6
+ lifecycle: mustflow-owned
7
+ authority: procedure
8
+ name: nestjs-code-change
9
+ description: Apply this skill when NestJS modules, controllers, providers, dependency injection, pipes, guards, interceptors, filters, decorators, OpenAPI metadata, adapters, lifecycle hooks, queues, schedulers, WebSockets, microservices, or Nest-backed HTTP API tests are created, changed, reviewed, or upgraded.
10
+ metadata:
11
+ mustflow_schema: "1"
12
+ mustflow_kind: procedure
13
+ pack_id: mustflow.core
14
+ skill_id: mustflow.core.nestjs-code-change
15
+ command_intents:
16
+ - changes_status
17
+ - changes_diff_summary
18
+ - lint
19
+ - build
20
+ - test_related
21
+ - test
22
+ - docs_validate_fast
23
+ - mustflow_check
24
+ ---
25
+
26
+ # NestJS Code Change
27
+
28
+ <!-- mustflow-section: purpose -->
29
+ ## Purpose
30
+
31
+ Preserve NestJS module boundaries, dependency-injection ownership, request pipeline order, validation, auth, error, OpenAPI, adapter, lifecycle, and test-module behavior while making focused Nest-backed service or API changes.
32
+
33
+ <!-- mustflow-section: use-when -->
34
+ ## Use When
35
+
36
+ - `@Module`, `@Controller`, route decorators, providers, custom decorators, dependency injection tokens, dynamic modules, global modules, guards, pipes, interceptors, filters, middleware, or Nest testing modules change.
37
+ - The task touches REST controllers, GraphQL resolvers, WebSockets, microservices, queues, schedulers, lifecycle hooks, adapters, request-scoped providers, validation pipes, class-transformer/class-validator behavior, OpenAPI metadata, or generated clients.
38
+ - The task changes auth, tenant, permission, request id, session, cache, transaction, or outbound integration behavior inside a Nest request path.
39
+
40
+ <!-- mustflow-section: do-not-use-when -->
41
+ ## Do Not Use When
42
+
43
+ - The task only changes framework-free service code behind a Nest provider and no provider scope, module export, decorator, pipeline, route, or test-module behavior changes; use the relevant language, architecture, data, or security skill.
44
+ - The project uses Hono, Elysia, Axum, Express without Nest, Fastify without Nest, or another framework as the route owner.
45
+ - The task only updates version prose; use `source-freshness-check` unless the NestJS procedure itself changes.
46
+
47
+ <!-- mustflow-section: required-inputs -->
48
+ ## Required Inputs
49
+
50
+ - Package metadata, Nest package versions, TypeScript config, app bootstrap, adapter choice, modules, controllers, providers, decorators, guards, pipes, interceptors, filters, middleware, OpenAPI setup, generated client surfaces, and tests.
51
+ - Route ledger: method, path, controller prefix, versioning, params, query, headers, cookies, body DTO, validation pipe behavior, auth boundary, response statuses, content types, and public error envelope.
52
+ - Dependency ledger: module imports, provider tokens, exports, scopes, dynamic module options, global modules, circular dependencies, async factories, config sources, request scope, and lifecycle hooks.
53
+ - Existing verification intents for typecheck, build, controller tests, provider tests, e2e HTTP tests, OpenAPI generation, and mustflow validation.
54
+
55
+ <!-- mustflow-section: preconditions -->
56
+ ## Preconditions
57
+
58
+ - Read package metadata, bootstrap, affected modules, controllers, providers, DTOs, decorators, pipeline components, OpenAPI setup, and tests before editing.
59
+ - Identify whether Express or Fastify is the active Nest adapter before using adapter-specific APIs.
60
+ - Identify global pipes, guards, interceptors, filters, middleware, versioning, CORS, prefix, and OpenAPI setup before changing route behavior.
61
+ - Refresh official or repository-local evidence before preserving exact latest-version, migration, or release-specific claims.
62
+
63
+ <!-- mustflow-section: allowed-edits -->
64
+ ## Allowed Edits
65
+
66
+ - Keep Nest framework concerns at module, controller, provider, decorator, and pipeline boundaries.
67
+ - Keep framework-free business logic in services where possible, but do not erase provider tokens, scopes, or module ownership needed by DI.
68
+ - Update DTOs, validation pipes, guards, interceptors, filters, OpenAPI metadata, tests, and docs examples when public API behavior changes.
69
+ - Do not hide dependencies in global modules, static singletons, module-level mutable state, or `forwardRef()` unless the cycle is explicit and reported.
70
+ - Do not bypass configured command intents or run unconfigured Nest servers, watchers, migrations, or generators.
71
+
72
+ <!-- mustflow-section: procedure -->
73
+ ## Procedure
74
+
75
+ 1. Read bootstrap, app module, affected feature modules, controllers, providers, DTOs, guards, pipes, interceptors, filters, middleware, OpenAPI setup, and tests.
76
+ 2. Build a module ledger: imports, providers, exports, dynamic module options, global modules, async factories, provider tokens, scopes, lifecycle hooks, and any circular dependencies.
77
+ 3. Build a route ledger: controller prefix, method, path, version, params, query, headers, cookies, body DTO, validation pipe, auth and permission guards, interceptors, filters, response status, content type, and public client surface.
78
+ 4. Keep dependency injection explicit. Prefer constructor injection with stable tokens, avoid service locators, and avoid importing concrete infrastructure providers into unrelated feature modules.
79
+ 5. Treat provider scope as a performance and correctness contract. Use singleton scope by default, request scope only when request-local data truly belongs in DI, and transient scope only when every construction cost and state boundary is intentional.
80
+ 6. Avoid `forwardRef()` as a casual cycle fix. If a cycle appears, inspect the module boundary, extract a port/interface, move shared policy, or report why the explicit cycle is accepted.
81
+ 7. Check dynamic modules and async factories. Keep options typed, validate config at the boundary, avoid reading secrets into logs or reports, and make module initialization failure explicit.
82
+ 8. Keep request-local data out of singleton provider mutable fields. Current user, tenant, request id, locale, transaction, or per-request cache should travel through request objects, guards, interceptors, CLS-style infrastructure with clear ownership, or explicit method arguments.
83
+ 9. Review pipeline order:
84
+ - middleware runs before guards;
85
+ - guards decide access before interceptors and pipes complete the handler path;
86
+ - pipes transform and validate inputs;
87
+ - interceptors wrap handler execution and response mapping;
88
+ - filters map thrown exceptions.
89
+ 10. Do not treat CORS, Swagger hiding, or route omission from OpenAPI as authorization. Add real guards or report the exposure.
90
+ 11. For DTOs, distinguish TypeScript shape from runtime validation. Class decorators, global `ValidationPipe` options, transform behavior, whitelist, forbid settings, nested validation, arrays, dates, enums, partial update DTOs, and file uploads must be checked against real runtime behavior.
91
+ 12. For params, query, headers, and cookies, remember that HTTP input starts as strings. Use explicit parse pipes, DTO transform rules, or schema validation rather than relying on TypeScript annotations.
92
+ 13. Keep response and error envelopes consistent. Map validation, auth, permission, not-found, conflict, rate-limit, upstream, timeout, and internal failures deliberately; do not leak stack traces, SQL, tokens, or provider details.
93
+ 14. Review adapter-specific behavior. Express and Fastify differ in reply objects, middleware plugins, body parsing, cookies, streaming, multipart handling, and lifecycle hooks; isolate adapter-specific APIs.
94
+ 15. Review OpenAPI and generated clients as separate public contracts. Ensure decorators, DTO metadata, mapped types, unions, file uploads, auth schemes, versioning, and hidden routes match the actual runtime route.
95
+ 16. For GraphQL, WebSockets, queues, schedulers, and microservices, map the transport boundary, serialization, auth context, retry/ack semantics, idempotency, cancellation, and lifecycle shutdown behavior before editing.
96
+ 17. For transactions, caches, queues, and outbound calls inside providers, apply the narrower data, transaction, performance, or third-party integration skill when those invariants change.
97
+ 18. Keep test modules honest. Override only the provider under test, preserve guards/pipes/interceptors when testing route behavior, and avoid mocks that remove the behavior being changed.
98
+ 19. Choose configured verification intents that cover type checking, build, controller/provider tests, validation failure, auth failure, OpenAPI output, and e2e adapter behavior when available.
99
+
100
+ <!-- mustflow-section: postconditions -->
101
+ ## Postconditions
102
+
103
+ - Module imports, provider tokens, exports, scopes, and lifecycle hooks remain intentional.
104
+ - Route, validation, auth, interceptor, filter, response, adapter, OpenAPI, and generated-client behavior are synchronized.
105
+ - Request-local state is not hidden in singleton mutable fields.
106
+ - Any missing route-level, OpenAPI, adapter, lifecycle, queue, WebSocket, microservice, or e2e verification is reported.
107
+
108
+ <!-- mustflow-section: verification -->
109
+ ## Verification
110
+
111
+ Use configured oneshot command intents when available:
112
+
113
+ - `lint`
114
+ - `build`
115
+ - `test_related`
116
+ - `test`
117
+ - `docs_validate_fast`
118
+ - `mustflow_check`
119
+
120
+ Report missing Nest controller, provider, pipeline, OpenAPI, adapter, e2e, queue, WebSocket, microservice, or lifecycle verification intents when relevant.
121
+
122
+ <!-- mustflow-section: failure-handling -->
123
+ ## Failure Handling
124
+
125
+ - If DI fails, inspect provider token registration, module imports and exports, dynamic module setup, circular dependencies, and test module overrides before adding globals or broad imports.
126
+ - If validation behaves unexpectedly, inspect global `ValidationPipe` options, DTO decorators, nested types, transform settings, and whether the route is using a raw body or file upload path.
127
+ - If auth or permission behavior is unclear, stop that route change and inspect guards, decorators, metadata readers, and route-level overrides before broadening access.
128
+ - If OpenAPI looks right but runtime behavior differs, make runtime behavior the source of truth and fix or report the documentation/client drift.
129
+ - If adapter-specific behavior cannot be covered by configured checks, report the skipped Express or Fastify smoke coverage.
130
+
131
+ <!-- mustflow-section: output-format -->
132
+ ## Output Format
133
+
134
+ - Boundary checked
135
+ - Module, provider, DI token, scope, and lifecycle notes
136
+ - Route, DTO, validation, guard, interceptor, filter, and response notes
137
+ - Adapter, OpenAPI, generated client, GraphQL, WebSocket, queue, scheduler, or microservice notes when touched
138
+ - Files changed
139
+ - Command intents run
140
+ - Skipped checks and reasons
141
+ - Remaining NestJS risk
@@ -660,6 +660,12 @@ route_type = "primary"
660
660
  priority = 85
661
661
  applies_to_reasons = ["code_change", "behavior_change", "public_api_change", "test_change", "docs_change", "performance_change", "security_change", "privacy_change", "package_metadata_change", "release_risk"]
662
662
 
663
+ [routes."nestjs-code-change"]
664
+ category = "general_code"
665
+ route_type = "primary"
666
+ priority = 85
667
+ applies_to_reasons = ["code_change", "behavior_change", "public_api_change", "test_change", "docs_change", "performance_change", "security_change", "privacy_change", "data_change", "package_metadata_change", "release_risk"]
668
+
663
669
  [routes."elysia-code-change"]
664
670
  category = "general_code"
665
671
  route_type = "primary"