@workflow-manager/runner 0.1.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.
@@ -0,0 +1,39 @@
1
+ import fs from "node:fs";
2
+ import os from "node:os";
3
+ import path from "node:path";
4
+ function configRoot() {
5
+ const override = process.env.WORKFLOW_MANAGER_CONFIG_DIR;
6
+ if (override) {
7
+ return override;
8
+ }
9
+ if (process.platform === "win32") {
10
+ return path.join(process.env.APPDATA ?? path.join(os.homedir(), "AppData", "Roaming"), "workflow-manager");
11
+ }
12
+ return path.join(os.homedir(), ".config", "workflow-manager");
13
+ }
14
+ export function configFilePath() {
15
+ return path.join(configRoot(), "config.json");
16
+ }
17
+ export function loadRemoteConfig() {
18
+ const filePath = configFilePath();
19
+ if (!fs.existsSync(filePath)) {
20
+ return {};
21
+ }
22
+ const raw = fs.readFileSync(filePath, "utf-8");
23
+ const parsed = JSON.parse(raw);
24
+ return typeof parsed === "object" && parsed ? parsed : {};
25
+ }
26
+ export function saveRemoteConfig(config) {
27
+ const filePath = configFilePath();
28
+ fs.mkdirSync(path.dirname(filePath), { recursive: true });
29
+ fs.writeFileSync(filePath, `${JSON.stringify(config, null, 2)}\n`, "utf-8");
30
+ }
31
+ export function clearRemoteConfig() {
32
+ const filePath = configFilePath();
33
+ if (fs.existsSync(filePath)) {
34
+ fs.rmSync(filePath);
35
+ }
36
+ }
37
+ export function resolveAuthToken() {
38
+ return process.env.WORKFLOW_MANAGER_TOKEN ?? loadRemoteConfig().token;
39
+ }
@@ -0,0 +1,12 @@
1
+ import type { RunResult, WorkflowDefinition } from "../types.js";
2
+ import { type RunTelemetryPayload } from "./api.js";
3
+ interface RunTelemetryOptions {
4
+ definition: WorkflowDefinition;
5
+ sourceFilePath: string;
6
+ durationMs: number;
7
+ result?: RunResult;
8
+ failureReason?: string;
9
+ }
10
+ export declare function buildRunTelemetryPayload(options: RunTelemetryOptions): RunTelemetryPayload;
11
+ export declare function emitRunTelemetryBestEffort(options: RunTelemetryOptions): Promise<void>;
12
+ export {};
@@ -0,0 +1,69 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+ import { resolveAuthToken } from "./config.js";
4
+ import { trackRunTelemetry } from "./api.js";
5
+ function workflowSourceFormat(filePath) {
6
+ return path.extname(filePath).toLowerCase() === ".json" ? "json" : "markdown";
7
+ }
8
+ function cliVersion() {
9
+ try {
10
+ const packagePath = path.resolve(process.cwd(), "package.json");
11
+ const parsed = JSON.parse(fs.readFileSync(packagePath, "utf-8"));
12
+ return typeof parsed.version === "string" ? parsed.version : null;
13
+ }
14
+ catch {
15
+ return null;
16
+ }
17
+ }
18
+ export function buildRunTelemetryPayload(options) {
19
+ const { definition, sourceFilePath, durationMs, result, failureReason } = options;
20
+ const stepRuns = result?.stepRuns ?? [];
21
+ const succeededSteps = stepRuns.filter((step) => step.status === "succeeded").length;
22
+ const failedSteps = stepRuns.filter((step) => step.status === "failed").length;
23
+ const waitingSteps = stepRuns.filter((step) => step.status === "waiting_for_approval").length;
24
+ const cancelledSteps = stepRuns.filter((step) => step.status === "cancelled").length;
25
+ const retriedSteps = stepRuns.reduce((sum, step) => sum + Math.max(step.attempt - 1, 0), 0);
26
+ const totalSteps = definition.steps.length;
27
+ const successRatio = totalSteps === 0 ? 0 : succeededSteps / totalSteps;
28
+ const retryPenalty = totalSteps === 0 ? 0 : Math.min(retriedSteps / totalSteps, 1) * 20;
29
+ const waitingPenalty = waitingSteps > 0 ? 15 : 0;
30
+ const failurePenalty = failedSteps > 0 ? 35 : 0;
31
+ const effectivenessScore = Math.max(0, Math.min(100, Math.round(successRatio * 100 - retryPenalty - waitingPenalty - failurePenalty)));
32
+ const terminalState = (result?.status ?? "failed");
33
+ return {
34
+ workflowKey: definition.key,
35
+ workflowTitle: definition.title,
36
+ runId: result?.runId ?? `failed-preflight:${definition.key}`,
37
+ terminalState,
38
+ totalSteps,
39
+ succeededSteps,
40
+ failedSteps,
41
+ waitingSteps,
42
+ cancelledSteps,
43
+ retriedSteps,
44
+ eventCount: result?.events.length ?? 0,
45
+ durationMs,
46
+ effectivenessScore,
47
+ outputKeys: Object.keys(result?.outputs ?? {}),
48
+ sourceName: path.basename(sourceFilePath),
49
+ sourceFormat: workflowSourceFormat(sourceFilePath),
50
+ cliVersion: cliVersion(),
51
+ failureReason: failureReason ?? (terminalState === "failed" ? "run failed" : null),
52
+ metadata: {
53
+ workflowObjectives: definition.objectives ?? [],
54
+ stepKeys: definition.steps.map((step) => step.key),
55
+ outputCount: Object.keys(result?.outputs ?? {}).length,
56
+ },
57
+ };
58
+ }
59
+ export async function emitRunTelemetryBestEffort(options) {
60
+ if (!resolveAuthToken()) {
61
+ return;
62
+ }
63
+ try {
64
+ await trackRunTelemetry(buildRunTelemetryPayload(options));
65
+ }
66
+ catch (error) {
67
+ console.warn(`Telemetry warning: ${error.message}`);
68
+ }
69
+ }
@@ -0,0 +1,7 @@
1
+ export interface RemoteProfileSummary {
2
+ userId: string;
3
+ username: string | null;
4
+ displayName: string | null;
5
+ authMethod: string;
6
+ scopes: string[];
7
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,122 @@
1
+ export type WorkflowRunStatus = "queued" | "running" | "waiting_for_approval" | "paused" | "succeeded" | "failed" | "cancelled";
2
+ export type StepRunStatus = "pending" | "runnable" | "running" | "waiting_for_approval" | "succeeded" | "failed" | "cancelled";
3
+ export type StepKind = "task" | "approval" | "system";
4
+ export type NodeType = "AGENT" | "HUMAN" | "SYSTEM";
5
+ export type ExecutionStatus = "SUCCESS" | "QA_REJECTED" | "YIELD_EXTERNAL" | "FAILED";
6
+ export type QaAction = "PROCEED" | "RETRY_CURRENT" | "ROLLBACK_PREVIOUS" | "RESTART_ALL";
7
+ export type ValidationMode = "none" | "human" | "external";
8
+ export type AdapterKey = "mock" | "opencode" | "codex" | "claude-code";
9
+ export interface RetryPolicy {
10
+ maxAttempts?: number;
11
+ }
12
+ export interface ValidationSpec {
13
+ mode?: ValidationMode;
14
+ required?: boolean;
15
+ autoConfirm?: boolean;
16
+ confirmerPolicy?: string;
17
+ }
18
+ export interface TaskInitConfig {
19
+ context?: Record<string, unknown> | string;
20
+ skills?: string[];
21
+ mcps?: string[];
22
+ systemPrompts?: string[];
23
+ model?: string;
24
+ }
25
+ export interface StepDefinition {
26
+ key: string;
27
+ kind: StepKind;
28
+ title?: string;
29
+ objective?: string;
30
+ dependsOn?: string[];
31
+ timeoutSec?: number;
32
+ retryPolicy?: RetryPolicy;
33
+ validation?: ValidationSpec;
34
+ taskSpec?: {
35
+ adapterKey?: AdapterKey;
36
+ capabilityRequirements?: string[];
37
+ init?: TaskInitConfig;
38
+ payload?: Record<string, unknown>;
39
+ };
40
+ approvalSpec?: {
41
+ approverPolicy?: string;
42
+ autoApprove?: boolean;
43
+ validation?: ValidationSpec;
44
+ };
45
+ }
46
+ export interface WorkflowDefinition {
47
+ key: string;
48
+ title: string;
49
+ description?: string;
50
+ objectives?: string[];
51
+ inputSchema?: Record<string, unknown>;
52
+ outputSchema?: Record<string, unknown>;
53
+ defaultRetryPolicy?: RetryPolicy;
54
+ steps: StepDefinition[];
55
+ }
56
+ export interface InputEnvelope {
57
+ global_context: {
58
+ workflow_id: string;
59
+ primary_objective: string;
60
+ workflow_objectives: string[];
61
+ global_state: Record<string, unknown>;
62
+ };
63
+ step_context: {
64
+ step_id: string;
65
+ step_objective: string;
66
+ previous_output: Record<string, unknown>;
67
+ assigned_node_type: NodeType;
68
+ };
69
+ priming_configuration: {
70
+ required_skills: string[];
71
+ mcp_endpoints: string[];
72
+ system_prompts: string[];
73
+ context?: Record<string, unknown> | string;
74
+ adapter?: AdapterKey;
75
+ model?: string;
76
+ };
77
+ }
78
+ export interface OutputEnvelope {
79
+ step_id: string;
80
+ execution_status: ExecutionStatus;
81
+ qa_routing: {
82
+ action: QaAction;
83
+ feedback_reason: string;
84
+ };
85
+ mutated_payload: Record<string, unknown>;
86
+ metadata: {
87
+ execution_time_ms: number;
88
+ external_intervention_required: boolean;
89
+ intervention_details?: Record<string, unknown>;
90
+ };
91
+ }
92
+ export interface StepRun {
93
+ stepKey: string;
94
+ status: StepRunStatus;
95
+ attempt: number;
96
+ confirmed: boolean;
97
+ output?: Record<string, unknown>;
98
+ }
99
+ export interface RunResult {
100
+ runId: string;
101
+ status: WorkflowRunStatus;
102
+ outputs: Record<string, unknown>;
103
+ stepRuns: StepRun[];
104
+ events: RunEvent[];
105
+ }
106
+ export interface RunOptions {
107
+ objective?: string;
108
+ input?: Record<string, unknown>;
109
+ actor?: string;
110
+ confirmations?: string[];
111
+ autoConfirmAll?: boolean;
112
+ }
113
+ export interface RunEvent {
114
+ id: string;
115
+ runId: string;
116
+ stepRunId?: string;
117
+ type: "run.created" | "run.started" | "run.waiting_for_approval" | "step.runnable" | "step.claimed" | "step.execution_started" | "step.execution_finished" | "step.waiting_for_approval" | "approval.resolved" | "step.retried" | "step.confirmed" | "run.completed" | "run.failed" | "run.cancelled";
118
+ sequenceNumber: number;
119
+ occurredAt: string;
120
+ actor: string;
121
+ payload: Record<string, unknown>;
122
+ }
package/dist/types.js ADDED
@@ -0,0 +1 @@
1
+ export {};
package/man/wfm.1 ADDED
@@ -0,0 +1,96 @@
1
+ .TH WFM 1 "April 2026" "@workflow-manager/runner" "User Commands"
2
+ .SH NAME
3
+ wfm \- run markdown or json workflows from the CLI
4
+ .SH SYNOPSIS
5
+ .B wfm
6
+ .I command
7
+ [options]
8
+ .SH DESCRIPTION
9
+ wfm parses a workflow definition file, validates it, and executes
10
+ it with deterministic in-memory orchestration.
11
+
12
+ Workflow files can be Markdown with YAML frontmatter or JSON.
13
+ .SH COMMANDS
14
+ .TP
15
+ .B questions
16
+ Print discovery questions used to design a workflow.
17
+ .TP
18
+ .B scaffold [path] [--format markdown|json]
19
+ Create a starter workflow file. Format defaults to markdown unless the output
20
+ path ends in .json.
21
+ .TP
22
+ .B validate <workflow.md|workflow.json>
23
+ Validate workflow structure and report schema errors.
24
+ .TP
25
+ .B run <workflow.md|workflow.json> [--input input.json] [--objective text] [--confirm list] [--auto-confirm-all]
26
+ Run the workflow and print a JSON result with events and per-step outputs.
27
+ .TP
28
+ .B auth <login|whoami|logout> [--token value]
29
+ Manage remote registry authentication for CLI publish and pull flows.
30
+ .TP
31
+ .B publish <workflow.md|workflow.json> [--slug slug] [--title text] [--description text] [--visibility public|private] [--version label] [--tag a,b] [--draft]
32
+ Publish a validated local workflow to the remote registry.
33
+ .TP
34
+ .B pull <owner/slug> [--version label] [--output path]
35
+ Download a remote workflow and write it to a local file.
36
+ .TP
37
+ .B search [query]
38
+ Search public workflows from the remote registry.
39
+ .TP
40
+ .B remote info <owner/slug>
41
+ Show metadata and source information for a remote workflow.
42
+ .TP
43
+ .B man
44
+ Open this man page.
45
+ .SH RUN OPTIONS
46
+ .TP
47
+ .B --input <path>
48
+ JSON file merged into global workflow input state.
49
+ .TP
50
+ .B --objective <text>
51
+ Override the default run objective.
52
+ .TP
53
+ .B --confirm <stepA,stepB:human,...>
54
+ Provide explicit confirmations for steps that require validation.
55
+ .TP
56
+ .B --auto-confirm-all
57
+ Bypass confirmation gating for all steps.
58
+ .SH EXAMPLES
59
+ .TP
60
+ Validate markdown workflow:
61
+ .B wfm validate ./example-workflow.md
62
+ .TP
63
+ Validate json workflow:
64
+ .B wfm validate ./example-workflow.json
65
+ .TP
66
+ Scaffold json workflow file:
67
+ .B wfm scaffold ./new-workflow.json --format json
68
+ .TP
69
+ Authenticate with a CLI token:
70
+ .B wfm auth login --token wm_exampletoken
71
+ .TP
72
+ Publish a workflow:
73
+ .B wfm publish ./example-workflow.json --visibility public --tag example,automation
74
+ .TP
75
+ Pull a remote workflow:
76
+ .B wfm pull alice/remote-bunny --output ./remote-bunny.json
77
+ .TP
78
+ Search the remote registry:
79
+ .B wfm search bunny
80
+ .TP
81
+ Run with explicit confirmations:
82
+ .B wfm run ./example-workflow.json --confirm discover:human,qa_gate:human
83
+ .SH FILES
84
+ .TP
85
+ .B man/wfm.1
86
+ The manual page source shipped with this repository.
87
+ .SH EXIT STATUS
88
+ .TP
89
+ .B 0
90
+ Successful command execution.
91
+ .TP
92
+ .B 1
93
+ Validation or runtime error.
94
+ .TP
95
+ .B 2
96
+ Run completed in non-success terminal status.
package/package.json ADDED
@@ -0,0 +1,65 @@
1
+ {
2
+ "name": "@workflow-manager/runner",
3
+ "version": "0.1.0",
4
+ "description": "CLI runner for in-memory and markdown workflow orchestration using ATEP-like envelopes",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "bin": {
8
+ "wfm": "dist/index.js"
9
+ },
10
+ "publishConfig": {
11
+ "access": "public"
12
+ },
13
+ "files": [
14
+ "dist/",
15
+ "man/",
16
+ "skills/",
17
+ "README.md"
18
+ ],
19
+ "scripts": {
20
+ "build": "tsc -p tsconfig.json",
21
+ "build:bin": "bun build ./src/index.ts --compile --outfile ./dist/wfm",
22
+ "build:bin:macos": "bun build ./src/index.ts --compile --target bun-darwin-arm64 --outfile ./dist/wfm-macos-arm64",
23
+ "build:bin:linux": "bun build ./src/index.ts --compile --target bun-linux-x64 --outfile ./dist/wfm-linux-x64",
24
+ "build:bin:windows": "bun build ./src/index.ts --compile --target bun-windows-x64 --outfile ./dist/wfm-windows-x64.exe",
25
+ "build:bin:all": "bun run build:bin:macos && bun run build:bin:linux && bun run build:bin:windows",
26
+ "man": "man ./man/wfm.1",
27
+ "test:unit": "bun test tests/parser.test.ts tests/engine.test.ts tests/mockExecutor.test.ts tests/opencodeExecutor.test.ts tests/remote.test.ts tests/run-telemetry.test.ts tests/supabase-functions.test.ts tests/supabase-ops.test.ts tests/remote-registry-app.test.ts",
28
+ "test:e2e": "bun test tests/story-workflow.e2e.test.ts tests/opencode-real.e2e.test.ts",
29
+ "test:e2e:real": "WORKFLOW_MANAGER_REAL_OPENCODE=1 bun test tests/opencode-real.e2e.test.ts",
30
+ "test": "bun test",
31
+ "dev": "bun run ./src/index.ts",
32
+ "package:check": "npm pack --dry-run",
33
+ "prepack": "bun run build",
34
+ "supabase:start": "supabase start",
35
+ "supabase:stop": "supabase stop",
36
+ "supabase:status": "supabase status",
37
+ "supabase:db:reset": "supabase db reset",
38
+ "supabase:functions:deploy": "supabase functions deploy create-cli-token --project-ref whairnylpdvxxgbygbzu --use-api --no-verify-jwt && supabase functions deploy auth-whoami --project-ref whairnylpdvxxgbygbzu --use-api --no-verify-jwt && supabase functions deploy list-cli-tokens --project-ref whairnylpdvxxgbygbzu --use-api --no-verify-jwt && supabase functions deploy manage-workflow --project-ref whairnylpdvxxgbygbzu --use-api --no-verify-jwt && supabase functions deploy refresh-workflow-stats --project-ref whairnylpdvxxgbygbzu --use-api --no-verify-jwt && supabase functions deploy revoke-cli-token --project-ref whairnylpdvxxgbygbzu --use-api --no-verify-jwt && supabase functions deploy publish-workflow --project-ref whairnylpdvxxgbygbzu --use-api --no-verify-jwt && supabase functions deploy pull-workflow --project-ref whairnylpdvxxgbygbzu --use-api --no-verify-jwt && supabase functions deploy search-workflows --project-ref whairnylpdvxxgbygbzu --use-api --no-verify-jwt && supabase functions deploy workflow-analytics --project-ref whairnylpdvxxgbygbzu --use-api --no-verify-jwt && supabase functions deploy track-run-telemetry --project-ref whairnylpdvxxgbygbzu --use-api --no-verify-jwt && supabase functions deploy workflow-run-insights --project-ref whairnylpdvxxgbygbzu --use-api --no-verify-jwt",
39
+ "remote-registry:dev": "bun --cwd apps/remote-registry dev",
40
+ "remote-registry:build": "bun --cwd apps/remote-registry build",
41
+ "docs:dev": "vitepress dev doc",
42
+ "docs:build": "vitepress build doc",
43
+ "docs:preview": "vitepress preview doc"
44
+ },
45
+ "keywords": [
46
+ "workflow",
47
+ "orchestration",
48
+ "cli",
49
+ "atep",
50
+ "agent-skills",
51
+ "claude-code",
52
+ "opencode",
53
+ "tanstack-intent"
54
+ ],
55
+ "license": "MIT",
56
+ "dependencies": {
57
+ "gray-matter": "^4.0.3"
58
+ },
59
+ "devDependencies": {
60
+ "@types/node": "^24.6.0",
61
+ "bun-types": "^1.3.0",
62
+ "typescript": "^5.9.2",
63
+ "vitepress": "^1.5.0"
64
+ }
65
+ }
@@ -0,0 +1,63 @@
1
+ # workflow-manager skills
2
+
3
+ `@workflow-manager/runner` now ships its TanStack Intent-compatible skills in the main npm package.
4
+
5
+ The first bundled skill is `workflow-manager-cli`, which teaches agents how to:
6
+
7
+ - design workflow definitions
8
+ - scaffold Markdown or JSON workflows
9
+ - validate and run workflows safely
10
+ - authenticate against the remote registry
11
+ - publish, search, and pull shared workflows
12
+
13
+ ## Install
14
+
15
+ Install the main package in the project where you want the CLI and skill available:
16
+
17
+ ```bash
18
+ npm install @workflow-manager/runner
19
+ ```
20
+
21
+ Then use TanStack Intent to discover and map the shipped skill into your agent configuration:
22
+
23
+ ```bash
24
+ npx @tanstack/intent@latest list
25
+ npx @tanstack/intent@latest install
26
+ ```
27
+
28
+ Intent writes task-to-skill mappings into `AGENTS.md`-style config files and points them at the installed package path under `node_modules/@workflow-manager/runner/skills/...`.
29
+
30
+ ## Packaged skill
31
+
32
+ - skill path: `skills/workflow-manager-cli/SKILL.md`
33
+ - package keyword: `tanstack-intent`
34
+ - published with: the root `@workflow-manager/runner` npm package
35
+
36
+ ## Local development
37
+
38
+ From the repository root:
39
+
40
+ ```bash
41
+ npm pack --dry-run
42
+ ls skills/workflow-manager-cli
43
+ ```
44
+
45
+ ## Publish
46
+
47
+ Publish from the repository root so the CLI runner and `skills/` ship together:
48
+
49
+ ```bash
50
+ npm publish
51
+ ```
52
+
53
+ Before publishing, verify the package contents:
54
+
55
+ ```bash
56
+ npm pack --dry-run
57
+ ```
58
+
59
+ ## Package layout
60
+
61
+ - `skills/workflow-manager-cli/SKILL.md`: TanStack Intent skill entrypoint
62
+ - `skills/workflow-manager-cli/README.md`: local notes for contributors
63
+ - `package.json`: package metadata, published files, and `tanstack-intent` keyword
@@ -0,0 +1,11 @@
1
+ # workflow-manager-cli skill
2
+
3
+ This skill ships inside the root `@workflow-manager/runner` npm package.
4
+
5
+ It is designed for TanStack Intent discovery and should stay aligned with the CLI behavior documented in:
6
+
7
+ - `README.md`
8
+ - `src/index.ts`
9
+ - `src/parser.ts`
10
+ - `src/engine.ts`
11
+ - `src/remote/commands.ts`
@@ -0,0 +1,111 @@
1
+ ---
2
+ name: @workflow-manager/runner/cli
3
+ description: >
4
+ Load this skill when working with the wfm CLI from @workflow-manager/runner, authoring or
5
+ validating workflow definitions, configuring step skills and adapters, or
6
+ publishing workflows to the remote registry. Covers questions, scaffold,
7
+ validate, run, auth, publish, pull, search, and remote info.
8
+ type: core
9
+ library: @workflow-manager/runner
10
+ library_version: "0.1.0"
11
+ sources:
12
+ - "navio/workflow-manager:README.md"
13
+ - "navio/workflow-manager:src/index.ts"
14
+ - "navio/workflow-manager:src/parser.ts"
15
+ - "navio/workflow-manager:src/engine.ts"
16
+ - "navio/workflow-manager:src/remote/commands.ts"
17
+ ---
18
+
19
+ # wfm CLI
20
+
21
+ Use this skill when you need to create or operate `workflow-manager` workflows from the terminal with `wfm`.
22
+
23
+ ## When to use this skill
24
+
25
+ Use it when the user wants to:
26
+
27
+ - scaffold a new workflow definition
28
+ - validate or run a workflow file
29
+ - configure approvals, retry policy, or adapter initialization
30
+ - publish a workflow to the remote registry
31
+ - search for or pull a shared workflow
32
+ - understand the difference between Markdown and JSON workflow formats
33
+
34
+ ## Core workflow
35
+
36
+ Use this sequence unless the user asks for a narrower task:
37
+
38
+ 1. Discover the workflow intent with `wfm questions`
39
+ 2. Scaffold a starter file with `wfm scaffold`
40
+ 3. Edit the workflow definition
41
+ 4. Validate the file with `wfm validate`
42
+ 5. Execute it with `wfm run`
43
+ 6. If needed, authenticate and publish with the remote registry commands
44
+
45
+ ## Local workflow commands
46
+
47
+ ```bash
48
+ wfm questions
49
+
50
+ wfm scaffold ./example-workflow.md
51
+ wfm scaffold ./example-workflow.json --format json
52
+
53
+ wfm validate ./example-workflow.md
54
+ wfm validate ./example-workflow.json
55
+
56
+ wfm run ./example-workflow.md --confirm discover,qa_gate:human
57
+ wfm run ./example-workflow.json --auto-confirm-all
58
+ ```
59
+
60
+ ## Remote registry commands
61
+
62
+ ```bash
63
+ wfm auth login --token <token>
64
+ wfm auth whoami
65
+ wfm auth logout
66
+
67
+ wfm search bunny
68
+ wfm remote info alice/remote-bunny
69
+ wfm publish ./example-workflow.json --visibility public --tag storytelling,example
70
+ wfm pull alice/remote-bunny --output ./remote-bunny.json
71
+ ```
72
+
73
+ ## Skill guidance
74
+
75
+ - Prefer `validate` before `run` or `publish`
76
+ - Keep `runWorkflow(...)` behavior registry-agnostic; registry operations belong in the CLI remote commands
77
+ - Use Markdown workflows when the user wants editable frontmatter plus notes
78
+ - Use JSON workflows when the user wants machine-generated or strongly structured files
79
+ - Use `--auto-confirm-all` only when the workflow is intentionally non-interactive
80
+ - When publishing, preserve the source format the user authored
81
+
82
+ ## Workflow authoring checklist
83
+
84
+ - Set stable `key` and `title` values
85
+ - Define clear step `objective` text
86
+ - Add `dependsOn` relationships explicitly
87
+ - Set validation mode per step (`none`, `human`, `external`)
88
+ - Configure adapter initialization under `taskSpec.init`
89
+ - Use stable step keys because tests and docs may refer to them
90
+
91
+ ## Adapter and validation notes
92
+
93
+ - Supported adapters include `mock`, `opencode`, `codex`, and `claude-code`
94
+ - Human approvals should stay explicit in workflow definitions
95
+ - External validation should be deterministic where possible
96
+ - Use the mock adapter for fast tests and scaffolding flows
97
+
98
+ ## Recommended project references
99
+
100
+ - `src/index.ts`: CLI command entrypoint
101
+ - `src/parser.ts`: Markdown and JSON parsing plus validation
102
+ - `src/engine.ts`: orchestration loop
103
+ - `src/remote/commands.ts`: auth, publish, pull, search, and remote info commands
104
+ - `tests/`: unit and e2e coverage for workflow behavior
105
+
106
+ ## Typical troubleshooting
107
+
108
+ - If validation fails, inspect the reported schema or dependency error before running again
109
+ - If `publish` fails, confirm the user is logged in with `wfm auth whoami`
110
+ - If remote calls fail in the browser, verify the remote registry app has valid Supabase `VITE_*` environment variables
111
+ - If a real adapter test fails, confirm the underlying external CLI is installed and available on `PATH`