@paradigma-inc/flywheel 0.2.32 → 0.2.45

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 (108) hide show
  1. package/package.json +1 -1
  2. package/skills/flywheel/SKILL.md +2 -0
  3. package/skills/flywheel/references/flywheel-cli-tool-map.md +7 -6
  4. package/skills/flywheel-auto/references/flywheel-cli-tool-map.md +6 -5
  5. package/skills/flywheel-llm-proof-paper/scripts/check_paper.py +1 -1
  6. package/skills/flywheel-lookahead/references/flywheel-cli-tool-map.md +6 -5
  7. package/skills/flywheel-prove/assets/pipeline_template/src/tproof/cli.py +11 -6
  8. package/skills/flywheel-prove/scripts/scaffold_pipeline.py +0 -1
  9. package/skills/flywheel-repo/SKILL.md +47 -0
  10. package/skills/flywheel-repo/references/repository-commands.md +104 -0
  11. package/skills/flywheel-reproduce/references/flywheel-cli-tool-map.md +6 -5
  12. package/skills/flywheel-to-graph/references/flywheel-cli-tool-map.md +6 -5
  13. package/skills/flywheel-tree/scripts/render_tree.py +23 -24
  14. package/skills/flywheel-tree/scripts/render_tree_via_mcp.py +29 -28
  15. package/src/runtime/required-runtime-commands.json +1 -0
  16. package/src/runtime/vendor/flywheel-cli-dist/commands/graph-operation.js +4 -0
  17. package/src/runtime/vendor/flywheel-cli-dist/commands/graph-operation.js.map +1 -1
  18. package/src/runtime/vendor/flywheel-cli-dist/commands/hosted-repository-snapshot.js +10 -4
  19. package/src/runtime/vendor/flywheel-cli-dist/commands/hosted-repository-snapshot.js.map +1 -1
  20. package/src/runtime/vendor/flywheel-cli-dist/commands/registry/hosted.js +65 -10
  21. package/src/runtime/vendor/flywheel-cli-dist/commands/registry/hosted.js.map +1 -1
  22. package/src/runtime/vendor/flywheel-cli-dist/commands/registry/repository.js +69 -26
  23. package/src/runtime/vendor/flywheel-cli-dist/commands/registry/repository.js.map +1 -1
  24. package/src/runtime/vendor/flywheel-cli-dist/commands/repository-operation.js +10 -0
  25. package/src/runtime/vendor/flywheel-cli-dist/commands/repository-operation.js.map +1 -1
  26. package/src/runtime/vendor/flywheel-cli-dist/commands/repository-refusal-hints.js +20 -0
  27. package/src/runtime/vendor/flywheel-cli-dist/commands/repository-refusal-hints.js.map +1 -1
  28. package/src/runtime/vendor/flywheel-cli-dist/commands/types.js.map +1 -1
  29. package/src/runtime/vendor/flywheel-cli-dist/local/adapter.js +40 -0
  30. package/src/runtime/vendor/flywheel-cli-dist/local/adapter.js.map +1 -1
  31. package/src/runtime/vendor/flywheel-cli-dist/local/domain/errors.js +10 -0
  32. package/src/runtime/vendor/flywheel-cli-dist/local/domain/errors.js.map +1 -1
  33. package/src/runtime/vendor/flywheel-cli-dist/local/domain/invariants.js +3 -0
  34. package/src/runtime/vendor/flywheel-cli-dist/local/domain/invariants.js.map +1 -1
  35. package/src/runtime/vendor/flywheel-cli-dist/local/domain/models/commits.js.map +1 -1
  36. package/src/runtime/vendor/flywheel-cli-dist/local/domain/models/constants.js +6 -4
  37. package/src/runtime/vendor/flywheel-cli-dist/local/domain/models/constants.js.map +1 -1
  38. package/src/runtime/vendor/flywheel-cli-dist/local/domain/models/operation-identity.js +28 -0
  39. package/src/runtime/vendor/flywheel-cli-dist/local/domain/models/operation-identity.js.map +1 -1
  40. package/src/runtime/vendor/flywheel-cli-dist/local/domain/models/operations.js +61 -2
  41. package/src/runtime/vendor/flywheel-cli-dist/local/domain/models/operations.js.map +1 -1
  42. package/src/runtime/vendor/flywheel-cli-dist/local/domain/rebase/conflicts.js +22 -2
  43. package/src/runtime/vendor/flywheel-cli-dist/local/domain/rebase/conflicts.js.map +1 -1
  44. package/src/runtime/vendor/flywheel-cli-dist/local/domain/rebase/context.js +5 -0
  45. package/src/runtime/vendor/flywheel-cli-dist/local/domain/rebase/context.js.map +1 -1
  46. package/src/runtime/vendor/flywheel-cli-dist/local/domain/rebase/pull.js +40 -5
  47. package/src/runtime/vendor/flywheel-cli-dist/local/domain/rebase/pull.js.map +1 -1
  48. package/src/runtime/vendor/flywheel-cli-dist/local/domain/rebase/replay.js +17 -9
  49. package/src/runtime/vendor/flywheel-cli-dist/local/domain/rebase/replay.js.map +1 -1
  50. package/src/runtime/vendor/flywheel-cli-dist/local/domain/service/commit.js +3 -2
  51. package/src/runtime/vendor/flywheel-cli-dist/local/domain/service/commit.js.map +1 -1
  52. package/src/runtime/vendor/flywheel-cli-dist/local/domain/service/projection.js +1 -1
  53. package/src/runtime/vendor/flywheel-cli-dist/local/domain/service/projection.js.map +1 -1
  54. package/src/runtime/vendor/flywheel-cli-dist/local/domain/service/revert.js +3 -2
  55. package/src/runtime/vendor/flywheel-cli-dist/local/domain/service/revert.js.map +1 -1
  56. package/src/runtime/vendor/flywheel-cli-dist/local/domain/sync/local-pull.js +1 -0
  57. package/src/runtime/vendor/flywheel-cli-dist/local/domain/sync/local-pull.js.map +1 -1
  58. package/src/runtime/vendor/flywheel-cli-dist/local/runtime/projection.js +11 -2
  59. package/src/runtime/vendor/flywheel-cli-dist/local/runtime/projection.js.map +1 -1
  60. package/src/runtime/vendor/flywheel-cli-dist/local/runtime/recover-departed.js +371 -0
  61. package/src/runtime/vendor/flywheel-cli-dist/local/runtime/recover-departed.js.map +1 -0
  62. package/src/runtime/vendor/flywheel-cli-dist/local/runtime/remote/pull.js +4 -0
  63. package/src/runtime/vendor/flywheel-cli-dist/local/runtime/remote/pull.js.map +1 -1
  64. package/src/runtime/vendor/flywheel-cli-dist/local/runtime/remote/push.js +13 -3
  65. package/src/runtime/vendor/flywheel-cli-dist/local/runtime/remote/push.js.map +1 -1
  66. package/src/runtime/vendor/flywheel-cli-dist/local/runtime/remote/transport.js +15 -8
  67. package/src/runtime/vendor/flywheel-cli-dist/local/runtime/remote/transport.js.map +1 -1
  68. package/src/runtime/vendor/flywheel-cli-dist/local/runtime/snapshot-diff.js +19 -4
  69. package/src/runtime/vendor/flywheel-cli-dist/local/runtime/snapshot-diff.js.map +1 -1
  70. package/src/runtime/vendor/flywheel-cli-dist/local/store/apply.js +3 -2
  71. package/src/runtime/vendor/flywheel-cli-dist/local/store/apply.js.map +1 -1
  72. package/src/runtime/vendor/flywheel-cli-dist/local/store/contract.js.map +1 -1
  73. package/src/runtime/vendor/flywheel-cli-dist/local/store/diagnostics.js +1 -1
  74. package/src/runtime/vendor/flywheel-cli-dist/local/store/diagnostics.js.map +1 -1
  75. package/src/runtime/vendor/flywheel-cli-dist/local/store/migration/steps.js +29 -1
  76. package/src/runtime/vendor/flywheel-cli-dist/local/store/migration/steps.js.map +1 -1
  77. package/src/runtime/vendor/flywheel-cli-dist/local/store/migration/versions.js +2 -2
  78. package/src/runtime/vendor/flywheel-cli-dist/local/store/migration/versions.js.map +1 -1
  79. package/src/runtime/vendor/flywheel-cli-dist/local/store/migrations/008_boundaries_departures_and_author.sql +59 -0
  80. package/src/runtime/vendor/flywheel-cli-dist/local/store/migrations.js +1 -0
  81. package/src/runtime/vendor/flywheel-cli-dist/local/store/migrations.js.map +1 -1
  82. package/src/runtime/vendor/flywheel-cli-dist/local/store/pending.js +3 -1
  83. package/src/runtime/vendor/flywheel-cli-dist/local/store/pending.js.map +1 -1
  84. package/src/runtime/vendor/flywheel-cli-dist/local/store/projection/nodes.js +7 -4
  85. package/src/runtime/vendor/flywheel-cli-dist/local/store/projection/nodes.js.map +1 -1
  86. package/src/runtime/vendor/flywheel-cli-dist/local/store/projection/relations.js +8 -4
  87. package/src/runtime/vendor/flywheel-cli-dist/local/store/projection/relations.js.map +1 -1
  88. package/src/runtime/vendor/flywheel-cli-dist/local/store/projection/rules.js +15 -6
  89. package/src/runtime/vendor/flywheel-cli-dist/local/store/projection/rules.js.map +1 -1
  90. package/src/runtime/vendor/flywheel-cli-dist/local/store/projection/tags.js +36 -17
  91. package/src/runtime/vendor/flywheel-cli-dist/local/store/projection/tags.js.map +1 -1
  92. package/src/runtime/vendor/flywheel-cli-dist/local/store/snapshot/hosted.js +20 -6
  93. package/src/runtime/vendor/flywheel-cli-dist/local/store/snapshot/hosted.js.map +1 -1
  94. package/src/runtime/vendor/flywheel-cli-dist/local/store/snapshot/replace.js +20 -3
  95. package/src/runtime/vendor/flywheel-cli-dist/local/store/snapshot/replace.js.map +1 -1
  96. package/src/runtime/vendor/flywheel-cli-dist/local/store/snapshot/schema.js +2 -2
  97. package/src/runtime/vendor/flywheel-cli-dist/local/store/snapshot/schema.js.map +1 -1
  98. package/src/runtime/vendor/flywheel-cli-dist/local/store/sqlite/schema.js +5 -1
  99. package/src/runtime/vendor/flywheel-cli-dist/local/store/sqlite/schema.js.map +1 -1
  100. package/src/runtime/vendor/flywheel-cli-dist/local/store/sqlite/store.js +41 -0
  101. package/src/runtime/vendor/flywheel-cli-dist/local/store/sqlite/store.js.map +1 -1
  102. package/src/runtime/vendor/flywheel-cli-dist/local/store/sync.js +35 -2
  103. package/src/runtime/vendor/flywheel-cli-dist/local/store/sync.js.map +1 -1
  104. package/src/runtime/vendor/flywheel-cli-dist/main.js +2 -0
  105. package/src/runtime/vendor/flywheel-cli-dist/main.js.map +1 -1
  106. package/src/runtime/vendor/flywheel-cli-dist/prebuilds/darwin-arm64/node.napi.node +0 -0
  107. package/src/runtime/vendor/flywheel-cli-dist/prebuilds/darwin-x64/node.napi.node +0 -0
  108. package/src/runtime/vendor/manifest.json +4 -7
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@paradigma-inc/flywheel",
3
- "version": "0.2.32",
3
+ "version": "0.2.45",
4
4
  "description": "One-command setup for Flywheel MCP hosts",
5
5
  "type": "module",
6
6
  "files": [
@@ -17,6 +17,7 @@ Use this skill when the conversation is about any of the following:
17
17
  - setting up, updating, authenticating, or troubleshooting Flywheel MCP
18
18
  - configuring hooks, hook secrets, and hook-run monitoring
19
19
  - managed compute, local hardware, campaigns, or Flywheel Web UI navigation
20
+ - working in a local Flywheel repository (`repo:*` commands, `.flywheel/`, history, pull, conflicts, push) or administering a hosted repository: hand off to the `flywheel-repo` skill
20
21
 
21
22
  If the request is ambiguous, default to experiment-design guidance before platform mechanics.
22
23
 
@@ -50,6 +51,7 @@ Choose one primary file first, then add at most one supporting file only if need
50
51
 
51
52
  - `references/experiment-design-protocol.md` for structured experiment design and readiness checks
52
53
  - `references/flywheel-mcp-tool-map.md` (MCP) or `references/flywheel-cli-tool-map.md` (CLI) for exact tool surface and contract behavior in the matching install mode
54
+ - the `flywheel-repo` skill for local-repository work (`repo:*`) and hosted repository ownership or membership (`hosted:repository:*`); this skill stays background only
53
55
  - `getting-started/flywheel-tutorial-overview.md` for orientation and learning path
54
56
  - `getting-started/flywheel-quickstart.md` for fastest first-use setup and auth recovery
55
57
  - `setting-up-flywheel/` for host-specific installation and update procedures
@@ -2,7 +2,7 @@
2
2
 
3
3
  Contract-aligned routing guide for the Flywheel runtime CLI.
4
4
 
5
- The Flywheel CLI (`flywheel <command>`) is the runtime command surface shipped by `@paradigma-inc/flywheel`. It wraps the canonical Flywheel HTTP API and is the parallel surface to Flywheel MCP. Use this map when the host install is `--mode cli` (skills installed without an MCP server entry) or whenever scripted / direct-API workflows are preferable to MCP tool calls.
5
+ The Flywheel CLI (`flywheel <command>`) is the runtime command surface shipped by `@paradigma-inc/flywheel`. `hosted:` and most other commands call the Flywheel HTTP API and are the parallel surface to Flywheel MCP; `repo:` commands work on a local repository on disk and touch the network only for `repo:clone`, `repo:pull`, `repo:push`, `repo:purge`, and `repo:artifact:download` (which fetches remote-only objects). Use this map when the host install is `--mode cli` (skills installed without an MCP server entry) or whenever scripted / direct-API workflows are preferable to MCP tool calls.
6
6
 
7
7
  For MCP routing, see `flywheel-mcp-tool-map.md`. The families below group related capabilities; CLI repository commands and MCP tools do not share the same staging or commit workflow.
8
8
 
@@ -17,6 +17,7 @@ Follow `flywheel-mcp-tool-map.md` for MCP-specific payload and lease workflows.
17
17
  - `repo:` and `hosted:` commands default to human output. Pass `--format=json` explicitly for scripts; other available formats are listed by command help.
18
18
  - Attach an artifact with `flywheel hosted:artifact:attach node <owner-id> --repository-id <uuid> --file <path> --metadata-file artifact.json --format=json`; the CLI prepares the upload, sends raw bytes, and commits the attachment.
19
19
  - Mutating commands are subject to per-user write limits: 120 node creates per minute, 2,000 node creates per 24 hours, and 120 graph writes per minute. Graph writes include existing-node commits, edge changes, deletes, merges, tags, sharing, artifact finalization, artifact deletion, and artifact-note updates. On `429`, honor `Retry-After` and retry the same idempotent command after waiting.
20
+ - A `426 client_version_unsupported` or `repository_snapshot_format_unsupported` response means the installed client is incompatible. Run `flywheel update --yes`, retry the original command, and do not discard local state.
20
21
  - Run `flywheel help <command>` for canonical per-command flags, types, defaults, examples, and related commands.
21
22
 
22
23
  ## CLI Families and Related MCP Operations
@@ -49,15 +50,15 @@ The families below group CLI capabilities alongside related MCP tools. A related
49
50
 
50
51
  ### Hosted graph mutations and stage leases
51
52
 
52
- - `flywheel hosted:node:create` (mutating; scopes: `write`; MCP equivalent: `flywheel_commit_new_node`): Create a node in one hosted commit.
53
+ - `flywheel hosted:node:create` (mutating; scopes: `write`; MCP equivalent: `flywheel_commit_new_node`): Create a node in the hosted repository named by `--repository-id`; this never selects a default workspace or creates another repository.
53
54
  - `flywheel nodes:stage:lease:acquire` (mutating; scopes: `write`; HTTP: `POST /nodes/{node_id}/stage/lease/acquire`; MCP equivalent: `flywheel_acquire_stage_lease`): Acquire a session-scoped edit lease for an existing-node MCP staged-payload workflow, not local CLI `repo:` authoring or direct `hosted:` mutations.
54
55
  - `flywheel nodes:stage:lease:heartbeat` (mutating; scopes: `write`; HTTP: `POST /nodes/{node_id}/stage/lease/heartbeat`; MCP equivalent: `flywheel_heartbeat_stage_lease`): Heartbeat an active node stage lease.
55
56
  - `flywheel nodes:stage:lease:release` (mutating; scopes: `write`; HTTP: `POST /nodes/{node_id}/stage/lease/release`; MCP equivalent: `flywheel_release_stage_lease`): Release a node stage lease.
56
57
  - `flywheel hosted:node:set` (mutating; scopes: `write`; MCP equivalent: `flywheel_commit_node`): Set one node field in one hosted commit.
57
- - `flywheel hosted:node:branch` (mutating; scopes: `write`; MCP equivalent: `flywheel_branch_node`): Create a child branch in one hosted commit. Pass `--expected-head` when the caller must reject concurrent hosted changes.
58
- - `flywheel hosted:node:merge` (mutating; scopes: `write`; MCP equivalent: `flywheel_merge_nodes`): Merge repeated `--source` nodes into one node in one hosted commit.
59
- - `flywheel hosted:lineage:add` (mutating; scopes: `write`; MCP equivalent: `flywheel_add_parent`): Add a parent-child lineage relation in one hosted commit.
60
- - `flywheel hosted:lineage:remove` (mutating; scopes: `write`; MCP equivalent: `flywheel_remove_parent`): Remove a parent-child lineage relation in one hosted commit.
58
+ - `flywheel hosted:node:branch` (mutating; scopes: `write`; MCP equivalent: `flywheel_branch_node`): Create a child branch in the hosted repository named by `--repository-id`. Pass `--expected-head` when the caller must reject concurrent hosted changes.
59
+ - `flywheel hosted:node:merge` (mutating; scopes: `write`; MCP equivalent: `flywheel_merge_nodes`): Merge repeated `--source` nodes into one node in the hosted repository named by `--repository-id`.
60
+ - `flywheel hosted:lineage:add` (mutating; scopes: `write`; MCP equivalent: `flywheel_add_parent`): Add a parent-child lineage relation in one hosted commit; include `--parent-repository-id` when the parent lives across a repository boundary.
61
+ - `flywheel hosted:lineage:remove` (mutating; scopes: `write`; MCP equivalent: `flywheel_remove_parent`): Remove a parent-child lineage relation in one hosted commit; include `--parent-repository-id` for a cross-repository parent.
61
62
  - `flywheel hosted:node:tombstone` (mutating; scopes: `write`; MCP equivalent: `flywheel_delete_node`): Tombstone one node in one hosted commit.
62
63
  - There is no hosted bulk-tombstone command; run `flywheel hosted:node:tombstone` once per node.
63
64
 
@@ -18,6 +18,7 @@ The CLI has its own destination and commit lifecycle:
18
18
  - Every hosted graph mutation requires `--repository-id <uuid>`. For an associated local workspace, read `repository_id` from `flywheel repo:status --repo <path> --format=json`.
19
19
  - Node values, tag definitions, edge content, and artifact metadata use the file flags documented by each graph command.
20
20
  - `repo:` and `hosted:` commands default to human output. Pass `--format=json` explicitly for scripts; other available formats are listed by command help.
21
+ - A `426 client_version_unsupported` or `repository_snapshot_format_unsupported` response means the installed client is incompatible. Run `flywheel update --yes`, retry the original command, and do not discard local state.
21
22
  - Run `flywheel help <command>` for canonical per-command flags, types, defaults, examples, and related commands.
22
23
 
23
24
  ## Related MCP Operations
@@ -50,15 +51,15 @@ The families below identify related MCP operations for discovery and terminology
50
51
 
51
52
  ### Hosted graph mutations and stage leases
52
53
 
53
- - `flywheel hosted:node:create` (mutating; scopes: `write`; related MCP operation: `flywheel_commit_new_node`): Create a node in one hosted repository commit; it is not an MCP staged-payload commit.
54
+ - `flywheel hosted:node:create` (mutating; scopes: `write`; related MCP operation: `flywheel_commit_new_node`): Create a node in the hosted repository named by `--repository-id`; this never selects a default workspace or creates another repository.
54
55
  - `flywheel nodes:stage:lease:acquire` (mutating; scopes: `write`; HTTP: `POST /nodes/{node_id}/stage/lease/acquire`; related MCP operation: `flywheel_acquire_stage_lease`): Acquire a session-scoped edit lease for an existing MCP node workflow.
55
56
  - `flywheel nodes:stage:lease:heartbeat` (mutating; scopes: `write`; HTTP: `POST /nodes/{node_id}/stage/lease/heartbeat`; related MCP operation: `flywheel_heartbeat_stage_lease`): Heartbeat an active node stage lease.
56
57
  - `flywheel nodes:stage:lease:release` (mutating; scopes: `write`; HTTP: `POST /nodes/{node_id}/stage/lease/release`; related MCP operation: `flywheel_release_stage_lease`): Release a node stage lease.
57
58
  - `flywheel hosted:node:set` (mutating; scopes: `write`; related MCP operation: `flywheel_commit_node`): Set one node field in one hosted repository commit; it is not an MCP staged-payload commit.
58
- - `flywheel hosted:node:branch` (mutating; scopes: `write`; related MCP operation: `flywheel_branch_node`): Create a child branch in one hosted repository commit. Pass `--expected-head` when the caller must reject concurrent hosted changes.
59
- - `flywheel hosted:node:merge` (mutating; scopes: `write`; related MCP operation: `flywheel_merge_nodes`): Merge repeated `--source` nodes into one hosted repository commit.
60
- - `flywheel hosted:lineage:add` (mutating; scopes: `write`; related MCP operation: `flywheel_add_parent`): Add a parent-child lineage relation in one hosted repository commit.
61
- - `flywheel hosted:lineage:remove` (mutating; scopes: `write`; related MCP operation: `flywheel_remove_parent`): Remove a parent-child lineage relation in one hosted repository commit.
59
+ - `flywheel hosted:node:branch` (mutating; scopes: `write`; related MCP operation: `flywheel_branch_node`): Create a child branch in the hosted repository named by `--repository-id`. Pass `--expected-head` when the caller must reject concurrent hosted changes.
60
+ - `flywheel hosted:node:merge` (mutating; scopes: `write`; related MCP operation: `flywheel_merge_nodes`): Merge repeated `--source` nodes in the hosted repository named by `--repository-id`.
61
+ - `flywheel hosted:lineage:add` (mutating; scopes: `write`; related MCP operation: `flywheel_add_parent`): Add a parent-child lineage relation in one hosted commit; include `--parent-repository-id` when the parent lives across a repository boundary.
62
+ - `flywheel hosted:lineage:remove` (mutating; scopes: `write`; related MCP operation: `flywheel_remove_parent`): Remove a parent-child lineage relation in one hosted commit; include `--parent-repository-id` for a cross-repository parent.
62
63
  - `flywheel hosted:node:tombstone` (mutating; scopes: `write`; related MCP operation: `flywheel_delete_node`): Tombstone one node in one hosted repository commit.
63
64
  - There is no hosted bulk-tombstone command; run `flywheel hosted:node:tombstone` once per node.
64
65
 
@@ -206,7 +206,7 @@ def main(argv: Sequence[str] | None = None) -> int:
206
206
  args = parser.parse_args(argv)
207
207
  try:
208
208
  report = run_check(Path(args.project).expanduser().resolve(), args)
209
- except Exception as exc:
209
+ except (OSError, RuntimeError, ValueError, ET.ParseError) as exc:
210
210
  print(f"paper-llm-proof could not complete: {exc}", file=sys.stderr)
211
211
  return 3
212
212
 
@@ -18,6 +18,7 @@ The CLI has its own destination and commit lifecycle:
18
18
  - Every hosted graph mutation requires `--repository-id <uuid>`. For an associated local workspace, read `repository_id` from `flywheel repo:status --repo <path> --format=json`.
19
19
  - Node values, tag definitions, edge content, and artifact metadata use the file flags documented by each graph command.
20
20
  - `repo:` and `hosted:` commands default to human output. Pass `--format=json` explicitly for scripts; other available formats are listed by command help.
21
+ - A `426 client_version_unsupported` or `repository_snapshot_format_unsupported` response means the installed client is incompatible. Run `flywheel update --yes`, retry the original command, and do not discard local state.
21
22
  - Run `flywheel help <command>` for canonical per-command flags, types, defaults, examples, and related commands.
22
23
 
23
24
  ## Related MCP Operations
@@ -50,15 +51,15 @@ The families below identify related MCP operations for discovery and terminology
50
51
 
51
52
  ### Hosted graph mutations and stage leases
52
53
 
53
- - `flywheel hosted:node:create` (mutating; scopes: `write`; related MCP operation: `flywheel_commit_new_node`): Create a node in one hosted repository commit; it is not an MCP staged-payload commit.
54
+ - `flywheel hosted:node:create` (mutating; scopes: `write`; related MCP operation: `flywheel_commit_new_node`): Create a node in the hosted repository named by `--repository-id`; this never selects a default workspace or creates another repository.
54
55
  - `flywheel nodes:stage:lease:acquire` (mutating; scopes: `write`; HTTP: `POST /nodes/{node_id}/stage/lease/acquire`; related MCP operation: `flywheel_acquire_stage_lease`): Acquire a session-scoped edit lease for an existing MCP node workflow.
55
56
  - `flywheel nodes:stage:lease:heartbeat` (mutating; scopes: `write`; HTTP: `POST /nodes/{node_id}/stage/lease/heartbeat`; related MCP operation: `flywheel_heartbeat_stage_lease`): Heartbeat an active node stage lease.
56
57
  - `flywheel nodes:stage:lease:release` (mutating; scopes: `write`; HTTP: `POST /nodes/{node_id}/stage/lease/release`; related MCP operation: `flywheel_release_stage_lease`): Release a node stage lease.
57
58
  - `flywheel hosted:node:set` (mutating; scopes: `write`; related MCP operation: `flywheel_commit_node`): Set one node field in one hosted repository commit; it is not an MCP staged-payload commit.
58
- - `flywheel hosted:node:branch` (mutating; scopes: `write`; related MCP operation: `flywheel_branch_node`): Create a child branch in one hosted repository commit. Pass `--expected-head` when the caller must reject concurrent hosted changes.
59
- - `flywheel hosted:node:merge` (mutating; scopes: `write`; related MCP operation: `flywheel_merge_nodes`): Merge repeated `--source` nodes into one hosted repository commit.
60
- - `flywheel hosted:lineage:add` (mutating; scopes: `write`; related MCP operation: `flywheel_add_parent`): Add a parent-child lineage relation in one hosted repository commit.
61
- - `flywheel hosted:lineage:remove` (mutating; scopes: `write`; related MCP operation: `flywheel_remove_parent`): Remove a parent-child lineage relation in one hosted repository commit.
59
+ - `flywheel hosted:node:branch` (mutating; scopes: `write`; related MCP operation: `flywheel_branch_node`): Create a child branch in the hosted repository named by `--repository-id`. Pass `--expected-head` when the caller must reject concurrent hosted changes.
60
+ - `flywheel hosted:node:merge` (mutating; scopes: `write`; related MCP operation: `flywheel_merge_nodes`): Merge repeated `--source` nodes in the hosted repository named by `--repository-id`.
61
+ - `flywheel hosted:lineage:add` (mutating; scopes: `write`; related MCP operation: `flywheel_add_parent`): Add a parent-child lineage relation in one hosted commit; include `--parent-repository-id` when the parent lives across a repository boundary.
62
+ - `flywheel hosted:lineage:remove` (mutating; scopes: `write`; related MCP operation: `flywheel_remove_parent`): Remove a parent-child lineage relation in one hosted commit; include `--parent-repository-id` for a cross-repository parent.
62
63
  - `flywheel hosted:node:tombstone` (mutating; scopes: `write`; related MCP operation: `flywheel_delete_node`): Tombstone one node in one hosted repository commit.
63
64
  - There is no hosted bulk-tombstone command; run `flywheel hosted:node:tombstone` once per node.
64
65
 
@@ -1,6 +1,7 @@
1
1
  import shutil
2
2
  from datetime import datetime, timezone
3
3
  from pathlib import Path
4
+ from typing import Annotated
4
5
 
5
6
  import typer
6
7
  from rich import print as rprint
@@ -137,7 +138,9 @@ def init(build: bool = typer.Option(True, "--build/--no-build")) -> None:
137
138
 
138
139
 
139
140
  @app.command("reindex")
140
- def reindex(project_dir: Path | None = typer.Option(None, "--project-dir")) -> None:
141
+ def reindex(
142
+ project_dir: Annotated[Path | None, typer.Option("--project-dir")] = None,
143
+ ) -> None:
141
144
  paths = _paths()
142
145
  target = project_dir or paths.lean_project_dir
143
146
  all_proofs_path = reindex_allproofs(target)
@@ -146,10 +149,10 @@ def reindex(project_dir: Path | None = typer.Option(None, "--project-dir")) -> N
146
149
 
147
150
  @app.command("start-run")
148
151
  def start_run(
149
- prompt_file: Path | None = typer.Option(None, "--prompt-file"),
150
- prompt_text: str | None = typer.Option(None, "--prompt-text"),
151
- run_label: str | None = typer.Option(None, "--run-label"),
152
- context_file: Path | None = typer.Option(None, "--context-file"),
152
+ prompt_file: Annotated[Path | None, typer.Option("--prompt-file")] = None,
153
+ prompt_text: Annotated[str | None, typer.Option("--prompt-text")] = None,
154
+ run_label: Annotated[str | None, typer.Option("--run-label")] = None,
155
+ context_file: Annotated[Path | None, typer.Option("--context-file")] = None,
153
156
  ) -> None:
154
157
  paths = _paths()
155
158
  task_prompt = read_task_prompt(prompt_file=prompt_file, prompt_text=prompt_text)
@@ -220,7 +223,9 @@ def set_status(
220
223
 
221
224
 
222
225
  @app.command("verify")
223
- def verify(project_dir: Path | None = typer.Option(None, "--project-dir")) -> None:
226
+ def verify(
227
+ project_dir: Annotated[Path | None, typer.Option("--project-dir")] = None,
228
+ ) -> None:
224
229
  paths = _paths()
225
230
  target = project_dir or paths.lean_project_dir
226
231
  code, output = lake_build(target)
@@ -1,4 +1,3 @@
1
- #!/usr/bin/env python3
2
1
  """
3
2
  Scaffold a local Lean theorem proving pipeline into a target repository.
4
3
  """
@@ -0,0 +1,47 @@
1
+ ---
2
+ name: flywheel-repo
3
+ description: "Work in a local Flywheel repository with the flywheel CLI: create or clone, stage, diff, commit, inspect history, pull, resolve conflicts, and, only when asked, push; plus hosted repository ownership and membership. Use for repo:* and hosted:repository:* tasks; use the flywheel skill for direct hosted repository writes, MCP, and setup."
4
+ ---
5
+
6
+ # Flywheel Repository Skill
7
+
8
+ A repository is one user's Flywheel project workspace: a graph of nodes with history. A local repository is the on-disk copy of that repository, rooted at a `.flywheel/` directory, with its own staging area and commit log; `repo:` commands operate on it. A hosted repository is the server-side copy that collaborators read through the web app, API, CLI, or MCP; `hosted:` commands change it directly. A staged change is a pending operation that a `repo:` mutation command saved in the local repository but that is not yet part of history. A local commit is the result of `repo:commit`: the staged changes become one entry in the local commit log, and nothing leaves the machine. A hosted commit is one entry in the hosted repository's history; `repo:push` turns local commits into hosted commits, and each `hosted:` mutation posts one hosted commit immediately.
9
+
10
+ ## Precondition
11
+
12
+ Run `flywheel --help` first. If `flywheel` is not on `PATH`, use `npx --yes @paradigma-inc/flywheel` in place of `flywheel` for every command in this skill. If neither runs, stop and tell the user the CLI is not available; do not fall back to MCP tools or `hosted:` commands for local-repository work.
13
+
14
+ ## When To Use
15
+
16
+ - the user wants to create, clone, inspect, edit, commit, back up, or repair a local Flywheel repository
17
+ - the user asks about local history, staged work, a failed pull, a rebase, or conflicts
18
+ - the user asks to publish local commits, or to list, transfer, retire, or change members of a hosted repository
19
+
20
+ Not for: direct hosted node edits (`hosted:node:*`, `hosted:tag:*`, and every other `hosted:*` family except `hosted:repository:*`), MCP tools, setup, or authentication. Use the `flywheel` skill for those.
21
+
22
+ ## Rules
23
+
24
+ - Flags are never listed here. Before running any command, run `flywheel help <command>`; use `flywheel help <command> --format=json` when you need to parse the output.
25
+ - Select the local repository explicitly: a `--repo <path>` repository, an explicitly requested `--personal` repository, or a repository found from the current directory. If none is selected, stop and ask; never switch to `hosted:` commands instead.
26
+ - Never run `flywheel repo:push` (with or without `--create-remote`) unless the user asked for or approved publication in this conversation. Staging and `repo:commit` never leave the machine.
27
+ - A 426 `client_version_unsupported` or `repository_snapshot_format_unsupported` response is a client compatibility refusal, not a repository conflict. Run `flywheel update --yes`, retry the original command (snapshot-format negotiation applies only to clone and pull), and never discard local state to work around it.
28
+ - `hosted:repository:transfer`, `hosted:repository:retire`, `hosted:repository:member:set`, and `hosted:repository:member:remove` change who owns or who can read a repository. Run one only on the user's explicit instruction for that exact change, and ask one direct confirmation question naming the repository and the change before running it. Never run one as a side effect of another task. `retire` is irreversible: every node in the repository stops being readable.
29
+ - `repo:purge` and `repo:staging:discard` destroy data. State what will be lost and get the user's confirmation first.
30
+
31
+ ## Workflow
32
+
33
+ Each phase names its commands only; look up flags with `flywheel help <command>`.
34
+
35
+ 1. Obtain a local repository: `repo:init` creates or adopts only the selected local repository, `repo:clone` reads an existing hosted projection v4 repository, and `repo:restore` reads a backup archive. Then run `repo:status` to confirm the repository is selected and healthy.
36
+ 2. Read before writing: `repo:node:get`, `repo:lineage:list`, `repo:tag:list`, `repo:edge:list`, `repo:edge:get`, `repo:containment:list`, `repo:containment:get`, and the artifact reads (`repo:artifact:get`, `repo:artifact:download`, `repo:node-artifact:list`, `repo:edge-artifact:list`). These default to committed local state; the staged option described in each command's help shows pending work instead. Lineage rows name `parent_repository_id`; `boundary:true` means the parent remains in another repository and is not a missing local node.
37
+ 3. Stage changes with the node, tag, relation, and artifact commands listed in the reference file. Every `repo:` mutation stages in the selected local repository; nothing is committed or placed in a different repository.
38
+ 4. Review with `repo:diff` (its staged option shows the complete pending result). Discard with `repo:staging:discard` only on request.
39
+ 5. Commit with `repo:commit`; the commit keeps its immutable author if another principal later pushes it. Inspect history with `repo:log`; undo a commit with `repo:revert`, which stages inverse operations for the reversible changes of that commit.
40
+ 6. Sync: `repo:pull` applies hosted history and atomically removes nodes that departed to a reported target repository. On ordinary conflicts, use `repo:conflicts:list`, `repo:conflicts:show`, and `repo:conflicts:resolve`, then `repo:rebase:continue` or `repo:rebase:abort`. Publish with `repo:push` only when requested; its create-remote option is for the first publication only, when the hosted repository does not exist yet (there is no `hosted:repository:create`). If a push fails with `repository_node_departed`, run `repo:recover-departed <current_repository_id> <directory> --repo <source-checkout>` to clone the current repository and replay the unpublished commits there; never redirect the old repository-bound push.
41
+ 7. Maintain: `repo:backup` before risky work, `repo:doctor` to diagnose availability or interrupted-sync problems, `repo:gc` to reclaim unreferenced artifact objects; `repo:purge` only on explicit request.
42
+ 8. Hosted repository administration: `hosted:repository:list`, `hosted:repository:head`, and `hosted:repository:members` are reads. `hosted:repository:member:set`, `hosted:repository:member:remove`, `hosted:repository:transfer`, and `hosted:repository:retire` follow the confirmation rule above.
43
+
44
+ ## Reference
45
+
46
+ - [references/repository-commands.md](references/repository-commands.md): every `repo:*` and `hosted:repository:*` command with its summary, grouped by the phases above.
47
+ - `flywheel help <command>`: flags, positionals, examples, and related commands.
@@ -0,0 +1,104 @@
1
+ # Flywheel Repository Commands
2
+
3
+ Each line names a command and its summary; run `flywheel help <command>` (add `--format=json` for machine-readable output) for flags, positionals, examples, and related commands.
4
+
5
+ ## Commands by lifecycle phase
6
+
7
+ ### Create or obtain a local repository
8
+
9
+ - `flywheel repo:init`: Initialize or adopt the selected local repository at a directory; this command does not choose a hosted default workspace or fork.
10
+ - `flywheel repo:clone`: Clone a projection v4 hosted repository, including boundary-parent and cross-repository tag-scope identities, into a new local directory. If the server requires a newer client, run `flywheel update --yes` and retry.
11
+ - `flywheel repo:restore`: Restore a verified backup archive into an empty directory.
12
+
13
+ ### Inspect state
14
+
15
+ - `flywheel repo:status`: Show local repository status, including interrupted push or pull (interrupted_sync) and an unpublished hosted remote (stranded_remote). Rerun an interrupted command with the same --idempotency-key; stranded_remote names the existing repo:push recovery flow.
16
+ - `flywheel repo:doctor`: Report local object availability disagreements and interrupted push or pull operations (interrupted_sync). Confirmed availability repair changes records only and refuses pending work.
17
+
18
+ ### Read committed or staged content
19
+
20
+ - `flywheel repo:node:get`: Read one node and its comparison digests. Defaults to committed local state; use --staged to inspect saved pending work.
21
+ - `flywheel repo:tag:list`: List tags and holder digests. Defaults to committed local state; use --staged to inspect saved pending work.
22
+ - `flywheel repo:lineage:list`: List lineage relations with `parent_repository_id` and boundary status. Defaults to committed local state; use --staged to inspect saved pending work.
23
+ - `flywheel repo:node-artifact:list`: List node artifact references. Defaults to committed local state; use --staged to inspect saved pending work.
24
+ - `flywheel repo:edge-artifact:list`: List edge artifact references. Defaults to committed local state; use --staged to inspect saved pending work.
25
+ - `flywheel repo:artifact:get`: Read one artifact and its references. Defaults to committed local state; use --staged to inspect saved pending work.
26
+ - `flywheel repo:artifact:download`: Download current-head artifact bytes, fetching and caching a remote-only object when needed; requires --out.
27
+ - `flywheel repo:containment:get`: Read active containment for one child. Defaults to committed local state; use --staged to inspect saved pending work.
28
+ - `flywheel repo:containment:list`: List active contained nodes. Defaults to committed local state; use --staged to inspect saved pending work.
29
+ - `flywheel repo:edge:list`: List semantic edges in one graph. Defaults to committed local state; use --staged to inspect saved pending work.
30
+ - `flywheel repo:edge:get`: Read one semantic edge. Defaults to committed local state; use --staged to inspect saved pending work.
31
+
32
+ ### Stage changes (nodes)
33
+
34
+ - `flywheel repo:node:create`: Stage a root node in the selected local repository from --title or the full six-field JSON values file; this command never creates or selects another repository.
35
+ - `flywheel repo:node:set`: Stage a new value for one field of a node.
36
+ - `flywheel repo:node:tombstone`: Stage the removal of a node; its history stays in the repository.
37
+ - `flywheel repo:node:restore`: Stage the restoration of a tombstoned node.
38
+ - `flywheel repo:node:branch`: Stage one branched node in the selected local repository and one lineage relation copying the source's title.
39
+ - `flywheel repo:node:merge`: Stage one merged node in the selected local repository and one lineage relation from each supplied source, in argument order.
40
+
41
+ ### Stage changes (tags)
42
+
43
+ - `flywheel repo:tag:define`: Stage a new tag definition under a scope node.
44
+ - `flywheel repo:tag:update`: Stage a changed tag definition.
45
+ - `flywheel repo:tag:retire`: Stage the retirement of a tag definition.
46
+ - `flywheel repo:node-tag:assign`: Stage assigning a tag to a node.
47
+ - `flywheel repo:node-tag:remove`: Stage removing a tag from a node.
48
+
49
+ ### Stage changes (relations)
50
+
51
+ - `flywheel repo:lineage:add`: Stage a parent-child lineage relation between two nodes.
52
+ - `flywheel repo:lineage:remove`: Stage the removal of a lineage relation.
53
+ - `flywheel repo:containment:assign`: Stage placing a node inside a container node.
54
+ - `flywheel repo:containment:remove`: Stage the removal of a containment relation.
55
+ - `flywheel repo:edge:add`: Stage an edge between distinct descendants of a graph in this repository.
56
+ - `flywheel repo:edge:set-content`: Stage new content for a semantic edge.
57
+ - `flywheel repo:edge:remove`: Stage the removal of a semantic edge.
58
+
59
+ ### Stage changes (artifacts)
60
+
61
+ - `flywheel repo:artifact:attach`: Stage an artifact attachment from --metadata-file or the inline --name/--media-type/--notes/--tags flags.
62
+ - `flywheel repo:artifact:detach`: Stage detaching an artifact from its node or edge.
63
+ - `flywheel repo:artifact:set-metadata`: Stage a replacement for exactly one artifact metadata field from --metadata-file or one inline flag.
64
+
65
+ ### Review and discard staged work
66
+
67
+ - `flywheel repo:diff`: Show committed-history differences or the complete pending staged result.
68
+ - `flywheel repo:staging:discard`: Discard all saved pending operations and associated values from only the selected local repository. Uncommitted work is not recoverable through graph history. Optional repo:backup preserves the batch, but restoring it does not repair invalid staging. No backup is required or created automatically; no export or network transfer occurs. Discard is never implicit in reads, edits, validation, failed commit, pull, push, revert, startup, migration, or upgrade.
69
+
70
+ ### Commit and history
71
+
72
+ - `flywheel repo:commit`: Commit the exact current staging digest with its immutable author principal.
73
+ - `flywheel repo:log`: List commits reachable from the local head, newest first.
74
+ - `flywheel repo:revert`: Append inverse operations for a target commit's supported reversible changes; node/edge latest-value fields and the legacy artifact.metadata.set.v1 operation are not reversible and are skipped.
75
+
76
+ ### Sync with the hosted repository
77
+
78
+ - `flywheel repo:pull`: Pull and atomically apply hosted history, preserving boundary references and removing departed nodes while reporting each `target_repository_id`. If the server requires a newer client, run `flywheel update --yes` and retry.
79
+ - `flywheel repo:conflicts:list`: List structured rebase conflicts.
80
+ - `flywheel repo:conflicts:show`: Show one structured conflict.
81
+ - `flywheel repo:conflicts:resolve`: Resolve one structured conflict.
82
+ - `flywheel repo:rebase:continue`: Continue one exact rebase.
83
+ - `flywheel repo:rebase:abort`: Abort one exact rebase.
84
+ - `flywheel repo:push`: Publish local commits to the hosted repository (use --create-remote for the first publication). `repository_node_departed` names `current_repository_id`; the push is never redirected.
85
+ - `flywheel repo:recover-departed`: Clone `current_repository_id` and atomically replay the selected source checkout's unpublished commits there in one client-side follow-up.
86
+
87
+ ### Maintenance
88
+
89
+ - `flywheel repo:backup`: Create and verify a local repository backup.
90
+ - `flywheel repo:gc`: Delete local artifact objects that no commit, staging entry, or backup still references.
91
+ - `flywheel repo:purge`: Permanently remove one node from the hosted repository and local history (irreversible; requires --confirm).
92
+
93
+ ### Hosted repository administration (reads)
94
+
95
+ - `flywheel hosted:repository:list`: List hosted repositories where you hold a role.
96
+ - `flywheel hosted:repository:head`: Show the published head of a hosted repository.
97
+ - `flywheel hosted:repository:members`: List the collaborators of a hosted repository with their roles (owner or admin only).
98
+
99
+ ### Hosted repository administration (writes)
100
+
101
+ - `flywheel hosted:repository:member:set`: Add a collaborator or change their role.
102
+ - `flywheel hosted:repository:member:remove`: Remove a collaborator from a hosted repository.
103
+ - `flywheel hosted:repository:transfer`: Transfer ownership of a hosted repository to another member; you remain admin.
104
+ - `flywheel hosted:repository:retire`: Permanently retire a hosted repository (irreversible; the ID can never be reused). Local clones keep working offline but can no longer sync; publishing the graph again needs repo:init in a new directory plus a re-import under a new identity.
@@ -19,6 +19,7 @@ The CLI has its own destination and commit lifecycle:
19
19
  - Every hosted graph mutation requires `--repository-id <uuid>`. For an associated local workspace, read `repository_id` from `flywheel repo:status --repo <path> --format=json`.
20
20
  - Node values, tag definitions, edge content, and artifact metadata use the file flags documented by each graph command.
21
21
  - `repo:` and `hosted:` commands default to human output. Pass `--format=json` explicitly for scripts; other available formats are listed by command help.
22
+ - A `426 client_version_unsupported` or `repository_snapshot_format_unsupported` response means the installed client is incompatible. Run `flywheel update --yes`, retry the original command, and do not discard local state.
22
23
  - Run `flywheel help <command>` for canonical per-command flags, types, defaults, examples, and related commands.
23
24
 
24
25
  ## Related MCP Operations
@@ -51,15 +52,15 @@ The families below identify related MCP operations for discovery and terminology
51
52
 
52
53
  ### Hosted graph mutations and stage leases
53
54
 
54
- - `flywheel hosted:node:create` (mutating; scopes: `write`; related MCP operation: `flywheel_commit_new_node`): Create a node in one hosted repository commit; it is not an MCP staged-payload commit.
55
+ - `flywheel hosted:node:create` (mutating; scopes: `write`; related MCP operation: `flywheel_commit_new_node`): Create a node in the hosted repository named by `--repository-id`; this never selects a default workspace or creates another repository.
55
56
  - `flywheel nodes:stage:lease:acquire` (mutating; scopes: `write`; HTTP: `POST /nodes/{node_id}/stage/lease/acquire`; related MCP operation: `flywheel_acquire_stage_lease`): Acquire a session-scoped edit lease for an existing MCP node workflow.
56
57
  - `flywheel nodes:stage:lease:heartbeat` (mutating; scopes: `write`; HTTP: `POST /nodes/{node_id}/stage/lease/heartbeat`; related MCP operation: `flywheel_heartbeat_stage_lease`): Heartbeat an active node stage lease.
57
58
  - `flywheel nodes:stage:lease:release` (mutating; scopes: `write`; HTTP: `POST /nodes/{node_id}/stage/lease/release`; related MCP operation: `flywheel_release_stage_lease`): Release a node stage lease.
58
59
  - `flywheel hosted:node:set` (mutating; scopes: `write`; related MCP operation: `flywheel_commit_node`): Set one node field in one hosted repository commit; it is not an MCP staged-payload commit.
59
- - `flywheel hosted:node:branch` (mutating; scopes: `write`; related MCP operation: `flywheel_branch_node`): Create a child branch in one hosted repository commit. Pass `--expected-head` when the caller must reject concurrent hosted changes.
60
- - `flywheel hosted:node:merge` (mutating; scopes: `write`; related MCP operation: `flywheel_merge_nodes`): Merge repeated `--source` nodes into one hosted repository commit.
61
- - `flywheel hosted:lineage:add` (mutating; scopes: `write`; related MCP operation: `flywheel_add_parent`): Add a parent-child lineage relation in one hosted repository commit.
62
- - `flywheel hosted:lineage:remove` (mutating; scopes: `write`; related MCP operation: `flywheel_remove_parent`): Remove a parent-child lineage relation in one hosted repository commit.
60
+ - `flywheel hosted:node:branch` (mutating; scopes: `write`; related MCP operation: `flywheel_branch_node`): Create a child branch in the hosted repository named by `--repository-id`. Pass `--expected-head` when the caller must reject concurrent hosted changes.
61
+ - `flywheel hosted:node:merge` (mutating; scopes: `write`; related MCP operation: `flywheel_merge_nodes`): Merge repeated `--source` nodes in the hosted repository named by `--repository-id`.
62
+ - `flywheel hosted:lineage:add` (mutating; scopes: `write`; related MCP operation: `flywheel_add_parent`): Add a parent-child lineage relation in one hosted commit; include `--parent-repository-id` when the parent lives across a repository boundary.
63
+ - `flywheel hosted:lineage:remove` (mutating; scopes: `write`; related MCP operation: `flywheel_remove_parent`): Remove a parent-child lineage relation in one hosted commit; include `--parent-repository-id` for a cross-repository parent.
63
64
  - `flywheel hosted:node:tombstone` (mutating; scopes: `write`; related MCP operation: `flywheel_delete_node`): Tombstone one node in one hosted repository commit.
64
65
  - There is no hosted bulk-tombstone command; run `flywheel hosted:node:tombstone` once per node.
65
66
 
@@ -19,6 +19,7 @@ The CLI has its own destination and commit lifecycle:
19
19
  - Every hosted graph mutation requires `--repository-id <uuid>`. For an associated local workspace, read `repository_id` from `flywheel repo:status --repo <path> --format=json`.
20
20
  - Node values, tag definitions, edge content, and artifact metadata use the file flags documented by each graph command.
21
21
  - `repo:` and `hosted:` commands default to human output. Pass `--format=json` explicitly for scripts; other available formats are listed by command help.
22
+ - A `426 client_version_unsupported` or `repository_snapshot_format_unsupported` response means the installed client is incompatible. Run `flywheel update --yes`, retry the original command, and do not discard local state.
22
23
  - Run `flywheel help <command>` for canonical per-command flags, types, defaults, examples, and related commands.
23
24
 
24
25
  ## Related MCP Operations
@@ -51,15 +52,15 @@ The families below identify related MCP operations for discovery and terminology
51
52
 
52
53
  ### Hosted graph mutations and stage leases
53
54
 
54
- - `flywheel hosted:node:create` (mutating; scopes: `write`; related MCP operation: `flywheel_commit_new_node`): Create a node in one hosted repository commit; it is not an MCP staged-payload commit.
55
+ - `flywheel hosted:node:create` (mutating; scopes: `write`; related MCP operation: `flywheel_commit_new_node`): Create a node in the hosted repository named by `--repository-id`; this never selects a default workspace or creates another repository.
55
56
  - `flywheel nodes:stage:lease:acquire` (mutating; scopes: `write`; HTTP: `POST /nodes/{node_id}/stage/lease/acquire`; related MCP operation: `flywheel_acquire_stage_lease`): Acquire a session-scoped edit lease for an existing MCP node workflow.
56
57
  - `flywheel nodes:stage:lease:heartbeat` (mutating; scopes: `write`; HTTP: `POST /nodes/{node_id}/stage/lease/heartbeat`; related MCP operation: `flywheel_heartbeat_stage_lease`): Heartbeat an active node stage lease.
57
58
  - `flywheel nodes:stage:lease:release` (mutating; scopes: `write`; HTTP: `POST /nodes/{node_id}/stage/lease/release`; related MCP operation: `flywheel_release_stage_lease`): Release a node stage lease.
58
59
  - `flywheel hosted:node:set` (mutating; scopes: `write`; related MCP operation: `flywheel_commit_node`): Set one node field in one hosted repository commit; it is not an MCP staged-payload commit.
59
- - `flywheel hosted:node:branch` (mutating; scopes: `write`; related MCP operation: `flywheel_branch_node`): Create a child branch in one hosted repository commit. Pass `--expected-head` when the caller must reject concurrent hosted changes.
60
- - `flywheel hosted:node:merge` (mutating; scopes: `write`; related MCP operation: `flywheel_merge_nodes`): Merge repeated `--source` nodes into one hosted repository commit.
61
- - `flywheel hosted:lineage:add` (mutating; scopes: `write`; related MCP operation: `flywheel_add_parent`): Add a parent-child lineage relation in one hosted repository commit.
62
- - `flywheel hosted:lineage:remove` (mutating; scopes: `write`; related MCP operation: `flywheel_remove_parent`): Remove a parent-child lineage relation in one hosted repository commit.
60
+ - `flywheel hosted:node:branch` (mutating; scopes: `write`; related MCP operation: `flywheel_branch_node`): Create a child branch in the hosted repository named by `--repository-id`. Pass `--expected-head` when the caller must reject concurrent hosted changes.
61
+ - `flywheel hosted:node:merge` (mutating; scopes: `write`; related MCP operation: `flywheel_merge_nodes`): Merge repeated `--source` nodes in the hosted repository named by `--repository-id`.
62
+ - `flywheel hosted:lineage:add` (mutating; scopes: `write`; related MCP operation: `flywheel_add_parent`): Add a parent-child lineage relation in one hosted commit; include `--parent-repository-id` when the parent lives across a repository boundary.
63
+ - `flywheel hosted:lineage:remove` (mutating; scopes: `write`; related MCP operation: `flywheel_remove_parent`): Remove a parent-child lineage relation in one hosted commit; include `--parent-repository-id` for a cross-repository parent.
63
64
  - `flywheel hosted:node:tombstone` (mutating; scopes: `write`; related MCP operation: `flywheel_delete_node`): Tombstone one node in one hosted repository commit.
64
65
  - There is no hosted bulk-tombstone command; run `flywheel hosted:node:tombstone` once per node.
65
66
 
@@ -13,10 +13,12 @@ Output:
13
13
  from __future__ import annotations
14
14
 
15
15
  import argparse
16
+ import io
16
17
  import json
17
18
  import sys
19
+ from collections.abc import Iterable, Iterator
18
20
  from pathlib import Path
19
- from typing import Any, Dict, Iterable, Iterator, List, NamedTuple, Set, Tuple
21
+ from typing import Any, NamedTuple
20
22
 
21
23
  DEFAULT_COLORS = [
22
24
  "\u001b[94m",
@@ -52,8 +54,8 @@ BOX_SPACE = " "
52
54
  class Node(NamedTuple):
53
55
  title: str
54
56
  slug_name: str
55
- parent_ids: Tuple[str, ...]
56
- child_ids: Tuple[str, ...]
57
+ parent_ids: tuple[str, ...]
58
+ child_ids: tuple[str, ...]
57
59
 
58
60
 
59
61
  def _normalize_ansi(value: str) -> str:
@@ -92,7 +94,7 @@ def _read_json_from_path(path: str) -> dict:
92
94
  return _extract_tree_payload(payload)
93
95
 
94
96
 
95
- def _load_palette(asset_path: Path) -> tuple[List[str], str]:
97
+ def _load_palette(asset_path: Path) -> tuple[list[str], str]:
96
98
  if not asset_path.exists():
97
99
  return DEFAULT_COLORS, DEFAULT_RESET
98
100
 
@@ -123,8 +125,8 @@ def _clean_text(value: Any) -> str:
123
125
  return value.strip() if isinstance(value, str) else ""
124
126
 
125
127
 
126
- def _build_node_map(nodes_payload: Iterable[dict]) -> Dict[str, Node]:
127
- node_map: Dict[str, Node] = {}
128
+ def _build_node_map(nodes_payload: Iterable[dict]) -> dict[str, Node]:
129
+ node_map: dict[str, Node] = {}
128
130
 
129
131
  for raw in nodes_payload:
130
132
  if not isinstance(raw, dict):
@@ -159,11 +161,11 @@ def _build_node_map(nodes_payload: Iterable[dict]) -> Dict[str, Node]:
159
161
 
160
162
 
161
163
  def _collect_descendants(
162
- anchor_node_id: str, node_map: Dict[str, Node]
163
- ) -> tuple[Set[str], List[str]]:
164
- descendants: Set[str] = set()
165
- order: List[str] = []
166
- stack: List[str] = [anchor_node_id]
164
+ anchor_node_id: str, node_map: dict[str, Node]
165
+ ) -> tuple[set[str], list[str]]:
166
+ descendants: set[str] = set()
167
+ order: list[str] = []
168
+ stack: list[str] = [anchor_node_id]
167
169
 
168
170
  while stack:
169
171
  current = stack.pop()
@@ -176,8 +178,7 @@ def _collect_descendants(
176
178
 
177
179
  descendants.add(current)
178
180
  order.append(current)
179
- for child_id in reversed(node.child_ids):
180
- stack.append(child_id)
181
+ stack.extend(reversed(node.child_ids))
181
182
 
182
183
  return descendants, order
183
184
 
@@ -218,8 +219,8 @@ def _iter_render_lines(
218
219
  if anchor not in descendants:
219
220
  raise ValueError(f"Could not build descendant subgraph for anchor '{anchor}'.")
220
221
 
221
- retained_children: Dict[str, Tuple[str, ...]] = {}
222
- multi_parent_nodes: List[str] = []
222
+ retained_children: dict[str, tuple[str, ...]] = {}
223
+ multi_parent_nodes: list[str] = []
223
224
 
224
225
  for node_id in ordered_descendants:
225
226
  node = node_map[node_id]
@@ -239,13 +240,13 @@ def _iter_render_lines(
239
240
  _load_palette(palette_path) if palette_path else (DEFAULT_COLORS, DEFAULT_RESET)
240
241
  )
241
242
 
242
- multi_parent_color: Dict[str, str] = {}
243
+ multi_parent_color: dict[str, str] = {}
243
244
  for idx, node_id in enumerate(multi_parent_nodes):
244
245
  multi_parent_color[node_id] = colors[idx % len(colors)]
245
246
 
246
- seen_multi_parent: Dict[str, int] = {node_id: 0 for node_id in multi_parent_nodes}
247
- ancestry: Set[str] = set()
248
- expanded_nodes: Set[str] = set()
247
+ seen_multi_parent: dict[str, int] = {node_id: 0 for node_id in multi_parent_nodes}
248
+ ancestry: set[str] = set()
249
+ expanded_nodes: set[str] = set()
249
250
 
250
251
  def line_for(node_id: str) -> str:
251
252
  node = node_map[node_id]
@@ -274,7 +275,7 @@ def _iter_render_lines(
274
275
  return rendered
275
276
 
276
277
  # Iterative DFS avoids RecursionError on very deep trees.
277
- stack: List[Tuple[Any, ...]] = [("enter", anchor, "", True, True)]
278
+ stack: list[tuple[Any, ...]] = [("enter", anchor, "", True, True)]
278
279
 
279
280
  while stack:
280
281
  frame = stack.pop()
@@ -365,10 +366,8 @@ def main() -> int:
365
366
  print(f"render_tree.py error: {exc}", file=sys.stderr)
366
367
  return 1
367
368
 
368
- try:
369
- sys.stdout.reconfigure(encoding="utf-8") # type: ignore[attr-defined]
370
- except Exception: # noqa: BLE001
371
- pass
369
+ if isinstance(sys.stdout, io.TextIOWrapper):
370
+ sys.stdout.reconfigure(encoding="utf-8")
372
371
 
373
372
  wrote_any = False
374
373
  for line in rendered_lines: