@paradigma-inc/flywheel 0.1.11 → 0.1.13
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.
- package/package.json +1 -1
- package/skills/flywheel/SKILL.md +7 -25
- package/skills/flywheel/agents/openai.yaml +2 -2
- package/skills/flywheel/example-workflows/organizing-exploring-and-iterating-on-a-research-topic.md +8 -8
- package/skills/flywheel/example-workflows/reproducing-papers-on-a-budget.md +8 -8
- package/skills/flywheel/getting-started/flywheel-tutorial-overview.md +1 -1
- package/skills/flywheel/references/experiment-design-protocol.md +204 -0
- package/skills/flywheel/references/flywheel-mcp-tool-map.md +160 -0
- package/skills/flywheel/web-ui/flywheel-webui-map.md +1 -1
- package/skills/flywheel-auto/SKILL.md +156 -0
- package/skills/flywheel-auto/agents/openai.yaml +12 -0
- package/skills/flywheel-auto/evals/evals.json +20 -0
- package/skills/flywheel-auto/references/ARTIFACTS.md +218 -0
- package/skills/flywheel-auto/references/INTERFACES.md +201 -0
- package/skills/{flywheel/reference → flywheel-auto/references}/experiment-design-protocol.md +9 -5
- package/skills/flywheel-lookahead/SKILL.md +145 -0
- package/skills/flywheel-lookahead/agents/openai.yaml +12 -0
- package/skills/flywheel-lookahead/evals/evals.json +20 -0
- package/skills/flywheel-lookahead/references/ARTIFACTS.md +218 -0
- package/skills/flywheel-lookahead/references/INTERFACES.md +201 -0
- package/skills/flywheel-lookahead/references/flywheel-mcp-tool-map.md +160 -0
- package/skills/flywheel-reproduce/SKILL.md +212 -0
- package/skills/flywheel-reproduce/agents/openai.yaml +12 -0
- package/skills/flywheel-reproduce/evals/evals.json +20 -0
- package/skills/flywheel-reproduce/references/ARTIFACTS.md +218 -0
- package/skills/flywheel-reproduce/references/INTERFACES.md +201 -0
- package/skills/flywheel-reproduce/references/experiment-design-protocol.md +204 -0
- package/skills/flywheel-reproduce/references/flywheel-mcp-tool-map.md +160 -0
- package/skills/flywheel-to-graph/SKILL.md +187 -0
- package/skills/flywheel-to-graph/agents/openai.yaml +12 -0
- package/skills/flywheel-to-graph/evals/evals.json +20 -0
- package/skills/flywheel-to-graph/references/ARTIFACTS.md +218 -0
- package/skills/flywheel-to-graph/references/INTERFACES.md +201 -0
- package/skills/flywheel-to-graph/references/flywheel-mcp-tool-map.md +160 -0
- package/skills/flywheel/reference/command-presets.md +0 -230
- package/skills/flywheel/reference/wiki-porting.md +0 -92
- /package/skills/{flywheel/reference → flywheel-auto/references}/flywheel-mcp-tool-map.md +0 -0
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: flywheel-to-graph
|
|
3
|
+
description: Port source material into Flywheel nodes, artifacts, and durable edges with Flywheel MCP, without execution or compute spend. Use for source-to-graph authoring, not empirical validation, next-step planning, or autonomous execution.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# flywheel-to-graph
|
|
7
|
+
|
|
8
|
+
## When To Use
|
|
9
|
+
|
|
10
|
+
Use this skill when the task is to shape information inside Flywheel rather than only discuss it. Use the flywheel-to-graph skill when the user's main goal is to convert unstructured source material into a Flywheel graph. Flywheel MCP is a node-first durable system of record for research work: nodes hold durable state, artifacts hold supporting files, executions record runs, and compute leases provide managed hardware. This skill is authoring only: it ports source material into nodes, artifacts, and durable edges without hidden execution, compute approval, or managed compute acquisition.
|
|
11
|
+
|
|
12
|
+
If exact tool or field semantics are unclear, load [references/flywheel-mcp-tool-map.md](references/flywheel-mcp-tool-map.md) and [references/INTERFACES.md](references/INTERFACES.md) before mutating nodes.
|
|
13
|
+
|
|
14
|
+
## Input Contract
|
|
15
|
+
|
|
16
|
+
Before authoring, recover or establish these inputs:
|
|
17
|
+
|
|
18
|
+
- Required before authoring: source material or explicit source nodes, and the intended source-to-graph scope.
|
|
19
|
+
- Optional: preferred root node, subtree shape, node granularity, and whether budget metadata should be tracked for later execution-oriented work.
|
|
20
|
+
- Recovery rules:
|
|
21
|
+
- Ask only when the source corpus, source nodes, or intended scope cannot be recovered from explicit user instructions, current conversational context, or recent graph state.
|
|
22
|
+
- If the corpus is already represented in Flywheel, recover the governing source nodes before asking.
|
|
23
|
+
- If no explicit scope is given, infer the narrowest stable scope that matches the provided source material and state it before authoring.
|
|
24
|
+
|
|
25
|
+
## Working Terms
|
|
26
|
+
|
|
27
|
+
- `source corpus`: the input material to port, such as papers, blog posts, READMEs, markdown wikis, or research notes.
|
|
28
|
+
- `normalized Flywheel graph export`: already-structured Flywheel node JSON with DAG-safe edges, suitable for `flywheel_import_subgraph`.
|
|
29
|
+
- `durable edge`: a graph relationship that carries stable semantic meaning, not just a navigational hyperlink.
|
|
30
|
+
- `authoring pass`: one pass that reads source material and stages or commits the corresponding node/artifact updates.
|
|
31
|
+
- `expected_revision`: the node's current revision token used for optimistic-locking writes.
|
|
32
|
+
|
|
33
|
+
## Core Rules
|
|
34
|
+
|
|
35
|
+
- Prefer explicit Flywheel node and artifact operations over ad hoc bulk-import stories, because node-first authoring keeps the graph legible and auditable.
|
|
36
|
+
- Treat the main page body as the node readme/body field (`content` on modern Flywheel surfaces).
|
|
37
|
+
- Use artifacts for supporting files and evidence, not as a substitute for the node's main narrative, because the node body should remain the readable source-of-truth for the imported material.
|
|
38
|
+
- Only create graph edges for durable semantic relationships, because graphifying every wiki link floods the graph with noise that hides decision-relevant structure.
|
|
39
|
+
- Use `flywheel_import_subgraph` only for prebuilt Flywheel graph JSON, not for raw markdown repositories, because raw corpora are usually file-centric and cyclic rather than clean node-centric payloads.
|
|
40
|
+
- Treat the flywheel-to-graph skill as source-to-graph authoring only. It ports material into Flywheel primitives but does not execute branches or spend budget implicitly, because that changes the job into `$flywheel-reproduce` or `$flywheel-auto`.
|
|
41
|
+
|
|
42
|
+
## Workflow
|
|
43
|
+
|
|
44
|
+
1. Resolve the starting context.
|
|
45
|
+
- Start from the provided source material or explicit source nodes.
|
|
46
|
+
- Resolve governing nodes in this order: explicit node ids/slugs, explicitly named current context, focused or recently referenced nodes, then ask the user if nothing stable is recoverable.
|
|
47
|
+
2. Classify the input.
|
|
48
|
+
- If it is already a normalized Flywheel graph export, `flywheel_import_subgraph` may be appropriate.
|
|
49
|
+
- If it is a markdown/wiki/blog/README corpus, paper, or research note set, port it explicitly with node and artifact tools.
|
|
50
|
+
3. Map each stable page, claim, or concept to a node.
|
|
51
|
+
- For exact node-mutation shapes, load [references/flywheel-mcp-tool-map.md](references/flywheel-mcp-tool-map.md).
|
|
52
|
+
- Create a new node with `flywheel_stage_node_create` when needed.
|
|
53
|
+
- Update an existing node with `flywheel_get_node` + `flywheel_stage_node_update` when continuing work.
|
|
54
|
+
4. Put the primary page markdown or source narrative in the node body/readme field (`content`).
|
|
55
|
+
- Keep `summary` concise.
|
|
56
|
+
- Populate `hypothesis`, `insights`, `outcome`, and similar fields only when the source actually supports them.
|
|
57
|
+
5. Publish supporting files with the artifact upload flow.
|
|
58
|
+
- For exact artifact contract details, load [references/ARTIFACTS.md](references/ARTIFACTS.md).
|
|
59
|
+
- Use `flywheel_prepare_artifact_uploads`.
|
|
60
|
+
- Upload raw file bytes to the returned signed URLs.
|
|
61
|
+
- Call `flywheel_finalize_artifact_uploads` once all uploads in the batch are staged.
|
|
62
|
+
- Keep the artifact filename stable enough to reference from markdown when inline rendering matters.
|
|
63
|
+
6. Add graph structure sparingly.
|
|
64
|
+
- Promote only durable semantic relationships to edges.
|
|
65
|
+
- Leave ordinary cross-links inside the markdown body.
|
|
66
|
+
7. Commit after the node snapshot is coherent with `flywheel_commit_node`.
|
|
67
|
+
- Commit once the source narrative, artifact attachments, and selected graph structure agree with each other.
|
|
68
|
+
|
|
69
|
+
## Result Contract
|
|
70
|
+
|
|
71
|
+
When the skill completes a pass, it should leave behind:
|
|
72
|
+
|
|
73
|
+
- A root node or subtree that represents the source material in Flywheel.
|
|
74
|
+
- The primary narrative preserved in node `content`.
|
|
75
|
+
- Supporting files attached as artifacts where appropriate.
|
|
76
|
+
- Only durable graph edges added to the graph.
|
|
77
|
+
- No hidden execution, no compute approval, and no managed compute acquisition.
|
|
78
|
+
|
|
79
|
+
## Persisted Authoring Contract
|
|
80
|
+
|
|
81
|
+
When the source-to-graph work spans multiple pages or multiple passes, use a dedicated `insight` node as the durable authoring controller for that corpus. Do not rely on unstated product fields or fresh chat context.
|
|
82
|
+
|
|
83
|
+
For the canonical entity model and public contract terminology behind this controller, load [references/INTERFACES.md](references/INTERFACES.md).
|
|
84
|
+
|
|
85
|
+
Use this storage convention:
|
|
86
|
+
|
|
87
|
+
1. Reuse an existing authoring control node when one already governs the same corpus; otherwise create one with `flywheel_stage_node_create`.
|
|
88
|
+
2. Put the canonical authoring contract in node `content`.
|
|
89
|
+
3. Put a one-line synopsis in `summary`.
|
|
90
|
+
4. Put the current mapping rationale or continuation note in `insights` so the `insight` commit contract is satisfied.
|
|
91
|
+
5. Update the control node with `flywheel_stage_node_update`.
|
|
92
|
+
6. Read the control node with `flywheel_get_node` before later passes that need a fresh `expected_revision`.
|
|
93
|
+
7. Commit the control node with `flywheel_commit_node` once the contract is coherent, even if downstream source nodes remain staged or in progress.
|
|
94
|
+
|
|
95
|
+
Canonical contract shape:
|
|
96
|
+
|
|
97
|
+
```md
|
|
98
|
+
## Authoring contract
|
|
99
|
+
|
|
100
|
+
- Source corpus:
|
|
101
|
+
- Intended scope:
|
|
102
|
+
- Root node or subtree target:
|
|
103
|
+
- Default node granularity:
|
|
104
|
+
- Edge policy:
|
|
105
|
+
- Execution policy:
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
The `Source corpus` and `Intended scope` lines are the recovery anchors for later authoring passes.
|
|
109
|
+
|
|
110
|
+
## Wiki Porting
|
|
111
|
+
|
|
112
|
+
Use this guide when the source material is a markdown wiki, README corpus, or a Karpathy-style LLM wiki that should become Flywheel nodes.
|
|
113
|
+
|
|
114
|
+
### Default Mapping
|
|
115
|
+
|
|
116
|
+
- One wiki page or stable concept -> one Flywheel node.
|
|
117
|
+
- The main page markdown -> the node body/readme field (`content`).
|
|
118
|
+
- A short synopsis of the page -> `summary`.
|
|
119
|
+
- Images, PDFs, datasets, notebooks, code snippets, and other supporting files -> node artifacts.
|
|
120
|
+
- Durable structural relationships -> graph edges.
|
|
121
|
+
- Ordinary wiki hyperlinks -> remain markdown links inside the node body.
|
|
122
|
+
|
|
123
|
+
Do not try to preserve the source wiki as a file-first mirror inside Flywheel. Flywheel is node-first.
|
|
124
|
+
|
|
125
|
+
### What The Model Should Do
|
|
126
|
+
|
|
127
|
+
Assume the model is expected to perform the port directly unless the user explicitly asks to build a dedicated importer.
|
|
128
|
+
|
|
129
|
+
That means:
|
|
130
|
+
|
|
131
|
+
1. Read the source pages and supporting files.
|
|
132
|
+
2. Create or update nodes explicitly.
|
|
133
|
+
3. Write the page body into node `content`.
|
|
134
|
+
4. Publish supporting files as artifacts.
|
|
135
|
+
5. Add only the graph edges that materially help reasoning or navigation.
|
|
136
|
+
|
|
137
|
+
Do not wait for a magical bulk-import surface if the available Flywheel primitives are already enough.
|
|
138
|
+
|
|
139
|
+
## `flywheel_import_subgraph`
|
|
140
|
+
|
|
141
|
+
Use `flywheel_import_subgraph` only when the input is already normalized into Flywheel node JSON with DAG-safe edges.
|
|
142
|
+
|
|
143
|
+
Do not use it for raw markdown repositories because those are usually:
|
|
144
|
+
|
|
145
|
+
- file-centric rather than node-centric
|
|
146
|
+
- heavily cross-linked
|
|
147
|
+
- cyclic in ways that are natural for a wiki but not a clean Flywheel graph
|
|
148
|
+
|
|
149
|
+
Treat raw wiki content as authoring input, not as a direct subgraph payload.
|
|
150
|
+
|
|
151
|
+
## Edge Policy
|
|
152
|
+
|
|
153
|
+
Promote a relation to a graph edge only when it carries durable meaning such as:
|
|
154
|
+
|
|
155
|
+
- hierarchy or decomposition
|
|
156
|
+
- prerequisite or dependency
|
|
157
|
+
- derived-from or result-of
|
|
158
|
+
- canonical comparison target
|
|
159
|
+
|
|
160
|
+
Do not create edges for every incidental mention, backlink, or navigational cross-reference. Keep those inside the markdown body instead.
|
|
161
|
+
|
|
162
|
+
## Inline Artifact Embeds
|
|
163
|
+
|
|
164
|
+
When the node body supports inline artifact rendering, keep references on their own lines so the renderer can replace them with the matching artifact preview.
|
|
165
|
+
|
|
166
|
+
Examples:
|
|
167
|
+
|
|
168
|
+
```md
|
|
169
|
+

|
|
170
|
+
|
|
171
|
+
[Evaluation metrics](metrics.json)
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
Guidelines:
|
|
175
|
+
|
|
176
|
+
- Upload the artifact first, then reference it from the body.
|
|
177
|
+
- Keep filenames stable enough for the renderer to match them.
|
|
178
|
+
- Use inline embeds for supporting visuals or data, but keep the main explanation in the node body itself.
|
|
179
|
+
- If a reference does not match an artifact, it should remain valid markdown rather than break the page.
|
|
180
|
+
|
|
181
|
+
## Guardrails
|
|
182
|
+
|
|
183
|
+
- Do not hide spend behind the flywheel-to-graph skill.
|
|
184
|
+
- Build the graph explicitly with nodes, artifacts, and selected edges.
|
|
185
|
+
- Keep the source material legible in `content`; do not dump everything into artifacts.
|
|
186
|
+
|
|
187
|
+
See also: invoke `$flywheel-reproduce` to graphify claim-bearing sources and run budgeted validation branches, invoke `$flywheel-lookahead` to stage next-step frontier nodes from existing graph state without execution, and invoke `$flywheel-auto` to advance a frontier autonomously under an explicit budget and persisted stop condition.
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
interface:
|
|
2
|
+
display_name: "flywheel-to-graph"
|
|
3
|
+
short_description: "Turn source material into a Flywheel graph"
|
|
4
|
+
default_prompt: "Use $flywheel-to-graph to turn this source corpus into Flywheel nodes, artifacts, and edges."
|
|
5
|
+
|
|
6
|
+
dependencies:
|
|
7
|
+
tools:
|
|
8
|
+
- type: "mcp"
|
|
9
|
+
value: "flywheel"
|
|
10
|
+
description: "Flywheel MCP server"
|
|
11
|
+
transport: "streamable_http"
|
|
12
|
+
url: "https://flywheel.paradigma.inc/mcp-server"
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
[
|
|
2
|
+
{
|
|
3
|
+
"id": "markdown-wiki-corpus-ports-explicitly",
|
|
4
|
+
"prompt": "Use $flywheel-to-graph to turn this markdown wiki corpus into a Flywheel graph. Preserve the main narrative in nodes, attach supporting files as artifacts, and do not invent a separate importer surface.",
|
|
5
|
+
"expected_output": "Port the corpus with explicit node and artifact authoring, keep the main narrative in node `content`, add only durable graph edges, and avoid hidden execution or compute spend.",
|
|
6
|
+
"files": []
|
|
7
|
+
},
|
|
8
|
+
{
|
|
9
|
+
"id": "normalized-export-uses-import-subgraph",
|
|
10
|
+
"prompt": "Use $flywheel-to-graph on this input, which is already a normalized Flywheel graph export with DAG-safe edges.",
|
|
11
|
+
"expected_output": "Recognize that the input is already normalized Flywheel graph JSON and use `flywheel_import_subgraph` rather than rebuilding the graph page by page.",
|
|
12
|
+
"files": []
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
"id": "claim-bearing-paper-without-execution",
|
|
16
|
+
"prompt": "Use $flywheel-to-graph to structure this claim-bearing paper into Flywheel nodes and artifacts, but do not run any validation branches yet.",
|
|
17
|
+
"expected_output": "Port the paper into nodes, artifacts, and durable edges without hidden execution or compute acquisition, leaving any later empirical validation to `$flywheel-reproduce`.",
|
|
18
|
+
"files": []
|
|
19
|
+
}
|
|
20
|
+
]
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
# Flywheel Artifacts
|
|
2
|
+
|
|
3
|
+
Canonical reference for node artifact publishing in Flywheel MCP 0.9.
|
|
4
|
+
|
|
5
|
+
Legacy note:
|
|
6
|
+
|
|
7
|
+
- historical `run_artifacts` rows are retained for backward reads.
|
|
8
|
+
- new artifact writes must use the MCP batch upload workflow:
|
|
9
|
+
`flywheel_prepare_artifact_uploads` -> raw file upload(s) ->
|
|
10
|
+
`flywheel_finalize_artifact_uploads`.
|
|
11
|
+
|
|
12
|
+
## Node MCP Contract
|
|
13
|
+
|
|
14
|
+
Artifacts are managed through node MCP tools:
|
|
15
|
+
|
|
16
|
+
- `flywheel_prepare_artifact_uploads` prepares one or more signed raw-file
|
|
17
|
+
upload requests for a node.
|
|
18
|
+
- The caller executes each returned upload request with raw bytes.
|
|
19
|
+
- `flywheel_finalize_artifact_uploads` appends all staged uploads in that batch
|
|
20
|
+
to the node and bumps node revision once.
|
|
21
|
+
- `flywheel_list_artifacts` and `flywheel_get_artifact` return artifact
|
|
22
|
+
metadata.
|
|
23
|
+
- `flywheel_get_artifact_preview` reads persisted preview payload content by
|
|
24
|
+
artifact id.
|
|
25
|
+
- `flywheel_commit_node` commits/finalizes node state after terminal fields are
|
|
26
|
+
already staged.
|
|
27
|
+
|
|
28
|
+
Contract rules:
|
|
29
|
+
|
|
30
|
+
- `flywheel_prepare_artifact_uploads` requires `expected_revision` and enforces
|
|
31
|
+
optimistic locking before issuing upload tickets.
|
|
32
|
+
- Upload uses the signed one-time ticket in each returned `upload_url`;
|
|
33
|
+
client-supplied path/reference fields are not part of this contract.
|
|
34
|
+
- Raw upload only stages payloads. It does not mutate node state or bump node
|
|
35
|
+
revision.
|
|
36
|
+
- `flywheel_finalize_artifact_uploads` is the single node mutation point for an
|
|
37
|
+
artifact batch.
|
|
38
|
+
- `flywheel_commit_node` is finalize-only:
|
|
39
|
+
- request shape is `expected_revision` with optional `summary` override.
|
|
40
|
+
- node kind/outcome/hypothesis/insights/no_artifacts_reason must already be
|
|
41
|
+
staged.
|
|
42
|
+
- commit transitions lifecycle to `committed`.
|
|
43
|
+
- committed node contract rules remain strict:
|
|
44
|
+
- `kind=empirical` + `outcome=completed` requires artifacts or
|
|
45
|
+
`no_artifacts_reason`.
|
|
46
|
+
- `kind=insight` requires non-empty `insights`.
|
|
47
|
+
- `kind=empirical` requires empty `insights`.
|
|
48
|
+
- MCP mutating calls require idempotency:
|
|
49
|
+
- tool transport auto-manages idempotency keys for tool calls.
|
|
50
|
+
- direct HTTP callers must provide `Idempotency-Key` on mutating MCP
|
|
51
|
+
endpoints.
|
|
52
|
+
|
|
53
|
+
`artifact_type=banner` is supported for campaign root visuals. It follows the
|
|
54
|
+
same raw image upload validation path as `artifact_type=image` and is intended
|
|
55
|
+
for zoomed-out canvas visibility.
|
|
56
|
+
|
|
57
|
+
## Prepare Request Shape
|
|
58
|
+
|
|
59
|
+
`POST /mcp/nodes/{node_id}/artifacts/uploads/prepare`
|
|
60
|
+
|
|
61
|
+
```json
|
|
62
|
+
{
|
|
63
|
+
"expected_revision": 7,
|
|
64
|
+
"items": [
|
|
65
|
+
{
|
|
66
|
+
"artifact_type": "image",
|
|
67
|
+
"title": "Loss curve",
|
|
68
|
+
"execution_id": "optional-execution-id",
|
|
69
|
+
"metadata": {
|
|
70
|
+
"source": "training-run"
|
|
71
|
+
},
|
|
72
|
+
"filename": "loss_curve.png",
|
|
73
|
+
"media_type": "image/png"
|
|
74
|
+
}
|
|
75
|
+
]
|
|
76
|
+
}
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Notes:
|
|
80
|
+
|
|
81
|
+
- `items` must contain at least one structured object item.
|
|
82
|
+
- String or JSON-encoded item payloads are invalid at the tool boundary.
|
|
83
|
+
- `filename` and `media_type` are required for each item.
|
|
84
|
+
- `metadata` is caller-defined JSON.
|
|
85
|
+
|
|
86
|
+
## Prepare Response Shape
|
|
87
|
+
|
|
88
|
+
```json
|
|
89
|
+
{
|
|
90
|
+
"batch": {
|
|
91
|
+
"batch_token": "uuid",
|
|
92
|
+
"expires_at": "2026-03-09T16:00:00+00:00",
|
|
93
|
+
"max_upload_bytes": 10485760,
|
|
94
|
+
"items": [
|
|
95
|
+
{
|
|
96
|
+
"upload_id": "uuid",
|
|
97
|
+
"upload_url": "https://.../mcp/artifacts/uploads/{upload_id}?ticket=...",
|
|
98
|
+
"method": "PUT",
|
|
99
|
+
"headers": {
|
|
100
|
+
"Content-Type": "image/png",
|
|
101
|
+
"X-Flywheel-Artifact-Filename": "loss_curve.png"
|
|
102
|
+
},
|
|
103
|
+
"curl_command": "curl -sS -X PUT '...' -H 'Content-Type: image/png' -H 'X-Flywheel-Artifact-Filename: loss_curve.png' --data-binary @/absolute/path/to/file"
|
|
104
|
+
}
|
|
105
|
+
]
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
## Raw Upload Step
|
|
111
|
+
|
|
112
|
+
Execute each returned request exactly:
|
|
113
|
+
|
|
114
|
+
- Method: `PUT`
|
|
115
|
+
- URL: `batch.items[i].upload_url`
|
|
116
|
+
- Body: raw file bytes
|
|
117
|
+
- Headers:
|
|
118
|
+
- `Content-Type` (media type)
|
|
119
|
+
- `X-Flywheel-Artifact-Filename` (filename hint)
|
|
120
|
+
|
|
121
|
+
A successful upload:
|
|
122
|
+
|
|
123
|
+
- validates the uploaded bytes against the requested artifact type
|
|
124
|
+
- stages canonical payload JSON in blob storage
|
|
125
|
+
- returns `202 Accepted`
|
|
126
|
+
- does not yet append an artifact record to the node
|
|
127
|
+
|
|
128
|
+
## Finalize Request and Response
|
|
129
|
+
|
|
130
|
+
`POST /mcp/nodes/{node_id}/artifacts/uploads/finalize`
|
|
131
|
+
|
|
132
|
+
```json
|
|
133
|
+
{
|
|
134
|
+
"batch_token": "uuid"
|
|
135
|
+
}
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
Successful finalize:
|
|
139
|
+
|
|
140
|
+
- validates the batch is complete and still revision-compatible
|
|
141
|
+
- appends all staged artifacts to the node
|
|
142
|
+
- persists canonical payload JSON to `artifacts/nodes/{node_id}/{artifact_id}.json`
|
|
143
|
+
- bumps node revision once
|
|
144
|
+
- returns `{ "node": ..., "artifacts": [...] }`
|
|
145
|
+
|
|
146
|
+
## Artifact Preview Behavior
|
|
147
|
+
|
|
148
|
+
Artifact preview endpoint:
|
|
149
|
+
`GET /mcp/nodes/{node_id}/artifacts/{artifact_id}/preview`.
|
|
150
|
+
MCP tool: `flywheel_get_artifact_preview`.
|
|
151
|
+
|
|
152
|
+
- Preview reads canonical persisted payload blob (`storage_path`) only.
|
|
153
|
+
- No workspace dependency or local-file fallback is required.
|
|
154
|
+
- `data_url` in preview responses is render output only; never upload JSON
|
|
155
|
+
metadata wrappers.
|
|
156
|
+
- Preview-normalized types:
|
|
157
|
+
- `image` -> image payload with `data_url`
|
|
158
|
+
- `html` / `plotly_html` -> HTML payload
|
|
159
|
+
- `json` -> JSON payload
|
|
160
|
+
- `text` / `diff_carousel` and common text/code extensions -> text payload
|
|
161
|
+
|
|
162
|
+
## WebUI Artifact Payload Reads
|
|
163
|
+
|
|
164
|
+
When artifacts are projected through node responses, the server returns
|
|
165
|
+
normalized storage references for each artifact payload:
|
|
166
|
+
|
|
167
|
+
- `storage_path`: canonical blob path (for example
|
|
168
|
+
`artifacts/nodes/{node_id}/{artifact_id}.json`).
|
|
169
|
+
- `storage_url`: the single client/host read URL for that payload.
|
|
170
|
+
- All blob backends: `/blobs/{storage_path}` authenticated byte-serving
|
|
171
|
+
proxy after access checks.
|
|
172
|
+
|
|
173
|
+
Clients should read artifact bytes from `storage_url` only. `storage_path`
|
|
174
|
+
remains metadata/debug context and must not be reconstructed into fetch URLs by
|
|
175
|
+
clients. Payload loads are coordinated through a shared loader with in-flight
|
|
176
|
+
deduplication, cache reuse, and bounded fetch concurrency to avoid bursty
|
|
177
|
+
request storms and `429` backpressure under artifact-heavy nodes.
|
|
178
|
+
|
|
179
|
+
The node overview panel additionally avoids eager load spikes by defaulting to
|
|
180
|
+
collapsed mode for artifact-heavy nodes and deferring artifact rendering until
|
|
181
|
+
cards approach the viewport.
|
|
182
|
+
|
|
183
|
+
## Artifact Load Telemetry
|
|
184
|
+
|
|
185
|
+
The WebUI emits a batched first-party product analytics event,
|
|
186
|
+
`web_artifact_payload_batch`, through `POST /analytics/events`.
|
|
187
|
+
|
|
188
|
+
This event is intended for aggregate artifact read-path observability and
|
|
189
|
+
includes fields such as:
|
|
190
|
+
|
|
191
|
+
- load volume (`loads_started`, `loads_completed`, `loads_failed`)
|
|
192
|
+
- rate-limit incidence (`loads_429`)
|
|
193
|
+
- queue/load latency aggregates
|
|
194
|
+
- source mix (`/blobs/*` authenticated proxy)
|
|
195
|
+
- top per-node load/failure summaries in the batch window
|
|
196
|
+
|
|
197
|
+
## File Inventory Surfaces
|
|
198
|
+
|
|
199
|
+
Artifacts and attachments are exposed through two HTTP inventory endpoints:
|
|
200
|
+
|
|
201
|
+
- `GET /users/me/files` for account-wide browsing in Settings.
|
|
202
|
+
- `GET /nodes/{node_id}/files` for node lineage-scoped browsing in the node
|
|
203
|
+
details panel.
|
|
204
|
+
|
|
205
|
+
Inventory entries include source context (`node_id`, `execution_id`) so the UI
|
|
206
|
+
can jump directly to the originating node or execution.
|
|
207
|
+
|
|
208
|
+
## Common Invalid Payload Causes
|
|
209
|
+
|
|
210
|
+
- stale `expected_revision` at prepare or finalize time
|
|
211
|
+
- missing/invalid upload ticket
|
|
212
|
+
- expired upload ticket or batch
|
|
213
|
+
- upload body exceeds configured size limit
|
|
214
|
+
- uploaded bytes do not match requested artifact format (for example invalid
|
|
215
|
+
JSON)
|
|
216
|
+
- finalize called before every prepared upload is staged
|
|
217
|
+
- commit contract violations (for example empirical `completed` without
|
|
218
|
+
artifacts or `no_artifacts_reason`)
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
# Interfaces
|
|
2
|
+
|
|
3
|
+
Canonical reference for Flywheel user-facing interfaces and public contracts.
|
|
4
|
+
|
|
5
|
+
Last updated: 2026-03-21
|
|
6
|
+
|
|
7
|
+
## Primary Clients
|
|
8
|
+
|
|
9
|
+
- `project/flywheel-webui` - canonical web product UI
|
|
10
|
+
- `project/flywheel-api` - canonical programmatic client interface (local + HTTP)
|
|
11
|
+
- MCP hosts (Codex/Claude/ChatGPT) via `/mcp-server`
|
|
12
|
+
|
|
13
|
+
## Canonical Entity Model
|
|
14
|
+
|
|
15
|
+
All interfaces operate on the same core entities:
|
|
16
|
+
|
|
17
|
+
- node
|
|
18
|
+
- node edge (branch/merge graph links)
|
|
19
|
+
- artifact
|
|
20
|
+
- execution
|
|
21
|
+
- compute lease
|
|
22
|
+
- budget grant
|
|
23
|
+
|
|
24
|
+
Node snapshots are the canonical durable contract for resume, review, and
|
|
25
|
+
cross-client interoperability.
|
|
26
|
+
|
|
27
|
+
## Core HTTP Surface
|
|
28
|
+
|
|
29
|
+
### Node lifecycle and graph
|
|
30
|
+
|
|
31
|
+
- `GET /mcp/nodes`
|
|
32
|
+
- `GET /mcp/nodes/{node_id}`
|
|
33
|
+
- `GET /mcp/nodes/{node_id}/tree`
|
|
34
|
+
- `POST /mcp/nodes/stage/create`
|
|
35
|
+
- `PATCH /mcp/nodes/{node_id}/stage/update`
|
|
36
|
+
- `POST /mcp/nodes/{node_id}/commit`
|
|
37
|
+
- `POST /mcp/nodes/{node_id}/branch`
|
|
38
|
+
- `POST /mcp/nodes/merge`
|
|
39
|
+
- `DELETE /mcp/nodes/{node_id}`
|
|
40
|
+
- `POST /mcp/nodes/bulk-delete`
|
|
41
|
+
|
|
42
|
+
### Artifact lifecycle
|
|
43
|
+
|
|
44
|
+
- `POST /mcp/nodes/{node_id}/artifacts/uploads/prepare`
|
|
45
|
+
- `POST /mcp/nodes/{node_id}/artifacts/uploads/finalize`
|
|
46
|
+
- `GET /mcp/nodes/{node_id}/artifacts`
|
|
47
|
+
- `GET /mcp/nodes/{node_id}/artifacts/{artifact_id}`
|
|
48
|
+
- `GET /mcp/nodes/{node_id}/artifacts/{artifact_id}/preview`
|
|
49
|
+
- `DELETE /mcp/nodes/{node_id}/artifacts/{artifact_id}`
|
|
50
|
+
- `PUT /mcp/artifacts/uploads/{upload_id}`
|
|
51
|
+
|
|
52
|
+
### Execution lifecycle
|
|
53
|
+
|
|
54
|
+
- `POST /mcp/nodes/{node_id}/executions`
|
|
55
|
+
- `GET /mcp/nodes/{node_id}/executions`
|
|
56
|
+
- `POST /mcp/nodes/{node_id}/executions/{execution_id}/terminate`
|
|
57
|
+
|
|
58
|
+
### Compute catalog
|
|
59
|
+
|
|
60
|
+
- `GET /compute/providers`
|
|
61
|
+
- `GET /compute/offers`
|
|
62
|
+
- `GET /compute/offers/{provider}`
|
|
63
|
+
|
|
64
|
+
### Managed compute and budgets
|
|
65
|
+
|
|
66
|
+
- `GET /mcp/nodes/{node_id}/compute/options`
|
|
67
|
+
- `POST /mcp/nodes/{node_id}/compute/acquire`
|
|
68
|
+
- `GET /mcp/compute/status`
|
|
69
|
+
- `GET /mcp/compute/connection`
|
|
70
|
+
- `POST /mcp/compute/release`
|
|
71
|
+
- `POST /mcp/compute/release-all`
|
|
72
|
+
- `GET /mcp/nodes/{node_id}/budget/grants`
|
|
73
|
+
- `GET /mcp/nodes/{node_id}/budget/campaign-grants`
|
|
74
|
+
- `POST /mcp/nodes/{node_id}/budget/campaign-grants`
|
|
75
|
+
- `PATCH /mcp/nodes/{node_id}/budget/campaign-grants/{budget_grant_id}`
|
|
76
|
+
- `DELETE /mcp/nodes/{node_id}/budget/campaign-grants/{budget_grant_id}`
|
|
77
|
+
|
|
78
|
+
### Sharing, tags, and audit
|
|
79
|
+
|
|
80
|
+
- `GET /mcp/nodes/{node_id}/sharing`
|
|
81
|
+
- `PUT /mcp/nodes/{node_id}/sharing`
|
|
82
|
+
- `POST /mcp/nodes/sharing/bulk`
|
|
83
|
+
- `GET /mcp/nodes/{node_id}/audit`
|
|
84
|
+
- `POST /mcp/nodes/{root_node_id}/tags`
|
|
85
|
+
- `PATCH /mcp/nodes/{root_node_id}/tags/{tag_id}`
|
|
86
|
+
- `DELETE /mcp/nodes/{root_node_id}/tags/{tag_id}`
|
|
87
|
+
- `PUT /mcp/nodes/{node_id}/tags`
|
|
88
|
+
|
|
89
|
+
### Export and summaries
|
|
90
|
+
|
|
91
|
+
- `POST /mcp/export`
|
|
92
|
+
- `POST /mcp/import`
|
|
93
|
+
- `POST /mcp/export-summary`
|
|
94
|
+
- `POST /mcp/export-summary-stream`
|
|
95
|
+
- `POST /mcp/export-summary-pdf`
|
|
96
|
+
- `POST /mcp/export-summary-render-pdf`
|
|
97
|
+
|
|
98
|
+
### Auth and integrations
|
|
99
|
+
|
|
100
|
+
- `GET /auth/status`
|
|
101
|
+
- `GET /auth/accounts`
|
|
102
|
+
- `POST /auth/accounts/merge/source-proof`
|
|
103
|
+
- `POST /auth/accounts/merge/preview`
|
|
104
|
+
- `POST /auth/accounts/merge`
|
|
105
|
+
- `POST /auth/accounts/detach`
|
|
106
|
+
- `GET /auth/integrations/status`
|
|
107
|
+
- `PUT /auth/integrations/wandb`
|
|
108
|
+
- `PUT /auth/integrations/huggingface`
|
|
109
|
+
- `DELETE /auth/integrations/wandb`
|
|
110
|
+
- `DELETE /auth/integrations/huggingface`
|
|
111
|
+
|
|
112
|
+
### Analytics
|
|
113
|
+
|
|
114
|
+
- `POST /analytics/events`
|
|
115
|
+
- `GET /admin/analytics/kpis`
|
|
116
|
+
- `GET /admin/analytics/overview`
|
|
117
|
+
|
|
118
|
+
## MCP Tool Surface
|
|
119
|
+
|
|
120
|
+
### Discovery and sharing tools
|
|
121
|
+
|
|
122
|
+
- `flywheel_auth_status`
|
|
123
|
+
- `flywheel_get_credits_balance`
|
|
124
|
+
- `flywheel_list_nodes`
|
|
125
|
+
- `flywheel_get_node`
|
|
126
|
+
- `flywheel_get_node_tree`
|
|
127
|
+
- `flywheel_get_node_sharing`
|
|
128
|
+
- `flywheel_set_node_sharing`
|
|
129
|
+
- `flywheel_bulk_set_node_sharing`
|
|
130
|
+
- `flywheel_create_node_tag`
|
|
131
|
+
- `flywheel_update_node_tag`
|
|
132
|
+
- `flywheel_delete_node_tag`
|
|
133
|
+
- `flywheel_set_node_tag_assignments`
|
|
134
|
+
|
|
135
|
+
### Node and graph tools
|
|
136
|
+
|
|
137
|
+
- `flywheel_stage_node_create`
|
|
138
|
+
- `flywheel_stage_node_update`
|
|
139
|
+
- `flywheel_commit_node`
|
|
140
|
+
- `flywheel_branch_node`
|
|
141
|
+
- `flywheel_merge_nodes`
|
|
142
|
+
- `flywheel_delete_node`
|
|
143
|
+
- `flywheel_bulk_delete_nodes`
|
|
144
|
+
|
|
145
|
+
### Artifact tools
|
|
146
|
+
|
|
147
|
+
- `flywheel_prepare_artifact_uploads`
|
|
148
|
+
- `flywheel_finalize_artifact_uploads`
|
|
149
|
+
- `flywheel_list_artifacts`
|
|
150
|
+
- `flywheel_get_artifact`
|
|
151
|
+
- `flywheel_get_artifact_preview`
|
|
152
|
+
- `flywheel_delete_artifact`
|
|
153
|
+
|
|
154
|
+
### Execution tools
|
|
155
|
+
|
|
156
|
+
- `flywheel_launch_execution`
|
|
157
|
+
- `flywheel_list_executions`
|
|
158
|
+
- `flywheel_terminate_execution`
|
|
159
|
+
|
|
160
|
+
### Compute lease and budget tools
|
|
161
|
+
|
|
162
|
+
- `flywheel_compute_list_options`
|
|
163
|
+
- `flywheel_request_compute_grant_approval`
|
|
164
|
+
- `flywheel_list_compute_grants`
|
|
165
|
+
- `flywheel_compute_acquire`
|
|
166
|
+
- `flywheel_compute_status`
|
|
167
|
+
- `flywheel_compute_connection`
|
|
168
|
+
- `flywheel_compute_release`
|
|
169
|
+
- `flywheel_compute_release_all`
|
|
170
|
+
|
|
171
|
+
### Campaign budget tools
|
|
172
|
+
|
|
173
|
+
- `flywheel_list_campaign_budgets`
|
|
174
|
+
- `flywheel_create_campaign_budget`
|
|
175
|
+
- `flywheel_update_campaign_budget`
|
|
176
|
+
- `flywheel_revoke_campaign_budget`
|
|
177
|
+
|
|
178
|
+
### Contract, audit, and export tools
|
|
179
|
+
|
|
180
|
+
- `flywheel_get_contract`
|
|
181
|
+
- `flywheel_list_audit`
|
|
182
|
+
- `flywheel_summarize_node_tree`
|
|
183
|
+
- `flywheel_export_subgraph`
|
|
184
|
+
- `flywheel_import_subgraph`
|
|
185
|
+
- `flywheel_export_summary`
|
|
186
|
+
- `flywheel_export_summary_stream`
|
|
187
|
+
- `flywheel_export_summary_pdf`
|
|
188
|
+
- `flywheel_export_summary_render_pdf`
|
|
189
|
+
|
|
190
|
+
## Legacy Archival Export
|
|
191
|
+
|
|
192
|
+
Experimental settings keep legacy history export available as an archival
|
|
193
|
+
migration aid. This path is read-only and outside canonical node workflows.
|
|
194
|
+
|
|
195
|
+
## Related Docs
|
|
196
|
+
|
|
197
|
+
- `docs/flywheel/CONCEPT.md`
|
|
198
|
+
- `docs/flywheel/FLYWHEEL_MCP.md`
|
|
199
|
+
- `docs/flywheel/PROVISIONING.md`
|
|
200
|
+
- `docs/flywheel/ARTIFACTS.md`
|
|
201
|
+
- `docs/flywheel/GIT_INTEGRATION.md`
|