원클릭으로
awaitly-analyze
Static analysis for awaitly workflows - complexity, paths, visualization. Optimized for coding agents.
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
메뉴
Static analysis for awaitly workflows - complexity, paths, visualization. Optimized for coding agents.
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
SOC 직업 분류 기준
Core patterns for awaitly: typed async workflows with automatic error inference. Use when writing workflows, migrating from try/catch, or debugging Result types.
Workflow visualization patterns for awaitly. Use when wiring event capture, renderers, collectors, time-travel, and export URLs in code.
| name | awaitly-analyze |
| description | Static analysis for awaitly workflows - complexity, paths, visualization. Optimized for coding agents. |
| user-invocable | true |
Use awaitly-analyze to understand workflow structure without execution. Entrypoint: analyze(path) then .single(), .named(name), or .all() to get IR; then use render/generate APIs.
analyze(filePath) (string path to a .ts file). Returns a selection API; MUST call one of .single(), .named('workflowName'), .singleOrNull(), .firstOrNull(), or .all() to obtain IR (or null).analyze() returns IR directly. It returns AnalyzeResult with .single(), .named(), .all(), .singleOrNull(), .firstOrNull().MermaidOptions, PathGeneratorOptions), consult package types.awaitly-analyze package types or README before using it..single() etc.) as the first argument to functions like renderStaticMermaid(ir), generatePaths(ir), calculateComplexity(ir), validateStrict(ir).analyzeWorkflowGraph([...paths]) takes file paths (strings), not IR.renderStatic*, generate*, calculate*, validate* functions take IR, not paths.analyzeWorkflowGraph. MUST NOT pass file paths to IR functions (e.g. renderStaticMermaid, generatePaths).step(fn, opts) without id); they produce stepId: "<missing>" and strict validation diagnostics.step.workflow, step.withFallback, and step.withResource (step ID from first argument). For step.workflow, getters that call childWorkflow.run(...) are traversed so child workflow refs are detected and emitted as workflow-ref nodes in diagrams.import { analyze } from 'awaitly-analyze';
// Single workflow in file (throws if not exactly 1)
const ir = analyze('./workflow.ts').single();
// Named workflow (when file has multiple)
const ir = analyze('./file.ts').named('checkoutWorkflow');
// All workflows in file
const workflows = analyze('./file.ts').all();
// Safe: null if none or multiple
const ir = analyze('./file.ts').singleOrNull();
const ir = analyze('./file.ts').firstOrNull();
import { renderStaticMermaid, renderEnhancedMermaid } from 'awaitly-analyze';
const diagram = renderStaticMermaid(ir, { direction: 'LR' });
const enhanced = renderEnhancedMermaid(ir, { showDataFlow: true, showErrors: true });
import { generatePaths, calculateComplexity, assessComplexity, formatComplexitySummary } from 'awaitly-analyze';
const paths = generatePaths(ir);
const metrics = calculateComplexity(ir);
const assessment = assessComplexity(metrics);
console.log(formatComplexitySummary(metrics, assessment));
const ir = analyze('./workflow.ts').singleOrNull();
if (!ir) {
console.error('No single workflow found');
process.exit(1);
}
const paths = generatePaths(ir);
Run strict validation before generating diagrams or paths; fail fast if the workflow has step-ID or other strict violations.
import { analyze, validateStrict, formatDiagnostics } from 'awaitly-analyze';
const ir = analyze('./workflow.ts').singleOrNull();
if (!ir) throw new Error('No single workflow found');
const strict = validateStrict(ir);
if (!strict.valid) {
console.error(formatDiagnostics(strict));
process.exit(1);
}
// Now safe to generatePaths(ir), renderStaticMermaid(ir), etc.
| See | Do instead |
|---|---|
Passing a file path to renderStaticMermaid or generatePaths | Get IR first: const ir = analyze(path).single(); then renderStaticMermaid(ir), generatePaths(ir). |
Assuming analyze(path) returns IR | Call .single() or .named(name) or .all() on the result. |
Inventing an export (e.g. renderWorkflow) | Use only exports listed here or in package types: renderStaticMermaid, renderEnhancedMermaid, renderRailwayMermaid, renderStaticJSON, diffWorkflows, renderDiffMarkdown, renderDiffJSON, renderDiffMermaid, etc. |
Passing a file path to diffWorkflows | Get IR first: const before = analyze(path1).single(); const after = analyze(path2).single(); then diffWorkflows(before, after). |
Passing IR to renderDiffMarkdown | Pass a WorkflowDiff from diffWorkflows(before, after). |
Omitting after IR from renderDiffMermaid | First arg is after IR: renderDiffMermaid(afterIR, diff, options). |
analyze(filePath) — path is a string to a .ts file..single() — returns IR; throws if not exactly one workflow..named('name') — returns IR for that workflow name; throws if not found..all() — returns array of IR..singleOrNull() / .firstOrNull() — returns IR or null; use when you want safe access.Prefer .singleOrNull() or .firstOrNull() in tooling/scripts; use .single() only when you expect exactly one workflow and want a hard failure on mismatch.
For options (e.g. TS config, globs), consult package types (AnalyzeResult, analyze).
| Need | Use | Notes |
|---|---|---|
| Mermaid diagram | renderStaticMermaid(ir) or renderEnhancedMermaid(ir, options) | First arg is IR. |
| Railway diagram | renderRailwayMermaid(ir, options?) | Linear happy path with ok/err branching. First arg is IR. |
| JSON | renderStaticJSON(ir, { pretty: true }) | For machine consumption. |
| Test matrix (markdown) | generateTestMatrix(paths) then formatTestMatrixMarkdown(matrix) | Paths from generatePaths(ir). |
| Test matrix (code) | generateTestMatrix(paths) then formatTestMatrixAsCode(matrix, { testRunner, workflowName }) | Generates vitest/jest/mocha test stubs. |
| Path stats | calculatePathStatistics(paths) | Paths from generatePaths(ir). |
| Diff (markdown) | renderDiffMarkdown(diff, options?) | First arg is WorkflowDiff. |
| Diff (JSON) | renderDiffJSON(diff, { pretty: true }) | First arg is WorkflowDiff. |
| Diff (Mermaid) | renderDiffMermaid(afterIR, diff, options?) | First arg is after IR, second is WorkflowDiff. |
For options (direction, showDataFlow, etc.), consult package types (MermaidOptions, EnhancedMermaidOptions, JSONRenderOptions, RailwayOptions, DiffMarkdownOptions, DiffMermaidOptions).
generatePaths(ir) with IR (not file path).filterPaths(paths, { mustIncludeStep, noLoops, maxLength }) when needed.calculatePathStatistics(paths) for counts and stats.calculateComplexity(ir) returns metrics (cyclomatic, cognitive, path count, max depth).assessComplexity(metrics) returns assessment; formatComplexitySummary(metrics, assessment) for human-readable output.validateStrict(ir, options) returns a validation result; use formatDiagnostics(result) for human-readable output.step(fn, opts) or missing step IDs trigger diagnostics. For full rule list and options, consult package types (StrictValidationResult, StrictRule).buildDataFlowGraph(ir) → graph; validateDataFlow(graph) for validation.analyzeErrorFlow(ir) → error flow; formatErrorSummary(errorFlow) for readable output.For types and options, consult package types (DataFlowGraph, ErrorFlowAnalysis).
analyzeWorkflowGraph([path1, path2, ...]) — array of file paths (not IR).renderGraphMermaid(graph) for diagram.Generate linear happy-path Mermaid flowcharts with ok/err branching per step.
import { renderRailwayMermaid } from 'awaitly-analyze';
const diagram = renderRailwayMermaid(ir);
const lrDiagram = renderRailwayMermaid(ir, { direction: 'LR' });
const detailed = renderRailwayMermaid(ir, {
stepLabel: 'callee', // 'callee' | 'stepId' | 'description'
showRetry: true,
showTimeout: true,
showKeys: true,
includeInferredErrors: true, // default: true — show errors inferred from AsyncResult return types
});
// Hide inferred errors, only show explicitly declared ones
const explicitOnly = renderRailwayMermaid(ir, { includeInferredErrors: false });
First arg is IR (not file path). Options: direction ('LR' | 'TD'), stepLabel, showRetry, showTimeout, showKeys, useNodeIds, includeInferredErrors (default: true), styles.
Compare two workflow IR snapshots to detect step additions, removals, renames, moves, and structural changes.
import { analyze, diffWorkflows, renderDiffMarkdown, renderDiffJSON, renderDiffMermaid } from 'awaitly-analyze';
const before = analyze('./v1.ts').single();
const after = analyze('./v2.ts').single();
const diff = diffWorkflows(before, after);
// diff.summary: { added, removed, renamed, moved, unchanged, structuralChanges, hasRegressions }
const markdown = renderDiffMarkdown(diff);
const json = renderDiffJSON(diff, { pretty: true });
const mermaid = renderDiffMermaid(after, diff, { direction: 'LR' });
const diff = diffWorkflows(before, after, {
detectRenames: true, // default: true — match unmatched steps by callee
regressionMode: false, // default: false — when true, removed steps flag hasRegressions
});
// Markdown
renderDiffMarkdown(diff, { showUnchanged: true, title: 'My Diff' });
// Mermaid (requires after IR as first arg)
renderDiffMermaid(after, diff, { showRemovedSteps: true, direction: 'TD' });
diffWorkflows(before, after) — not file paths.after IR as first arg to renderDiffMermaid(after, diff, options).renderDiffMarkdown takes a WorkflowDiff, not IR.# Static analysis (default: generates mermaid diagram + types file)
npx awaitly-analyze ./workflow.ts
# Output formats
npx awaitly-analyze ./workflow.ts --format=json
npx awaitly-analyze ./workflow.ts --format=markdown
# Control outputs
npx awaitly-analyze ./workflow.ts --types # Generate types file (default: on)
npx awaitly-analyze ./workflow.ts --no-types # Skip types file generation
npx awaitly-analyze ./workflow.ts --test # Generate test stubs (default: off)
npx awaitly-analyze ./workflow.ts --test --test-runner=jest # Test runner: vitest (default), jest, mocha
npx awaitly-analyze ./workflow.ts --errors # Show error nodes in diagrams (default: on)
npx awaitly-analyze ./workflow.ts --no-errors # Hide error nodes
# Diagram options
npx awaitly-analyze ./workflow.ts --direction LR
npx awaitly-analyze ./workflow.ts --keys
npx awaitly-analyze ./workflow.ts --railway
# Output files
npx awaitly-analyze ./workflow.ts -o # Write adjacent .workflow.md
npx awaitly-analyze ./workflow.ts --html # Generate interactive HTML
npx awaitly-analyze ./workflow.ts --write-dsl # Write .awaitly/dsl/ folder
# Diff: two local files
npx awaitly-analyze --diff v1.ts v2.ts
# Diff: single file vs HEAD
npx awaitly-analyze --diff src/workflow.ts
# Diff: git ref vs local
npx awaitly-analyze --diff main:src/workflow.ts src/workflow.ts
# Diff: GitHub PR (all .ts files)
npx awaitly-analyze --diff gh:#123
# Diff: GitHub PR scoped to one file
npx awaitly-analyze --diff gh:#123 src/wf.ts
# Diff with regression detection (removed steps flagged)
npx awaitly-analyze --diff v1.ts v2.ts --regression
# Diff output formats
npx awaitly-analyze --diff v1.ts v2.ts --format json
npx awaitly-analyze --diff v1.ts v2.ts --format mermaid --direction LR
Do not invent CLI flags; consult package CLI help or README for supported options.
The analyzer produces a static IR tree. Common node types include: workflow, step, saga-step, sequence, parallel, race, conditional, decision, switch, loop, stream, workflow-ref (non-exhaustive; consult package types). Step nodes have a string step ID (or <missing> if legacy form). When step options include metadata, step nodes may also have optional fields: intent, domain, owner, tags, stateChanges, emits, calls, errorMeta (see schema). MUST NOT assume presence or shape of a .type string at runtime; consult types for the current schema.