@paradigma-inc/flywheel 0.1.19 → 0.1.25

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 (56) hide show
  1. package/README.md +8 -0
  2. package/package.json +1 -1
  3. package/skills/flywheel/references/experiment-design-protocol.md +1 -1
  4. package/skills/flywheel/references/flywheel-mcp-tool-map.md +28 -33
  5. package/skills/flywheel/setting-up-flywheel/updating-flywheel-mcp.md +8 -0
  6. package/skills/flywheel-auto/SKILL.md +1 -1
  7. package/skills/flywheel-auto/references/ARTIFACTS.md +0 -1
  8. package/skills/flywheel-auto/references/INTERFACES.md +13 -9
  9. package/skills/flywheel-auto/references/experiment-design-protocol.md +1 -1
  10. package/skills/flywheel-auto/references/flywheel-mcp-tool-map.md +28 -33
  11. package/skills/flywheel-lookahead/SKILL.md +22 -15
  12. package/skills/flywheel-lookahead/agents/openai.yaml +3 -3
  13. package/skills/flywheel-lookahead/evals/evals.json +13 -1
  14. package/skills/flywheel-lookahead/references/ARTIFACTS.md +0 -1
  15. package/skills/flywheel-lookahead/references/INTERFACES.md +13 -9
  16. package/skills/flywheel-lookahead/references/flywheel-mcp-tool-map.md +28 -33
  17. package/skills/flywheel-prove/SKILL.md +163 -0
  18. package/skills/flywheel-prove/agents/interface.yaml +4 -0
  19. package/skills/flywheel-prove/assets/pipeline_template/bin/tproof +3 -0
  20. package/skills/flywheel-prove/assets/pipeline_template/bin/tproof.cmd +2 -0
  21. package/skills/flywheel-prove/assets/pipeline_template/logs/.gitkeep +1 -0
  22. package/skills/flywheel-prove/assets/pipeline_template/pyproject.toml +23 -0
  23. package/skills/flywheel-prove/assets/pipeline_template/scripts/smoke_test.cmd +2 -0
  24. package/skills/flywheel-prove/assets/pipeline_template/scripts/smoke_test.sh +3 -0
  25. package/skills/flywheel-prove/assets/pipeline_template/src/tproof/__init__.py +1 -0
  26. package/skills/flywheel-prove/assets/pipeline_template/src/tproof/cli.py +298 -0
  27. package/skills/flywheel-prove/assets/pipeline_template/src/tproof/constants.py +10 -0
  28. package/skills/flywheel-prove/assets/pipeline_template/src/tproof/layout.py +51 -0
  29. package/skills/flywheel-prove/assets/pipeline_template/src/tproof/leanops.py +116 -0
  30. package/skills/flywheel-prove/assets/pipeline_template/src/tproof/runstore.py +58 -0
  31. package/skills/flywheel-prove/assets/pipeline_template/src/tproof/tasking.py +94 -0
  32. package/skills/flywheel-prove/assets/pipeline_template/workspace/prompts/fill_sorries.txt +3 -0
  33. package/skills/flywheel-prove/references/workflow.md +193 -0
  34. package/skills/flywheel-prove/scripts/scaffold_pipeline.py +111 -0
  35. package/skills/flywheel-reproduce/SKILL.md +28 -23
  36. package/skills/flywheel-reproduce/evals/evals.json +7 -1
  37. package/skills/flywheel-reproduce/references/ARTIFACTS.md +0 -1
  38. package/skills/flywheel-reproduce/references/INTERFACES.md +13 -9
  39. package/skills/flywheel-reproduce/references/experiment-design-protocol.md +1 -1
  40. package/skills/flywheel-reproduce/references/flywheel-mcp-tool-map.md +28 -33
  41. package/skills/flywheel-reproduce/references/source-blog.md +35 -0
  42. package/skills/flywheel-reproduce/references/source-generic.md +30 -0
  43. package/skills/flywheel-reproduce/references/source-notes.md +35 -0
  44. package/skills/flywheel-reproduce/references/source-paper.md +89 -0
  45. package/skills/flywheel-reproduce/references/source-wiki.md +36 -0
  46. package/skills/flywheel-to-graph/SKILL.md +26 -21
  47. package/skills/flywheel-to-graph/evals/evals.json +7 -1
  48. package/skills/flywheel-to-graph/references/ARTIFACTS.md +0 -1
  49. package/skills/flywheel-to-graph/references/INTERFACES.md +13 -9
  50. package/skills/flywheel-to-graph/references/flywheel-mcp-tool-map.md +28 -33
  51. package/skills/flywheel-to-graph/references/source-blog.md +34 -0
  52. package/skills/flywheel-to-graph/references/source-generic.md +29 -0
  53. package/skills/flywheel-to-graph/references/source-notes.md +34 -0
  54. package/skills/flywheel-to-graph/references/source-paper.md +85 -0
  55. package/skills/flywheel-to-graph/references/source-wiki.md +35 -0
  56. package/src/cli.mjs +69 -3
@@ -0,0 +1,193 @@
1
+ # Workflow
2
+
3
+ ## 0. Prerequisite: Local Toolchain Bootstrap
4
+
5
+ Ensure the host has:
6
+ - `uv`
7
+ - `elan` (Lean toolchain manager)
8
+
9
+ If `uv` is missing, install it by OS:
10
+ - macOS/Linux:
11
+ ```bash
12
+ curl -LsSf https://astral.sh/uv/install.sh | sh
13
+ ```
14
+ - Windows (PowerShell):
15
+ ```powershell
16
+ irm https://astral.sh/uv/install.ps1 | iex
17
+ ```
18
+
19
+ If `elan` is missing, install it by OS:
20
+ - macOS/Linux:
21
+ ```bash
22
+ curl https://raw.githubusercontent.com/leanprover/elan/master/elan-init.sh -sSf | sh -s -- -y
23
+ ```
24
+ - Windows (PowerShell):
25
+ ```powershell
26
+ Invoke-WebRequest -Uri https://raw.githubusercontent.com/leanprover/elan/master/elan-init.ps1 -OutFile elan-init.ps1
27
+ powershell -ExecutionPolicy Bypass -File .\elan-init.ps1
28
+ ```
29
+
30
+ Verify bootstrap before running pipeline commands:
31
+
32
+ ```bash
33
+ uv --version
34
+ elan --version
35
+ lean --version
36
+ lake --version
37
+ ```
38
+
39
+ ## 1. Scaffold Pipeline Into Repo
40
+
41
+ ```bash
42
+ python <skill-root>/scripts/scaffold_pipeline.py --repo-root <repo-root> --setup-env
43
+ ```
44
+
45
+ `<skill-root>` is the directory that contains this skill.
46
+
47
+ Creates `<repo-root>/theorem_pipeline` with:
48
+ - `workspace/lean_project/` canonical cumulative Lean project
49
+ - `data/runs/` run metadata and proof briefs
50
+ - `logs/` local Lean verification logs
51
+ - `src/tproof/` local CLI orchestration
52
+
53
+ ## 2. Initialize Lean Toolchain
54
+
55
+ From `theorem_pipeline/`:
56
+
57
+ ```bash
58
+ uv run -m tproof.cli doctor
59
+ uv run -m tproof.cli init --build
60
+ ```
61
+
62
+ Warning: `init --build` can take several minutes the first time (toolchain/dependency download and initial compilation). Subsequent proving runs in the same workspace are usually much faster because those artifacts are cached.
63
+ Operator requirement: Before running `uv run -m tproof.cli init --build`, explicitly notify the human user in-chat about this first-run delay.
64
+
65
+ Pinned versions:
66
+ - Lean toolchain: `leanprover/lean4:v4.28.0`
67
+ - Mathlib hash: `8f9d9cff6bd728b17a24e163c9402775d9e6a365`
68
+
69
+ ## 2.1 Source Context Normalization (Conditional)
70
+
71
+ Handle source ingestion based on user-provided input type.
72
+
73
+ If input is a PDF:
74
+ - Use `pypdf` (not `pdftotext`) and sanitize mojibake with UTF-8-safe output before theorem formalization.
75
+ - Required output A (full cached extraction):
76
+ - `theorem_pipeline/workspace/contexts/<pdf_stem>.txt`
77
+ - Example: `paper.pdf -> theorem_pipeline/workspace/contexts/paper.txt`
78
+ - Required output B (theorem-focused excerpt):
79
+ - `theorem_pipeline/workspace/contexts/<theorem_slug>_source_excerpt.txt`
80
+ - Example: `proposition2_source_excerpt.txt`
81
+ - Keep both outputs:
82
+ - full extraction = reusable cache across multiple theorem proofs from the same paper;
83
+ - excerpt = focused context for the current theorem.
84
+ - Reuse policy:
85
+ - if the full extraction file already exists and is still valid for the current PDF, reuse it instead of converting the PDF again.
86
+
87
+ If input is not a PDF (prompt text, local `.txt`/`.md`/`.tex`, or fetched online source):
88
+ - Skip PDF conversion.
89
+ - Use the source as requested by the user.
90
+ - Store a normalized local source artifact under `theorem_pipeline/workspace/contexts/` (for example, `<theorem_slug>_source.txt`).
91
+ - Optionally store a focused excerpt as `<theorem_slug>_source_excerpt.txt` when useful for theorem-specific context.
92
+
93
+ ASCII rewrites of common symbols are allowed when needed for robust editing/parsing.
94
+
95
+ ## 3. Create a Proof Run
96
+
97
+ ```bash
98
+ uv run -m tproof.cli start-run --prompt-file ./workspace/prompts/fill_sorries.txt
99
+ ```
100
+
101
+ This writes:
102
+ - `data/runs/<run_id>/run.json`
103
+ - `data/runs/<run_id>/run_brief.md`
104
+ - snapshot of the Lean project for traceability
105
+
106
+ ## 4. Required Agent Routing
107
+
108
+ Use two workers:
109
+
110
+ 1. Proof worker (math-heavy):
111
+ - profile: deep-thinking reasoning model for complex mathematics
112
+ - responsibility: theorem proving, decomposition, and difficult Lean proof terms.
113
+
114
+ 2. Ops worker (programming/reporting):
115
+ - profile: smaller coding-oriented model for implementation and reporting
116
+ - responsibility: scripts, logs, verification loops, metadata updates, concise run reports.
117
+
118
+ ## 5. Iterate Until Clean Verification
119
+
120
+ After proof edits:
121
+
122
+ ```bash
123
+ uv run -m tproof.cli reindex
124
+ uv run -m tproof.cli verify
125
+ ```
126
+
127
+ `verify` fails on:
128
+ - `lake build` failures
129
+ - any unresolved `sorry`
130
+ - any `.lean`/`.md` final artifacts found under `workspace/staging/` (forbidden; move to `ProofWorkspace/Final/`)
131
+
132
+ When done, set run status:
133
+
134
+ ```bash
135
+ uv run -m tproof.cli set-status <run_id> COMPLETE --note "all goals proven and verified"
136
+ ```
137
+
138
+ ## 6. Final Artifact Placement and Sidecar Sketch Files (`.md`)
139
+
140
+ Final theorem artifacts must be written only under:
141
+ - `theorem_pipeline/workspace/lean_project/ProofWorkspace/Final/`
142
+
143
+ Forbidden output location:
144
+ - `workspace/staging/` for any final proof or sketch artifact.
145
+
146
+ For every finalized Lean proof file, create a sibling Markdown sketch file:
147
+ - Naming convention:
148
+ - full proof (Lean-safe filename): `ProofWorkspace/Final/<Name>Full.lean`
149
+ - sketch: `ProofWorkspace/Final/<Name>Sketch.md`
150
+ - example pair: `ProofWorkspace/Final/Proposition1Full.lean` and `ProofWorkspace/Final/Proposition1Sketch.md`
151
+ - Keep sidecars in the same module directory so paper authors can trace them easily.
152
+ - In sketch files, all mathematics must be written with LaTeX dollar syntax (`$...$` / `$$...$$`).
153
+ - The `Proof Sketch` section must be fluent mathematical prose (paper style), not a numbered recipe.
154
+
155
+ Recommended sidecar template:
156
+
157
+ ```md
158
+ # <Theorem Name>
159
+
160
+ ## Statement
161
+ Plain-language statement mapped to the Lean theorem name(s).
162
+
163
+ ## Assumptions
164
+ - A1
165
+ - A2
166
+ - ...
167
+
168
+ ## Proof Sketch
169
+ Write a concise, fluent paragraph (or short sequence of paragraphs) as a mathematician would explain the proof to another mathematician in a paper. Emphasize the key reductions and ideas, but avoid low-level proof script details.
170
+
171
+ Use inline/display LaTeX where needed, for example:
172
+ `By reducing the claim to $X$, applying $Y$, and combining with $Z$, we obtain the target bound $f(x) \le g(x)$ for all $x \in D$.`
173
+
174
+ ## Corollaries (if required)
175
+ - help
176
+ - match
177
+ - upper-bound
178
+
179
+ ## Lean Artifacts
180
+ - File: <path/to/ProofWorkspace/Final/NameFull.lean>
181
+ - Theorems:
182
+ - <theorem_name_1>
183
+ - <theorem_name_2>
184
+ ```
185
+
186
+ Compatibility note:
187
+ - The pipeline indexes/checks only `*.lean` files (`reindex`, module discovery, and `sorry` scan), so `.md` sidecars do not affect Lean verification.
188
+
189
+ ## 7. Final Report Status Line
190
+
191
+ Keep the existing report format, and append one additional final line:
192
+ - `SUCCESS`
193
+ - or `FAIL: <reason>`
@@ -0,0 +1,111 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Scaffold a local Lean theorem proving pipeline into a target repository.
4
+ """
5
+
6
+ from __future__ import annotations
7
+
8
+ import argparse
9
+ import shutil
10
+ import subprocess
11
+ from pathlib import Path
12
+
13
+
14
+ def run(command: list[str], cwd: Path) -> None:
15
+ proc = subprocess.run(command, cwd=cwd, text=True, check=False)
16
+ if proc.returncode != 0:
17
+ raise RuntimeError(f"Command failed ({proc.returncode}): {' '.join(command)}")
18
+
19
+
20
+ def scaffold(repo_root: Path, subdir: str, force: bool) -> Path:
21
+ skill_root = Path(__file__).resolve().parents[1]
22
+ template_dir = skill_root / "assets" / "pipeline_template"
23
+ if not template_dir.is_dir():
24
+ raise FileNotFoundError(f"Missing template directory: {template_dir}")
25
+
26
+ target = (repo_root / subdir).resolve()
27
+ if target.exists():
28
+ if not force:
29
+ raise FileExistsError(
30
+ f"Target already exists: {target}. Pass --force to replace it."
31
+ )
32
+ if target == repo_root.resolve():
33
+ raise RuntimeError("Refusing to delete repo root.")
34
+ shutil.rmtree(target)
35
+
36
+ shutil.copytree(template_dir, target)
37
+ return target
38
+
39
+
40
+ def ensure_uv_available() -> None:
41
+ proc = subprocess.run(
42
+ ["uv", "--version"], capture_output=True, text=True, check=False
43
+ )
44
+ if proc.returncode != 0:
45
+ raise RuntimeError(
46
+ "Missing `uv` on PATH. Install uv first: https://docs.astral.sh/uv/getting-started/installation/"
47
+ )
48
+
49
+
50
+ def setup_env_with_uv(pipeline_dir: Path) -> None:
51
+ ensure_uv_available()
52
+ run(["uv", "sync"], cwd=pipeline_dir)
53
+
54
+
55
+ def parse_args() -> argparse.Namespace:
56
+ parser = argparse.ArgumentParser(
57
+ description="Scaffold local Lean theorem proving pipeline."
58
+ )
59
+ parser.add_argument(
60
+ "--repo-root",
61
+ type=Path,
62
+ default=Path.cwd(),
63
+ help="Repository root where the pipeline folder will be created.",
64
+ )
65
+ parser.add_argument(
66
+ "--subdir",
67
+ type=str,
68
+ default="theorem_pipeline",
69
+ help="Subdirectory name for the pipeline workspace.",
70
+ )
71
+ parser.add_argument(
72
+ "--force",
73
+ action="store_true",
74
+ help="Replace target directory if it already exists.",
75
+ )
76
+ parser.add_argument(
77
+ "--setup-env",
78
+ action="store_true",
79
+ help="Run `uv sync` in the scaffolded pipeline directory.",
80
+ )
81
+ return parser.parse_args()
82
+
83
+
84
+ def main() -> int:
85
+ args = parse_args()
86
+ repo_root = args.repo_root.resolve()
87
+ repo_root.mkdir(parents=True, exist_ok=True)
88
+
89
+ pipeline_dir = scaffold(repo_root=repo_root, subdir=args.subdir, force=args.force)
90
+ if args.setup_env:
91
+ setup_env_with_uv(pipeline_dir)
92
+
93
+ print(f"[OK] Scaffolded pipeline at: {pipeline_dir}")
94
+ print("Next commands:")
95
+ print(f" cd {pipeline_dir}")
96
+ if not args.setup_env:
97
+ print(" uv sync")
98
+ print(" uv run -m tproof.cli doctor")
99
+ print(" uv run -m tproof.cli init --build")
100
+ print(
101
+ " uv run -m tproof.cli start-run --prompt-file ./workspace/prompts/fill_sorries.txt"
102
+ )
103
+ print(" uv run -m tproof.cli verify")
104
+ print("Optional wrappers:")
105
+ print(" macOS/Linux: ./bin/tproof doctor")
106
+ print(" Windows cmd: .\\bin\\tproof.cmd doctor")
107
+ return 0
108
+
109
+
110
+ if __name__ == "__main__":
111
+ raise SystemExit(main())
@@ -57,8 +57,10 @@ Before execution, recover or establish these inputs:
57
57
  - Later reproduce passes must read the control node `content` first and continue from that persisted contract rather than from chat memory.
58
58
  3. Classify the source.
59
59
  - If the input is already a normalized Flywheel graph export, `flywheel_import_subgraph` may be appropriate.
60
- - If it is a markdown wiki, README corpus, blog post, or paper, port it explicitly with node and artifact tools before execution.
61
- - If it is a claim-bearing paper or benchmark result, split the work into explicit validation branches rather than treating the whole source as one flat note.
60
+ - Otherwise, route to one source reference in `references/` using the
61
+ `Source Type Routing` section below.
62
+ - Complete source decomposition from the selected reference before step 8
63
+ branch planning or execution.
62
64
  4. Map each stable page, claim, or concept to a node.
63
65
  - For exact node-mutation shapes, load [references/flywheel-mcp-tool-map.md](references/flywheel-mcp-tool-map.md).
64
66
  - Create a new node with `flywheel_stage_node_create` when needed.
@@ -80,7 +82,7 @@ Before execution, recover or establish these inputs:
80
82
  - Prefer explicit validation branches such as baseline checks, mechanism or intermediate-signal checks, ablations, efficiency checks, robustness checks, failure analysis, and follow-up analysis branches after results land.
81
83
  - If the branch can run through Flywheel execution directly, use `flywheel_launch_execution` and inspect terminal status before commit.
82
84
 
83
- - If the branch needs managed compute, use `flywheel_request_compute_grant_approval`, resolve the approved `compute_grant_id` with `flywheel_list_compute_grants` or `flywheel_list_approval_sessions`, call `flywheel_compute_list_options`, recommend one offer deterministically and present up to two alternatives, wait for explicit user confirmation (or explicit user override offer id), then `flywheel_compute_acquire`, poll `flywheel_compute_status`, and use `flywheel_compute_connection` when the lease is ready.
85
+ - If the branch needs managed compute, use `flywheel_request_compute_grant_approval`, resolve the approved `compute_grant_id` with `flywheel_list_compute_grants(status=active, approval_session_id=<session_id>)`, call `flywheel_compute_list_options`, recommend one offer deterministically and present up to two alternatives, wait for explicit user confirmation (or explicit user override offer id), then `flywheel_compute_acquire`, poll `flywheel_compute_status`, and use `flywheel_compute_connection` when the lease is ready.
84
86
  - Release managed compute when a branch is done. Default to releasing only
85
87
  known leases. Use `flywheel_compute_release_all` only when the user
86
88
  explicitly requests account-wide cleanup.
@@ -133,35 +135,38 @@ Canonical contract shape:
133
135
 
134
136
  The `Source or claim nodes under test` line is the recovery anchor for later validation passes. If multiple claim nodes are in scope, list the governing node ids or slugs explicitly.
135
137
 
136
- ## Wiki Porting
138
+ ## Source Type Routing
137
139
 
138
- Use this guide when the source material is a markdown wiki, README corpus, or a Karpathy-style LLM wiki that should become Flywheel nodes. In the flywheel-reproduce skill, do this graphification pass before empirical execution starts.
140
+ Route every non-normalized source through one reference file before
141
+ graphification and validation planning.
139
142
 
140
- ### Default Mapping
143
+ Routing order:
141
144
 
142
- - One wiki page or stable concept -> one Flywheel node.
143
- - The main page markdown -> the node body/readme field (`content`).
144
- - A short synopsis of the page -> `summary`.
145
- - Images, PDFs, datasets, notebooks, code snippets, and other supporting files -> node artifacts.
146
- - Durable structural relationships -> graph edges.
147
- - Ordinary wiki hyperlinks -> remain markdown links inside the node body.
145
+ 1. Deterministic routing.
146
+ 2. Natural-language routing.
147
+ 3. Generic fallback.
148
148
 
149
- Do not try to preserve the source wiki as a file-first mirror inside Flywheel. Flywheel is node-first.
149
+ Deterministic routing rules:
150
150
 
151
- ### What The Model Should Do
151
+ - Local `.pdf` files -> `references/source-paper.md`
152
+ - `arxiv.org/abs/*`, `arxiv.org/pdf/*`, DOI URLs, direct PDF URLs -> `references/source-paper.md`
153
+ - Markdown files, wiki exports, wiki-like repositories -> `references/source-wiki.md`
154
+ - Blog/article domains and long-form article URLs -> `references/source-blog.md`
155
+ - Local notes trees (Obsidian, Logseq, plain markdown note directories) -> `references/source-notes.md`
152
156
 
153
- Assume the model is expected to perform the port directly unless the user explicitly asks to build a dedicated importer.
157
+ Natural-language routing rule:
154
158
 
155
- That means:
159
+ - If deterministic routing is inconclusive, use user intent from prompt/context
160
+ (for example, "import this paper", "graph this wiki", "convert this blog
161
+ post", "port these research notes") and pick the matching source reference.
156
162
 
157
- 1. Read the source pages and supporting files.
158
- 2. Create or update nodes explicitly.
159
- 3. Write the page body into node `content`.
160
- 4. Publish supporting files as artifacts.
161
- 5. Add only the graph edges that materially help reasoning or navigation.
162
- 6. Split the claim-bearing work into explicit validation branches before execution.
163
+ Generic fallback rule:
163
164
 
164
- Do not wait for a magical bulk-import surface if the available Flywheel primitives are already enough.
165
+ - If deterministic and natural-language routing are both inconclusive, load
166
+ `references/source-generic.md`.
167
+
168
+ After choosing a source type, load that reference and complete source
169
+ decomposition before entering step 8 validation branch planning.
165
170
 
166
171
  ## `flywheel_import_subgraph`
167
172
 
@@ -2,7 +2,13 @@
2
2
  {
3
3
  "id": "claim-bearing-paper-with-no-budget-yet",
4
4
  "prompt": "Use $flywheel-reproduce to validate the central empirical claims from this paper in Flywheel. I have not given you a max budget yet, but I do want the source structured and the validation plan prepared.",
5
- "expected_output": "Graphify the source and plan explicit validation branches, ask once for a hard max budget before any compute acquisition, and avoid empirical execution until the budget is explicit.",
5
+ "expected_output": "Create a parent paper node under the requested root, decompose the paper into section child nodes, keep section narratives in each child `content`, attach the PDF to the parent node, and stage explicit validation branch plans. Ask once for a hard max budget before any compute acquisition, and do not execute branches until the budget is explicit. Do NOT produce a single `insight` node with the PDF as the only artifact.",
6
+ "files": []
7
+ },
8
+ {
9
+ "id": "paper-pdf-decomposes-into-section-children",
10
+ "prompt": "Use $flywheel-reproduce on the paper PDF in the current folder, attach results under an existing root, plan validation branches, and do not launch execution yet.",
11
+ "expected_output": "Create a parent paper node under the root, add one child node per top-level paper section, place section narratives in child `content`, and attach the PDF artifact on the parent. Plan at least one explicit validation branch and keep execution unlaunched until budget gating is satisfied. Do NOT emit a single `insight` node with only a summary and the PDF artifact.",
6
12
  "files": []
7
13
  },
8
14
  {
@@ -43,7 +43,6 @@ Canonical artifact upload/finalize contract derived from `mcp_contract.py`.
43
43
 
44
44
  - Stale `expected_revision` on mutating calls returns `409` and requires explicit reconciliation.
45
45
  - Reusing an idempotency key with a different payload hash causes `409_conflict`.
46
- - Empirical `completed` commits must satisfy one of: `artifacts_non_empty`, `no_artifacts_reason_non_empty`.
47
46
  - Prepare item payloads must be structured objects; stringified JSON item payloads are invalid.
48
47
  - Uploading metadata wrappers instead of raw file bytes violates the upload contract.
49
48
  - Finalize requires a valid prepared batch token and staged uploads from that batch.
@@ -9,10 +9,10 @@ Canonical reference for Flywheel MCP public interfaces and contract pointers.
9
9
  - Section order:
10
10
  - `quickstart` (Quickstart): Recommended first calls and section read order for onboarding.
11
11
  - `graph` (Graph): Node model, graph topology guidance, and durable behavior rules.
12
- - `lifecycle` (Lifecycle): Lifecycle operations, commit-time validation requirements, and reproducibility guidance.
12
+ - `stage_commit` (Stage and commit): Stage/commit operations, commit-time validation requirements, and reproducibility guidance.
13
13
  - `sharing` (Sharing): Sharing modes, derived visibility, collaborator roles, and query translation.
14
14
  - `artifacts` (Artifacts): Prepare/upload/finalize requirements and artifact type rules.
15
- - `compute` (Compute): Lease ownership, approval session, and budget source semantics.
15
+ - `compute` (Compute): Lease ownership, token-scoped control, approval session, and budget source semantics.
16
16
  - `compute/troubleshooting_v1` (Compute Troubleshooting v1): Provider-specific acquire/retry hints for launch kwargs and request tuning.
17
17
  - `campaign` (Campaign Contract): Campaign projection and budget contracts plus template section pointers.
18
18
 
@@ -50,10 +50,12 @@ Canonical reference for Flywheel MCP public interfaces and contract pointers.
50
50
  - `flywheel_get_campaign_snapshot` (read; scopes: `read`; core surface; binding: `operation`)
51
51
  - `flywheel_list_audit` (read; scopes: `read`; full-surface only; binding: `operation`)
52
52
 
53
- ### Node lifecycle
53
+ ### Node stage and commit
54
54
 
55
- - `flywheel_stage_node_create` (mutating; scopes: `write`; full-surface only; binding: `operation`)
56
- - `flywheel_stage_node_update` (mutating; scopes: `write`; core surface; binding: `operation`)
55
+ - `flywheel_commit_new_node` (mutating; scopes: `write`; full-surface only; binding: `operation`)
56
+ - `flywheel_acquire_stage_lease` (mutating; scopes: `write`; full-surface only; binding: `operation`)
57
+ - `flywheel_heartbeat_stage_lease` (mutating; scopes: `write`; full-surface only; binding: `operation`)
58
+ - `flywheel_release_stage_lease` (mutating; scopes: `write`; full-surface only; binding: `operation`)
57
59
  - `flywheel_commit_node` (mutating; scopes: `write`; core surface; binding: `operation`)
58
60
  - `flywheel_branch_node` (mutating; scopes: `write`; full-surface only; binding: `operation`)
59
61
  - `flywheel_merge_nodes` (mutating; scopes: `write`; full-surface only; binding: `operation`)
@@ -132,10 +134,12 @@ Canonical reference for Flywheel MCP public interfaces and contract pointers.
132
134
  - `GET /mcp/nodes/{node_id}/campaign/snapshot` -> `flywheel_get_campaign_snapshot`
133
135
  - `GET /mcp/nodes/{node_id}/audit` -> `flywheel_list_audit`
134
136
 
135
- ### Node lifecycle
137
+ ### Node stage and commit
136
138
 
137
- - `POST /mcp/nodes/stage/create` -> `flywheel_stage_node_create`
138
- - `PATCH /mcp/nodes/{node_id}/stage/update` -> `flywheel_stage_node_update`
139
+ - `POST /mcp/nodes/commit-new` -> `flywheel_commit_new_node`
140
+ - `POST /mcp/nodes/{node_id}/stage/lease/acquire` -> `flywheel_acquire_stage_lease`
141
+ - `POST /mcp/nodes/{node_id}/stage/lease/heartbeat` -> `flywheel_heartbeat_stage_lease`
142
+ - `POST /mcp/nodes/{node_id}/stage/lease/release` -> `flywheel_release_stage_lease`
139
143
  - `POST /mcp/nodes/{node_id}/commit` -> `flywheel_commit_node`
140
144
  - `POST /mcp/nodes/{node_id}/branch` -> `flywheel_branch_node`
141
145
  - `POST /mcp/nodes/merge` -> `flywheel_merge_nodes`
@@ -173,7 +177,7 @@ Canonical reference for Flywheel MCP public interfaces and contract pointers.
173
177
  - `POST /mcp/nodes/{root_node_id}/campaign-budgets` -> `flywheel_create_campaign_budget`
174
178
  - `PATCH /mcp/nodes/{root_node_id}/campaign-budgets/{compute_budget_id}` -> `flywheel_update_campaign_budget`
175
179
  - `DELETE /mcp/nodes/{root_node_id}/campaign-budgets/{compute_budget_id}` -> `flywheel_revoke_campaign_budget`
176
- - `POST /mcp/nodes/{node_id}/compute/acquire` -> `flywheel_compute_acquire`
180
+ - `tool-mediated` -> `flywheel_compute_acquire`
177
181
  - `POST /mcp/compute/release` -> `flywheel_compute_release`
178
182
  - `POST /mcp/compute/release-all` -> `flywheel_compute_release_all`
179
183
 
@@ -141,7 +141,7 @@ Typical flow:
141
141
  1. `mcp__flywheel__flywheel_branch_node` or `mcp__flywheel__flywheel_stage_node_create`
142
142
  2. `mcp__flywheel__flywheel_stage_node_update` with the explicit run summary and the local question or hypothesis for that branch
143
143
  3. `mcp__flywheel__flywheel_request_compute_grant_approval` only after the user accepts the design
144
- 4. `mcp__flywheel__flywheel_list_compute_grants` or `mcp__flywheel__flywheel_list_approval_sessions` when you need to resolve the approved `compute_grant_id`
144
+ 4. `mcp__flywheel__flywheel_list_compute_grants(status=active, approval_session_id=<session_id>)` when you need to resolve the approved `compute_grant_id`
145
145
  5. `mcp__flywheel__flywheel_compute_acquire` and related compute tools only when execution is actually needed
146
146
  6. `mcp__flywheel__flywheel_prepare_artifact_uploads`, raw upload to the returned signed URLs, then `mcp__flywheel__flywheel_finalize_artifact_uploads`
147
147
  7. Do a brief epistemic check before commit: verify what the evidence actually shows, whether it matches the interpretation rule from the brief, and whether any gap between the data and the hoped-for story needs to be named explicitly in the node summary.
@@ -12,13 +12,6 @@ Flywheel is a graph-based system for tracking research work, decisions, and evid
12
12
  - Node references include immutable `node_id` and optional immutable `slug_name`; prefer communicating both together for human clarity and disambiguation.
13
13
  - Insight nodes should represent conceptual observations (theoretical insights, intuitions, motivations, decision-relevant framing); empirical nodes should represent experiments with explicit hypotheses and measured outcomes.
14
14
  - Graph topology should encode logical/causal relations between concepts and experiments. Avoid defaulting to shallow root-only branching unless work items are truly independent.
15
- - Node lifecycle semantics are interface-agnostic (`stage_node_create`, `stage_node_update`, `commit_node`); MCP tools are one projection of this shared contract.
16
- - Mutating node writes are optimistic-locking operations: read latest state, pass `expected_revision`, and handle `409 conflict` with explicit reconciliation.
17
- - Mutating operations are idempotent; MCP tool transport auto-manages `Idempotency-Key` on mutating tool calls.
18
- - Commit is finalize-only: commit requests require `expected_revision` and may optionally override `summary`; committed node state must still satisfy strict contract (`summary`/`outcome`, `empirical+completed` requires artifacts or `no_artifacts_reason`, `insight` requires non-empty insights).
19
- - When code is involved, pass `repo_url`/`branch_name`/`head_commit_sha` and align git structure with graph topology where practical (without forcing one-to-one mapping).
20
- - Summaries, hypotheses, and artifacts should be reproduction-grade: enough setup, method, evidence, and interpretation for another reader to reproduce or audit results.
21
- - Empirical workflow is hypothesis-driven: launch execution, inspect outcomes, publish evidence artifacts, and commit only after terminal status.
22
15
  - For empirical work, publish evidence with `flywheel_prepare_artifact_uploads`, upload raw file bytes, then `flywheel_finalize_artifact_uploads` before commit.
23
16
  - Artifact metadata records expose a non-empty `title` suitable for display labels; title normalization must never derive from `storage_url`.
24
17
 
@@ -47,11 +40,13 @@ Flywheel is a graph-based system for tracking research work, decisions, and evid
47
40
  - `flywheel_get_campaign_snapshot` (read; scopes: `read`; HTTP: `GET /mcp/nodes/{node_id}/campaign/snapshot`; core surface): Read the current campaign snapshot for a node's root campaign, including configured views and derived records.
48
41
  - `flywheel_list_audit` (read; scopes: `read`; HTTP: `GET /mcp/nodes/{node_id}/audit`; full-surface only): List node MCP audit events.
49
42
 
50
- ### Node lifecycle
43
+ ### Node stage and commit
51
44
 
52
- - `flywheel_stage_node_create` (mutating; scopes: `write`; HTTP: `POST /mcp/nodes/stage/create`; full-surface only): Stage creation of a new Flywheel node.
53
- - `flywheel_stage_node_update` (mutating; scopes: `write`; HTTP: `PATCH /mcp/nodes/{node_id}/stage/update`; core surface): Stage mutable node fields, including content/readme text, with optimistic locking; use `no_artifacts_reason` when empirical completed nodes intentionally have no artifacts.
54
- - `flywheel_commit_node` (mutating; scopes: `write`; HTTP: `POST /mcp/nodes/{node_id}/commit`; core surface): Commit a node with contract validation.
45
+ - `flywheel_commit_new_node` (mutating; scopes: `write`; HTTP: `POST /mcp/nodes/commit-new`; full-surface only): Commit a locally staged new node into canonical storage and return the persisted node.
46
+ - `flywheel_acquire_stage_lease` (mutating; scopes: `write`; HTTP: `POST /mcp/nodes/{node_id}/stage/lease/acquire`; full-surface only): Acquire a session-scoped stage lease for an existing node before local staged edits.
47
+ - `flywheel_heartbeat_stage_lease` (mutating; scopes: `write`; HTTP: `POST /mcp/nodes/{node_id}/stage/lease/heartbeat`; full-surface only): Refresh the active stage lease for the current editing session.
48
+ - `flywheel_release_stage_lease` (mutating; scopes: `write`; HTTP: `POST /mcp/nodes/{node_id}/stage/lease/release`; full-surface only): Release the active stage lease for the current editing session.
49
+ - `flywheel_commit_node` (mutating; scopes: `write`; HTTP: `POST /mcp/nodes/{node_id}/commit`; core surface): Commit an existing node by publishing the caller's staged payload under an active stage lease.
55
50
  - `flywheel_branch_node` (mutating; scopes: `write`; HTTP: `POST /mcp/nodes/{node_id}/branch`; full-surface only): Create a child branch node.
56
51
  - `flywheel_merge_nodes` (mutating; scopes: `write`; HTTP: `POST /mcp/nodes/merge`; full-surface only): Merge nodes with caller-resolved node payload.
57
52
  - `flywheel_add_parent` (mutating; scopes: `write`; HTTP: `POST /mcp/nodes/{node_id}/parents/add`; full-surface only): Attach an additional parent edge to an existing node (keeps node identity, validates against cycles).
@@ -77,20 +72,20 @@ Flywheel is a graph-based system for tracking research work, decisions, and evid
77
72
  ### Compute and budgets
78
73
 
79
74
  - `flywheel_compute_list_options` (read; scopes: `compute`; HTTP: `GET /mcp/nodes/{node_id}/compute/options`; core surface): List managed compute options allowed for a node. When using grant-backed compute, pass the same compute_grant_id you will use for acquire.
80
- - `flywheel_compute_status` (read; scopes: `compute`; HTTP: `GET /mcp/compute/status`; core surface): Read managed compute lease status for the current user. Lease rows include ownership flags so hosts can distinguish user-owned leases from sponsor-visible campaign leases. When checking a grant-backed lease, reuse the same compute_grant_id passed to acquire.
81
- - `flywheel_compute_connection` (read; scopes: `compute`; HTTP: `GET /mcp/compute/connection`; core surface): Read SSH connection material for an active managed compute lease once flywheel_compute_status indicates the lease is usable. Only leases owned by the current user are connectable. Pass lease_id or node_id to disambiguate when needed.
75
+ - `flywheel_compute_status` (read; scopes: `compute`; HTTP: `GET /mcp/compute/status`; core surface): Read managed compute lease status for the current user and current lease_control_token scope. Lease rows include ownership flags so hosts can distinguish user-owned leases from sponsor-visible campaign leases. When checking a grant-backed lease, reuse the same compute_grant_id passed to acquire.
76
+ - `flywheel_compute_connection` (read; scopes: `compute`; HTTP: `GET /mcp/compute/connection`; core surface): Read SSH connection material for an active managed compute lease once flywheel_compute_status indicates the lease is usable. This tool is token-scoped to lease_control_token and only leases owned by the current user are connectable. Pass lease_id or node_id to disambiguate when needed.
82
77
  - `flywheel_approval_session_heartbeat` (read; scopes: `compute`; HTTP: `POST /mcp/approval-sessions/heartbeat`; core surface): Create or refresh a compute-grant approval session for the current MCP host session.
83
- - `flywheel_list_approval_sessions` (read; scopes: `compute`; HTTP: `GET /mcp/approval-sessions`; core surface): List approval sessions visible to the current user. Optionally include grant approval bindings for each session.
84
- - `flywheel_expire_approval_session` (mutating; scopes: `compute`; HTTP: `POST /mcp/approval-sessions/expire`; core surface): Expire the current compute-grant approval session and release its active leases.
85
- - `flywheel_request_compute_grant_approval` (mutating; scopes: `compute`; HTTP: `tool-mediated`; core surface): Request budget approval and return approval_url + request_id for user confirmation before managed compute acquisition.
78
+ - `flywheel_list_approval_sessions` (read; scopes: `compute`; HTTP: `GET /mcp/approval-sessions`; core surface): List approval sessions visible to the current user.
79
+ - `flywheel_expire_approval_session` (mutating; scopes: `compute`; HTTP: `POST /mcp/approval-sessions/expire`; core surface): Expire the current compute-grant approval session context without releasing active leases.
80
+ - `flywheel_request_compute_grant_approval` (mutating; scopes: `compute`; HTTP: `tool-mediated`; core surface): Request budget approval context before managed compute acquisition; branch on response status.
86
81
  - `flywheel_list_compute_grants` (read; scopes: `compute`; HTTP: `GET /mcp/compute/grants`; core surface): List active/exhausted compute grants available to the current user.
87
82
  - `flywheel_list_campaign_budgets` (read; scopes: `compute`; HTTP: `GET /mcp/nodes/{root_node_id}/campaign-budgets`; full-surface only): List campaign compute budgets for a campaign root. Organizer-only management view.
88
83
  - `flywheel_create_campaign_budget` (mutating; scopes: `compute`; HTTP: `POST /mcp/nodes/{root_node_id}/campaign-budgets`; full-surface only): Create an organizer-funded campaign compute budget shared with participants.
89
84
  - `flywheel_update_campaign_budget` (mutating; scopes: `compute`; HTTP: `PATCH /mcp/nodes/{root_node_id}/campaign-budgets/{compute_budget_id}`; full-surface only): Update hard caps or metadata for an organizer-funded campaign compute budget.
90
85
  - `flywheel_revoke_campaign_budget` (mutating; scopes: `compute`; HTTP: `DELETE /mcp/nodes/{root_node_id}/campaign-budgets/{compute_budget_id}`; full-surface only): Revoke an organizer-funded campaign compute budget.
91
- - `flywheel_compute_acquire` (mutating; scopes: `compute`; HTTP: `POST /mcp/nodes/{node_id}/compute/acquire`; core surface): Acquire managed compute for a node with explicit SKU + region and required compute_grant_id (returns accepted/completed lease state only; poll flywheel_compute_status for readiness, not SSH key material). This tool heartbeats and forwards approval_session_id.
92
- - `flywheel_compute_release` (mutating; scopes: `compute`; HTTP: `POST /mcp/compute/release`; core surface): Asynchronously release one managed compute lease by lease_id.
93
- - `flywheel_compute_release_all` (mutating; scopes: `compute`; HTTP: `POST /mcp/compute/release-all`; core surface): Asynchronously release all active managed compute leases for the current user.
86
+ - `flywheel_compute_acquire` (mutating; scopes: `compute`; HTTP: `tool-mediated`; core surface): Acquire managed compute for a node with explicit SKU + region and required compute_grant_id (returns accepted/completed lease state only; poll flywheel_compute_status for readiness, not SSH key material). This tool forwards approval_session_id.
87
+ - `flywheel_compute_release` (mutating; scopes: `compute`; HTTP: `POST /mcp/compute/release`; core surface): Asynchronously release one managed compute lease by lease_id within the current lease_control_token scope.
88
+ - `flywheel_compute_release_all` (mutating; scopes: `compute`; HTTP: `POST /mcp/compute/release-all`; core surface): Asynchronously release active managed compute leases in the current lease_control_token scope; set force=true for explicit account-wide cleanup for the current user.
94
89
 
95
90
  ### Contract, audit, and export
96
91
 
@@ -113,15 +108,15 @@ Flywheel is a graph-based system for tracking research work, decisions, and evid
113
108
  ### Safe Node Update
114
109
 
115
110
  1. `flywheel_get_node`: Read latest node state before mutating fields.
116
- 2. `flywheel_stage_node_update`: Stage changes with fresh expected_revision and resolve 409 conflicts explicitly.
117
- 3. `flywheel_commit_node`: Commit once terminal and contract-complete.
111
+ 2. `flywheel_acquire_stage_lease`: Acquire a session-scoped stage lease before editing an existing node locally.
112
+ 3. `flywheel_commit_node`: Commit with `stage_session_id`, `base_committed_revision`, and full `staged_payload` once terminal and contract-complete.
118
113
 
119
114
  ### Empirical Workflow
120
115
 
121
- 1. `flywheel_stage_node_create`: Create a staged node, then set empirical fields before execution.
122
- 2. `flywheel_stage_node_update`: Set `kind=empirical`, `hypothesis`, and summary fields with fresh `expected_revision`.
123
- 3. `flywheel_request_compute_grant_approval`: If compute is needed, request budget approval first. Response status is `approval_required`.
124
- 4. Branch on `flywheel_request_compute_grant_approval.status`: Branch by response status. `approval_required` is a response state, not a request parameter.. if `approval_required` then `present_approval_url_to_user`: Present `approval_url` to the user; the user opens it and confirms budget approval.; `flywheel_list_approval_sessions`: After approval, list approval sessions with include_approvals=true and use the active `compute_grant_id` for the current approval_session_id.
116
+ 1. `flywheel_commit_new_node`: Commit a local staged new node to canonical storage as the first persistence boundary.
117
+ 2. `flywheel_commit_node`: Commit staged empirical fields with `stage_session_id`, `base_committed_revision`, and a full `staged_payload` once the working state is ready to publish.
118
+ 3. `flywheel_request_compute_grant_approval`: If compute is needed, request budget approval context first. Branch on response status.
119
+ 4. Branch on `flywheel_request_compute_grant_approval.status`: Branch by response status (`already_approved`, `approval_required`, `insufficient_credits`).. if `already_approved` then `reuse_compute_grant_id`: Use returned `compute_grant_id` directly for flywheel_compute_acquire.. if `approval_required` then `present_approval_url_to_user`: Present `approval_url` to the user; the user opens it and confirms budget approval.; `flywheel_list_compute_grants`: After approval, list active grants for the current `approval_session_id` and use the returned `compute_grant_id` for acquire.. if `insufficient_credits` then `request_user_credit_top_up`: No `approval_url` is returned. Ask the user to add credits, then retry flywheel_request_compute_grant_approval.
125
120
  5. `flywheel_compute_acquire`: Acquire lease with `compute_grant_id`; include `approval_session_id` from approval response.
126
121
  6. `flywheel_compute_status`: Poll until the active lease is ready; follow `recommended_next_action`.
127
122
  7. `flywheel_launch_execution`: Launch execution once compute and inputs are ready.
@@ -135,19 +130,19 @@ Flywheel is a graph-based system for tracking research work, decisions, and evid
135
130
 
136
131
  - `flywheel_resolve_node_slug`: resolve human-facing slug references. If response status is `ambiguous`, ask the user to confirm the intended node_id before mutating anything.
137
132
  - `flywheel_get_node`: read the current node state before writes.
138
- - `flywheel_stage_node_update`: update in-progress node fields (title/content/summary, kind/outcome/hypothesis/insights/no_artifacts_reason), always with fresh `expected_revision`.
133
+ - `flywheel_acquire_stage_lease`, `flywheel_heartbeat_stage_lease`, `flywheel_release_stage_lease`: coordinate session-scoped local staged edits for an existing node before commit.
139
134
  - `flywheel_get_campaign_snapshot`: read the current derived campaign state for this node's root campaign instead of inferring standings from freeform text.
140
135
  - `flywheel_get_node_sharing`: after sharing writes, verify with flywheel_get_node_sharing before reporting private/shared/public state.
141
- - `flywheel_compute_status`: check first when work may need managed compute (GPU), to detect any active user lease state.
136
+ - `flywheel_compute_status`: check first when work may need managed compute (GPU), using the active lease_control_token from host context (or pass it explicitly).
142
137
  - `flywheel_list_compute_grants`: list active compute grants (funded by user/root budgets) and select one `compute_grant_id` for acquisition.
143
- - `flywheel_request_compute_grant_approval`: request/confirm budget before acquire and choose a budget source (`user` or `root`); this returns `approval_url` + `request_id` when interactive approval is needed.
144
- - `flywheel_compute_connection`: read SSH connection material for the active user lease once status indicates the lease is usable.
138
+ - `flywheel_request_compute_grant_approval`: request/confirm budget before acquire and choose a budget source (`user` or `root`); branch on status (`already_approved`, `approval_required`, `insufficient_credits`).
139
+ - `flywheel_compute_connection`: read SSH connection material for the active user lease once status indicates the lease is usable, scoped by lease_control_token.
145
140
  - `flywheel_compute_list_options`: use when a lease is needed and no suitable active lease exists, then select explicit provider-qualified `offer_id` (`provider::offer_id`) and `region`. Consider each option's `availability_mode`: `live_capacity` means provider-reported capacity, `allocation_time` means capacity is confirmed only when `flywheel_compute_acquire` attempts provisioning.
146
- - `flywheel_compute_acquire`: provision compute once requirements are clear. This requires a valid `compute_grant_id` and returns lease/provisioning state only (not SSH key material).
147
- - `flywheel_compute_release`: release compute when no longer needed.
148
- - `flywheel_launch_execution`, `flywheel_list_executions`, `flywheel_terminate_execution`: manage execution lifecycle.
141
+ - `flywheel_compute_acquire`: provision compute once requirements are clear. This requires a valid `compute_grant_id` and returns lease/provisioning state only (not SSH key material). Capture `compute.lease_control_token` from the response for follow-up lease control tools.
142
+ - `flywheel_compute_release`: release compute when no longer needed, scoped by lease_control_token.
143
+ - `flywheel_launch_execution`, `flywheel_list_executions`, `flywheel_terminate_execution`: manage execution status transitions.
149
144
  - `flywheel_prepare_artifact_uploads`: prepare one or more signed raw-file upload requests for concrete deliverables/evidence produced by the work.
150
145
  - `flywheel_finalize_artifact_uploads`: finalize a staged artifact batch and append all uploaded artifacts in one revision bump.
151
146
  - `flywheel_delete_artifact`: remove an accidental/obsolete node artifact.
152
147
  - `flywheel_list_artifacts`, `flywheel_get_artifact`: inspect node artifact metadata (`title` is the display label) and consume `storage_url` for raw artifact bytes only.
153
- - `flywheel_commit_node`: finalize staged node state once terminal and contract-complete (optional summary override only).
148
+ - `flywheel_commit_new_node`, `flywheel_commit_node`: publish the caller's full staged payload for an existing node once terminal and contract-complete; requires an active stage lease and explicit `base_committed_revision`.
@@ -0,0 +1,35 @@
1
+ # Blog Source Reference
2
+
3
+ Use this reference for blog posts and article-style URLs.
4
+
5
+ ## Source Detection
6
+
7
+ Match this reference for sources from common blog/article domains or article-like HTML pages.
8
+
9
+ ## Acquisition
10
+
11
+ - Fetch URL content.
12
+ - Extract main article body and heading structure.
13
+
14
+ ## Decomposition
15
+
16
+ - Short posts: one node is acceptable.
17
+ - Long posts: parent article node plus section children by top-level headings.
18
+ - Complete source decomposition before branch planning.
19
+
20
+ ## Content and Artifacts
21
+
22
+ - Article narrative in node `content`.
23
+ - Summary in `summary`.
24
+ - Supporting media files as artifacts when available.
25
+
26
+ ## Edges
27
+
28
+ - Use hierarchy edges when section children are created.
29
+ - Avoid lateral interpretive edges by default.
30
+
31
+ ## Failure Behavior
32
+
33
+ - If fetch or extraction fails, emit explicit failure and stop.
34
+
35
+ These rules apply only when `$flywheel-reproduce` is the active skill.