MCPcopy Create free account
hub / github.com/adcontextprotocol/adcp / lintFile

Function lintFile

scripts/build-compliance.cjs:299–382  ·  view source on GitHub ↗
(p)

Source from the content-addressed store, hash-verified

297 }
298
299 function lintFile(p) {
300 const rel = path.relative(sourceDir, p);
301 // Not storyboards: test-kit fixtures and the schema doc itself.
302 if (rel.startsWith('test-kits/')) return;
303 if (rel.endsWith('storyboard-schema.yaml')) return;
304
305 let doc;
306 try { doc = yaml.load(fs.readFileSync(p, 'utf8')); }
307 catch { return; }
308 if (!doc || typeof doc !== 'object' || !Array.isArray(doc.phases)) return;
309 const generatedContextNames = new Set();
310
311 for (const phase of doc.phases) {
312 if (!phase || !Array.isArray(phase.steps)) continue;
313 for (const step of phase.steps) {
314 if (!step || typeof step !== 'object' || !step.task) continue;
315 // Steps without schema_ref are HTTP probes, controller calls, or
316 // synthetic invocations (e.g., comply_test_controller's
317 // simulate_budget scenarios, universal/security.yaml's probe steps)
318 // that don't send a task request schema. They're out of scope for
319 // this lint — UNLESS the task name itself is a known mutating tool,
320 // in which case the missing schema_ref is itself a storyboard bug
321 // (the step would bypass the idempotency_key lint above). Positive
322 // check per red-team I-9 / security.mdx storyboard hygiene.
323 if (step.task && mutatingTools.has(step.task) && !step.schema_ref) {
324 missingSchemaRefs.push({
325 file: rel,
326 step: step.id,
327 msg: `Step uses mutating tool "${step.task}" but has no schema_ref`,
328 });
329 }
330 const schemaRef = step.schema_ref;
331 if (!schemaRef || !mutatingRefs.has(schemaRef)) {
332 rememberGeneratedUuidContextOutputs(step, generatedContextNames);
333 continue;
334 }
335 // The missing-key negative vector explicitly suppresses both runner
336 // auto-injection and this authored-sample lint.
337 if (step.omit_idempotency_key === true) {
338 rememberGeneratedUuidContextOutputs(step, generatedContextNames);
339 continue;
340 }
341 const hasKey =
342 step.sample_request &&
343 typeof step.sample_request === 'object' &&
344 step.sample_request.idempotency_key !== undefined;
345 if (hasKey) {
346 const key = step.sample_request.idempotency_key;
347 if (!isGeneratedIdempotencyKey(key, generatedContextNames)) {
348 stableKeyViolations.push({
349 file: rel,
350 phase: phase.id,
351 step: step.id,
352 task: step.task,
353 key,
354 });
355 } else if (!duplicateGeneratedKeyAllowedFiles.has(rel)) {
356 const existing = generatedKeyUses.get(key);

Callers 1

walkFunction · 0.70

Calls 5

hasMethod · 0.80
getMethod · 0.45
setMethod · 0.45

Tested by

no test coverage detected