@echelon-foundry/design-system 0.3.0 → 0.4.0-main.222.1

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.
Files changed (76) hide show
  1. package/README.md +29 -0
  2. package/contracts/diagram-presentation.json +109 -0
  3. package/contracts/machine-operability.json +48 -0
  4. package/contracts/workflow-capabilities.json +25 -0
  5. package/dist/all.css +175 -3
  6. package/dist/build-metrics.json +33 -5
  7. package/dist/components.css +173 -3
  8. package/dist/foundations.css +2 -0
  9. package/dist/marketing/forma-all.css +176 -4
  10. package/dist/marketing/forma-echelon-marketing.css +3 -1
  11. package/dist/marketing/forma-marketing-theme-echelon.css +1 -1
  12. package/dist/marketing/forma-marketing.css +3 -1
  13. package/dist/marketing/forma-marketing.manifest.json +9 -9
  14. package/dist/marketing/forma-marketing.sha256 +4 -4
  15. package/dist/patterns/bounded-overflow.html +9 -0
  16. package/dist/patterns/button.html +5 -0
  17. package/dist/patterns/container.html +6 -0
  18. package/dist/patterns/date-time-field.html +5 -0
  19. package/dist/patterns/grid.html +5 -0
  20. package/dist/patterns/image-choice.html +2 -2
  21. package/dist/patterns/key-value-list.html +5 -0
  22. package/dist/patterns/section.html +4 -0
  23. package/dist/patterns/skip-link.html +6 -0
  24. package/dist/patterns/spatial-canvas.html +2 -2
  25. package/dist/patterns/split.html +12 -0
  26. package/dist/patterns/surface.html +4 -0
  27. package/dist/patterns/text-field.html +5 -0
  28. package/dist/patterns/text-roles.html +7 -0
  29. package/dist/patterns/textarea.html +5 -0
  30. package/dist/patterns/visually-hidden.html +4 -0
  31. package/docs/MARKETING-SITES.md +1 -1
  32. package/docs/workflow/EMBEDDING.md +148 -0
  33. package/docs/workflow/EXTERNAL-PRODUCERS.md +34 -0
  34. package/docs/workflow/FORMAT.md +196 -0
  35. package/docs/workflow/RENDERING.md +90 -0
  36. package/docs/workflow/REQUIREMENTS-AUDIT-2026-10-01.md +55 -0
  37. package/docs/workflow/VALIDATION.md +91 -0
  38. package/examples/workflows/fixtures.json +101 -0
  39. package/examples/workflows/forma/workflows/accessible.forma-workflow.json +90 -0
  40. package/examples/workflows/forma/workflows/branching.forma-workflow.json +91 -0
  41. package/examples/workflows/forma/workflows/branded.forma-workflow.json +85 -0
  42. package/examples/workflows/forma/workflows/color-mapping.forma-workflow.json +111 -0
  43. package/examples/workflows/forma/workflows/colored.forma-workflow.json +131 -0
  44. package/examples/workflows/forma/workflows/edge-metadata.forma-workflow.json +66 -0
  45. package/examples/workflows/forma/workflows/embedded-edit.forma-workflow.json +117 -0
  46. package/examples/workflows/forma/workflows/embedded-view.forma-workflow.json +93 -0
  47. package/examples/workflows/forma/workflows/extensions.forma-workflow.json +90 -0
  48. package/examples/workflows/forma/workflows/groups.forma-workflow.json +89 -0
  49. package/examples/workflows/forma/workflows/interactive-export.forma-workflow.json +62 -0
  50. package/examples/workflows/forma/workflows/minimal.forma-workflow.json +17 -0
  51. package/examples/workflows/forma/workflows/mobile.forma-workflow.json +80 -0
  52. package/examples/workflows/forma/workflows/multi-step.forma-workflow.json +82 -0
  53. package/examples/workflows/forma/workflows/no-layout.forma-workflow.json +90 -0
  54. package/examples/workflows/forma/workflows/node-metadata.forma-workflow.json +80 -0
  55. package/examples/workflows/forma/workflows/runtime-ports.forma-workflow.json +118 -0
  56. package/examples/workflows/forma/workflows/static-export.forma-workflow.json +77 -0
  57. package/examples/workflows/forma/workflows/swimlanes.forma-workflow.json +130 -0
  58. package/figma/component-contracts.json +140 -0
  59. package/package.json +33 -10
  60. package/patterns/bounded-overflow.html +9 -0
  61. package/patterns/button.html +5 -0
  62. package/patterns/container.html +6 -0
  63. package/patterns/date-time-field.html +5 -0
  64. package/patterns/grid.html +5 -0
  65. package/patterns/image-choice.html +2 -2
  66. package/patterns/key-value-list.html +5 -0
  67. package/patterns/section.html +4 -0
  68. package/patterns/skip-link.html +6 -0
  69. package/patterns/spatial-canvas.html +2 -2
  70. package/patterns/split.html +12 -0
  71. package/patterns/surface.html +4 -0
  72. package/patterns/text-field.html +5 -0
  73. package/patterns/text-roles.html +7 -0
  74. package/patterns/textarea.html +5 -0
  75. package/patterns/visually-hidden.html +4 -0
  76. package/schemas/workflow/1.0/forma-workflow.schema.json +1045 -0
@@ -0,0 +1,91 @@
1
+ # Validating workflows
2
+
3
+ Validation does not need Forma Studio. CI, Praxis, agents and external
4
+ applications all use the same implementation: `Forma.Workflow.Validation`. It
5
+ is available through the CLI, the .NET library and the browser package.
6
+
7
+ ## Command line
8
+
9
+ ```bash
10
+ dotnet run --project src/workflow/Forma.Workflow.Cli -c Release -- validate forma/workflows/*.forma-workflow.json
11
+ dotnet run --project src/workflow/Forma.Workflow.Cli -c Release -- validate --json forma/workflows/launch.forma-workflow.json
12
+ ```
13
+
14
+ | Exit code | Meaning |
15
+ |---|---|
16
+ | 0 | Every file is valid. That includes valid with preserved extensions, valid with unavailable capabilities, and automatically migrated. |
17
+ | 1 | At least one file is invalid or needs a migration that cannot run automatically. |
18
+ | 2 | Invalid arguments. |
19
+ | 3 | A file could not be read. |
20
+
21
+ `--json` prints a report for each file:
22
+
23
+ ```json
24
+ [
25
+ {
26
+ "file": "forma/workflows/extensions.forma-workflow.json",
27
+ "report": {
28
+ "class": "supported-with-preserved-extensions",
29
+ "valid": true,
30
+ "workflow": "extensions",
31
+ "formatVersion": "1.0.0",
32
+ "capabilities": ["workflow.core"],
33
+ "extensions": ["com.example.scheduler", "org.example.audit", "gov.nasa.example.range"],
34
+ "findings": []
35
+ }
36
+ }
37
+ ]
38
+ ```
39
+
40
+ ## .NET
41
+
42
+ ```fsharp
43
+ open Forma.Workflow
44
+
45
+ let report = Validation.load (System.IO.File.ReadAllText "forma/workflows/launch.forma-workflow.json")
46
+ match report.Class with
47
+ | FullySupported | SupportedWithPreservedExtensions _ -> printfn "ok"
48
+ | UnavailableCapabilities caps -> printfn "needs a newer Forma: %A" caps
49
+ | MigrationRequired(from, target, automatic, reason) -> printfn "%s" reason
50
+ | StructurallyInvalid | SemanticallyInvalid ->
51
+ for f in report.Findings do printfn "%s %s %s" f.Code f.Pointer f.Message
52
+ ```
53
+
54
+ ## Browser
55
+
56
+ ```js
57
+ const report = await document.querySelector("forma-workflow").validate(workflowObject);
58
+ ```
59
+
60
+ ## Compatibility classes
61
+
62
+ | Class | When |
63
+ |---|---|
64
+ | `fully-supported` | Valid, and everything in it is understood. |
65
+ | `supported-with-preserved-extensions` | Valid, and it carries namespaced extensions that Forma preserves but does not interpret. |
66
+ | `migration-required` | It declares another `formatVersion`. `migration.automatic` says whether Forma migrated it. |
67
+ | `structurally-invalid` | Not JSON, has duplicate keys, has the wrong `format`, or violates the published schema. |
68
+ | `semantically-invalid` | Schema-valid, but has broken references, ids, ports, membership, unsafe URLs or failed static accessibility rules. The document still decodes, so an editor can show the findings without deleting anyone's data. |
69
+ | `unavailable-capabilities` | Valid format, but it needs capabilities the target `forma.version` lacks, or capabilities this Forma does not provide. |
70
+
71
+ ## What is checked
72
+
73
+ Structure is checked against the published schema file itself. A small built-in
74
+ JSON Schema validator enforces it, so there is no hand-maintained copy.
75
+
76
+ | Area | Finding codes |
77
+ |---|---|
78
+ | JSON | `JSON` (malformed, duplicate keys, more than 64 levels deep, larger than 16 MB) |
79
+ | Format | `FORMAT`, `FORMAT-VERSION`, `FORMAT-MIGRATED` |
80
+ | Schema | `SCHEMA` (with a JSON Pointer) |
81
+ | Identity | `ID-DUPLICATE`, `ID-DUPLICATE-PORT`, `ID-DUPLICATE-REFERENCE`, `ID-DUPLICATE-LEGEND` |
82
+ | References | `REF-DANGLING-EDGE`, `REF-MISSING-PORT`, `REF-INTERACTION-TARGET`, `REF-PALETTE` |
83
+ | Ports | `PORT-DIRECTION`, `PORT-CARDINALITY` |
84
+ | Groups | `GROUP-MISSING-MEMBER`, `GROUP-MISSING-PARENT`, `GROUP-CYCLE`, `GROUP-LANE-CONFLICT` |
85
+ | Extensions | `EXT-RESERVED` (and the schema's namespace and object rules) |
86
+ | Compatibility | `COMPAT-UNAVAILABLE`, `COMPAT-UNKNOWN-CAPABILITY` |
87
+ | Accessibility (static) | `A11Y-TITLE`, `A11Y-NAME`, `A11Y-CONTRAST` (authored text colour against fill below 4.5:1), `A11Y-BRANCH-LABEL`, `A11Y-LEGEND` |
88
+ | Security | `SEC-UNSAFE-URL` (anything other than http, https, mailto or relative; also control characters and leading spaces), `SEC-BIDI-CONTROL` |
89
+ | Semantics (warnings) | `SEM-DECISION-BRANCHES`, `SEM-START-INCOMING`, `SEM-END-OUTGOING`, `LAYOUT-PARTIAL` |
90
+
91
+ Errors decide the class. Warnings and notes do not.
@@ -0,0 +1,101 @@
1
+ {
2
+ "description": "Executable compatibility fixtures for the Forma portable workflow format. Each entry names the file, the compatibility class Forma validation must report, and what it proves. tests/workflow runs every entry.",
3
+ "formatVersion": "1.0.0",
4
+ "fixtures": [
5
+ {
6
+ "id": "minimal",
7
+ "class": "fully-supported",
8
+ "proves": "The smallest valid workflow: one node, no layout."
9
+ },
10
+ {
11
+ "id": "multi-step",
12
+ "class": "fully-supported",
13
+ "proves": "A linear multi-step workflow with provenance."
14
+ },
15
+ {
16
+ "id": "branching",
17
+ "class": "fully-supported",
18
+ "proves": "A decision with labelled conditional branches and a loop back."
19
+ },
20
+ {
21
+ "id": "groups",
22
+ "class": "fully-supported",
23
+ "proves": "Groups and containers with explicit membership and nesting."
24
+ },
25
+ {
26
+ "id": "swimlanes",
27
+ "class": "fully-supported",
28
+ "proves": "Swimlanes and a phase that crosses lanes."
29
+ },
30
+ {
31
+ "id": "colored",
32
+ "class": "fully-supported",
33
+ "proves": "Literal, token and palette colours unrelated to status, with a legend (FMD-TEST-007)."
34
+ },
35
+ {
36
+ "id": "node-metadata",
37
+ "class": "fully-supported",
38
+ "proves": "Arbitrary node and workflow metadata, plus typed domain references."
39
+ },
40
+ {
41
+ "id": "edge-metadata",
42
+ "class": "fully-supported",
43
+ "proves": "Edge metadata, semantic edge kinds and edge status."
44
+ },
45
+ {
46
+ "id": "extensions",
47
+ "class": "supported-with-preserved-extensions",
48
+ "proves": "Namespaced extension data at workflow, node and edge level survives unchanged."
49
+ },
50
+ {
51
+ "id": "no-layout",
52
+ "class": "fully-supported",
53
+ "proves": "A workflow with no coordinates; the deterministic default layout places it."
54
+ },
55
+ {
56
+ "id": "accessible",
57
+ "class": "fully-supported",
58
+ "proves": "Accessible names and descriptions, and labelled branches."
59
+ },
60
+ {
61
+ "id": "mobile",
62
+ "class": "fully-supported",
63
+ "proves": "A top-to-bottom compact workflow for narrow screens."
64
+ },
65
+ {
66
+ "id": "branded",
67
+ "class": "fully-supported",
68
+ "proves": "Token-backed palette slots that a Forma brand restyles."
69
+ },
70
+ {
71
+ "id": "embedded-view",
72
+ "class": "fully-supported",
73
+ "proves": "Runtime status projected onto a read-only embedded workflow."
74
+ },
75
+ {
76
+ "id": "embedded-edit",
77
+ "class": "supported-with-preserved-extensions",
78
+ "proves": "Ports, interaction intents and host extension data in an editable embedded workflow."
79
+ },
80
+ {
81
+ "id": "static-export",
82
+ "class": "fully-supported",
83
+ "proves": "Authored geometry; the reference for static HTML export (exports/static-export.*.html)."
84
+ },
85
+ {
86
+ "id": "interactive-export",
87
+ "class": "fully-supported",
88
+ "proves": "Declarative interaction intents; the reference for interactive HTML export (exports/interactive-export.document.html)."
89
+ },
90
+ {
91
+ "id": "runtime-ports",
92
+ "class": "fully-supported",
93
+ "proves": "Ports with direction and cardinality, core and namespaced status states."
94
+ },
95
+ {
96
+ "id": "color-mapping",
97
+ "class": "supported-with-preserved-extensions",
98
+ "proves": "An explicit producer metadata-to-colour mapping with a legend (FMD-TEST-008)."
99
+ }
100
+ ]
101
+ }
@@ -0,0 +1,90 @@
1
+ {
2
+ "$schema": "https://forma.echelonfoundry.com/schemas/workflow/1.0/forma-workflow.schema.json",
3
+ "format": "forma-workflow",
4
+ "formatVersion": "1.0.0",
5
+ "id": "accessible",
6
+ "title": "Docking approach",
7
+ "description": "Every branch is labelled so the paths are distinguishable without seeing the diagram.",
8
+ "language": "en",
9
+ "direction": "ltr",
10
+ "forma": {
11
+ "version": "0.4.0"
12
+ },
13
+ "nodes": [
14
+ {
15
+ "id": "approach",
16
+ "kind": "start",
17
+ "label": "Begin approach",
18
+ "accessibility": {
19
+ "description": "The spacecraft starts its final approach at 200 metres."
20
+ }
21
+ },
22
+ {
23
+ "id": "check",
24
+ "kind": "decision",
25
+ "label": "Alignment within limits?",
26
+ "accessibility": {
27
+ "name": "Decision: is alignment within limits?"
28
+ }
29
+ },
30
+ {
31
+ "id": "capture",
32
+ "kind": "task",
33
+ "label": "Soft capture"
34
+ },
35
+ {
36
+ "id": "abort",
37
+ "kind": "task",
38
+ "label": "Abort and back away"
39
+ },
40
+ {
41
+ "id": "docked",
42
+ "kind": "end",
43
+ "label": "Docked"
44
+ }
45
+ ],
46
+ "edges": [
47
+ {
48
+ "id": "a1",
49
+ "source": {
50
+ "node": "approach"
51
+ },
52
+ "target": {
53
+ "node": "check"
54
+ }
55
+ },
56
+ {
57
+ "id": "a2",
58
+ "source": {
59
+ "node": "check"
60
+ },
61
+ "target": {
62
+ "node": "capture"
63
+ },
64
+ "label": "Within limits",
65
+ "accessibility": {
66
+ "description": "Normal path."
67
+ }
68
+ },
69
+ {
70
+ "id": "a3",
71
+ "source": {
72
+ "node": "check"
73
+ },
74
+ "target": {
75
+ "node": "abort"
76
+ },
77
+ "label": "Out of limits",
78
+ "line": "dashed"
79
+ },
80
+ {
81
+ "id": "a4",
82
+ "source": {
83
+ "node": "capture"
84
+ },
85
+ "target": {
86
+ "node": "docked"
87
+ }
88
+ }
89
+ ]
90
+ }
@@ -0,0 +1,91 @@
1
+ {
2
+ "$schema": "https://forma.echelonfoundry.com/schemas/workflow/1.0/forma-workflow.schema.json",
3
+ "format": "forma-workflow",
4
+ "formatVersion": "1.0.0",
5
+ "id": "branching",
6
+ "title": "Launch readiness poll",
7
+ "forma": {
8
+ "version": "0.4.0"
9
+ },
10
+ "nodes": [
11
+ {
12
+ "id": "poll",
13
+ "kind": "start",
14
+ "label": "Begin readiness poll"
15
+ },
16
+ {
17
+ "id": "go",
18
+ "kind": "decision",
19
+ "label": "All stations go?"
20
+ },
21
+ {
22
+ "id": "hold",
23
+ "kind": "task",
24
+ "label": "Call a hold"
25
+ },
26
+ {
27
+ "id": "resolve",
28
+ "kind": "task",
29
+ "label": "Resolve the issue"
30
+ },
31
+ {
32
+ "id": "launch",
33
+ "kind": "end",
34
+ "label": "Proceed to launch"
35
+ }
36
+ ],
37
+ "edges": [
38
+ {
39
+ "id": "e-poll",
40
+ "source": {
41
+ "node": "poll"
42
+ },
43
+ "target": {
44
+ "node": "go"
45
+ }
46
+ },
47
+ {
48
+ "id": "e-yes",
49
+ "source": {
50
+ "node": "go"
51
+ },
52
+ "target": {
53
+ "node": "launch"
54
+ },
55
+ "kind": "conditional",
56
+ "label": "Go"
57
+ },
58
+ {
59
+ "id": "e-no",
60
+ "source": {
61
+ "node": "go"
62
+ },
63
+ "target": {
64
+ "node": "hold"
65
+ },
66
+ "kind": "conditional",
67
+ "label": "No go",
68
+ "line": "dashed"
69
+ },
70
+ {
71
+ "id": "e-fix",
72
+ "source": {
73
+ "node": "hold"
74
+ },
75
+ "target": {
76
+ "node": "resolve"
77
+ }
78
+ },
79
+ {
80
+ "id": "e-repoll",
81
+ "source": {
82
+ "node": "resolve"
83
+ },
84
+ "target": {
85
+ "node": "go"
86
+ },
87
+ "label": "Repoll",
88
+ "line": "dotted"
89
+ }
90
+ ]
91
+ }
@@ -0,0 +1,85 @@
1
+ {
2
+ "$schema": "https://forma.echelonfoundry.com/schemas/workflow/1.0/forma-workflow.schema.json",
3
+ "format": "forma-workflow",
4
+ "formatVersion": "1.0.0",
5
+ "id": "branded",
6
+ "title": "Partner mission review",
7
+ "description": "Uses only token-backed palette slots, so a Forma brand restyles it without editing the workflow.",
8
+ "forma": {
9
+ "version": "0.4.0"
10
+ },
11
+ "palette": {
12
+ "primary": "token:surface-secondary",
13
+ "accent": "token:accent-primary"
14
+ },
15
+ "nodes": [
16
+ {
17
+ "id": "brief",
18
+ "kind": "task",
19
+ "label": "Partner briefing",
20
+ "color": {
21
+ "fill": "palette:primary",
22
+ "foreground": "token:text-primary"
23
+ }
24
+ },
25
+ {
26
+ "id": "review",
27
+ "kind": "task",
28
+ "label": "Joint review",
29
+ "color": {
30
+ "accent": "palette:accent"
31
+ }
32
+ },
33
+ {
34
+ "id": "signoff",
35
+ "kind": "end",
36
+ "label": "Joint sign-off",
37
+ "color": {
38
+ "stroke": "palette:accent"
39
+ }
40
+ }
41
+ ],
42
+ "edges": [
43
+ {
44
+ "id": "b1",
45
+ "source": {
46
+ "node": "brief"
47
+ },
48
+ "target": {
49
+ "node": "review"
50
+ }
51
+ },
52
+ {
53
+ "id": "b2",
54
+ "source": {
55
+ "node": "review"
56
+ },
57
+ "target": {
58
+ "node": "signoff"
59
+ },
60
+ "color": {
61
+ "stroke": "palette:accent"
62
+ }
63
+ }
64
+ ],
65
+ "presentation": {
66
+ "legend": [
67
+ {
68
+ "id": "partner",
69
+ "label": "Partner-owned step",
70
+ "description": "brand surface fill",
71
+ "color": {
72
+ "fill": "palette:primary"
73
+ }
74
+ },
75
+ {
76
+ "id": "joint",
77
+ "label": "Joint step",
78
+ "description": "brand accent",
79
+ "color": {
80
+ "accent": "palette:accent"
81
+ }
82
+ }
83
+ ]
84
+ }
85
+ }
@@ -0,0 +1,111 @@
1
+ {
2
+ "$schema": "https://forma.echelonfoundry.com/schemas/workflow/1.0/forma-workflow.schema.json",
3
+ "format": "forma-workflow",
4
+ "formatVersion": "1.0.0",
5
+ "id": "color-mapping",
6
+ "title": "Risk-coded review queue",
7
+ "description": "Colours come from an explicit mapping the producer applied to the metadata field risk. The mapping belongs to the producer; Forma only renders the resolved colours. Risk is also stated in text.",
8
+ "forma": {
9
+ "version": "0.4.0"
10
+ },
11
+ "nodes": [
12
+ {
13
+ "id": "r1",
14
+ "kind": "task",
15
+ "label": "Thermal model update",
16
+ "metadata": {
17
+ "risk": "high"
18
+ },
19
+ "color": {
20
+ "fill": "#fde2e1",
21
+ "accent": "#9b1c1c",
22
+ "foreground": "#1d1d1b"
23
+ }
24
+ },
25
+ {
26
+ "id": "r2",
27
+ "kind": "task",
28
+ "label": "Antenna re-point",
29
+ "metadata": {
30
+ "risk": "medium"
31
+ },
32
+ "color": {
33
+ "fill": "#fff1d6",
34
+ "accent": "#8a5300",
35
+ "foreground": "#1d1d1b"
36
+ }
37
+ },
38
+ {
39
+ "id": "r3",
40
+ "kind": "task",
41
+ "label": "Battery trend report",
42
+ "metadata": {
43
+ "risk": "low"
44
+ },
45
+ "color": {
46
+ "fill": "#e3f4e8",
47
+ "accent": "#1e6b3a",
48
+ "foreground": "#1d1d1b"
49
+ }
50
+ }
51
+ ],
52
+ "edges": [
53
+ {
54
+ "id": "q1",
55
+ "source": {
56
+ "node": "r1"
57
+ },
58
+ "target": {
59
+ "node": "r2"
60
+ }
61
+ },
62
+ {
63
+ "id": "q2",
64
+ "source": {
65
+ "node": "r2"
66
+ },
67
+ "target": {
68
+ "node": "r3"
69
+ }
70
+ }
71
+ ],
72
+ "presentation": {
73
+ "legendTitle": "Key: risk (producer mapping of metadata field risk)",
74
+ "legend": [
75
+ {
76
+ "id": "high",
77
+ "label": "High risk",
78
+ "color": {
79
+ "fill": "#fde2e1",
80
+ "accent": "#9b1c1c"
81
+ }
82
+ },
83
+ {
84
+ "id": "medium",
85
+ "label": "Medium risk",
86
+ "color": {
87
+ "fill": "#fff1d6",
88
+ "accent": "#8a5300"
89
+ }
90
+ },
91
+ {
92
+ "id": "low",
93
+ "label": "Low risk",
94
+ "color": {
95
+ "fill": "#e3f4e8",
96
+ "accent": "#1e6b3a"
97
+ }
98
+ }
99
+ ]
100
+ },
101
+ "extensions": {
102
+ "com.example.riskboard": {
103
+ "mapping": {
104
+ "field": "risk",
105
+ "high": "#fde2e1",
106
+ "medium": "#fff1d6",
107
+ "low": "#e3f4e8"
108
+ }
109
+ }
110
+ }
111
+ }
@@ -0,0 +1,131 @@
1
+ {
2
+ "$schema": "https://forma.echelonfoundry.com/schemas/workflow/1.0/forma-workflow.schema.json",
3
+ "format": "forma-workflow",
4
+ "formatVersion": "1.0.0",
5
+ "id": "colored",
6
+ "title": "Mission operations by team",
7
+ "description": "Fill colour shows the owning team. It says nothing about status: each step states its status in text.",
8
+ "forma": {
9
+ "version": "0.4.0"
10
+ },
11
+ "palette": {
12
+ "archive": "token:surface-secondary"
13
+ },
14
+ "nodes": [
15
+ {
16
+ "id": "plan",
17
+ "kind": "task",
18
+ "label": "Plan the pass",
19
+ "color": {
20
+ "fill": "#e8f0ff",
21
+ "accent": "#2f5fb3",
22
+ "foreground": "#1d1d1b"
23
+ },
24
+ "status": {
25
+ "state": "complete"
26
+ }
27
+ },
28
+ {
29
+ "id": "uplink",
30
+ "kind": "task",
31
+ "label": "Uplink commands",
32
+ "color": {
33
+ "fill": "#e8f0ff",
34
+ "accent": "#2f5fb3",
35
+ "foreground": "#1d1d1b"
36
+ },
37
+ "status": {
38
+ "state": "active"
39
+ }
40
+ },
41
+ {
42
+ "id": "downlink",
43
+ "kind": "task",
44
+ "label": "Receive telemetry",
45
+ "color": {
46
+ "fill": "#fff1d6",
47
+ "accent": "#8a5300",
48
+ "foreground": "#1d1d1b"
49
+ },
50
+ "status": {
51
+ "state": "pending"
52
+ }
53
+ },
54
+ {
55
+ "id": "archive",
56
+ "kind": "end",
57
+ "label": "Archive the pass",
58
+ "color": {
59
+ "fill": "palette:archive",
60
+ "foreground": "token:text-primary"
61
+ }
62
+ }
63
+ ],
64
+ "edges": [
65
+ {
66
+ "id": "c1",
67
+ "source": {
68
+ "node": "plan"
69
+ },
70
+ "target": {
71
+ "node": "uplink"
72
+ }
73
+ },
74
+ {
75
+ "id": "c2",
76
+ "source": {
77
+ "node": "uplink"
78
+ },
79
+ "target": {
80
+ "node": "downlink"
81
+ },
82
+ "color": {
83
+ "stroke": "#2f5fb3"
84
+ },
85
+ "width": 3
86
+ },
87
+ {
88
+ "id": "c3",
89
+ "source": {
90
+ "node": "downlink"
91
+ },
92
+ "target": {
93
+ "node": "archive"
94
+ },
95
+ "color": {
96
+ "stroke": "token:accent-secondary"
97
+ }
98
+ }
99
+ ],
100
+ "presentation": {
101
+ "legendTitle": "Key: fill colour by owning team",
102
+ "legend": [
103
+ {
104
+ "id": "ops",
105
+ "label": "Flight operations",
106
+ "description": "blue fill",
107
+ "color": {
108
+ "fill": "#e8f0ff",
109
+ "accent": "#2f5fb3"
110
+ }
111
+ },
112
+ {
113
+ "id": "ground",
114
+ "label": "Ground network",
115
+ "description": "amber fill",
116
+ "color": {
117
+ "fill": "#fff1d6",
118
+ "accent": "#8a5300"
119
+ }
120
+ },
121
+ {
122
+ "id": "data",
123
+ "label": "Data systems",
124
+ "description": "neutral fill",
125
+ "color": {
126
+ "fill": "palette:archive"
127
+ }
128
+ }
129
+ ]
130
+ }
131
+ }