deepcell-cli 0.6.1__py3-none-any.whl

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 (67) hide show
  1. deepcell_cli/__init__.py +12 -0
  2. deepcell_cli/__main__.py +5 -0
  3. deepcell_cli/_findings.py +84 -0
  4. deepcell_cli/capabilities.py +560 -0
  5. deepcell_cli/capability-contract.json +15622 -0
  6. deepcell_cli/client.py +503 -0
  7. deepcell_cli/commands/__init__.py +1 -0
  8. deepcell_cli/commands/_batch_input.py +29 -0
  9. deepcell_cli/commands/_datatypes.py +56 -0
  10. deepcell_cli/commands/_negative_args.py +133 -0
  11. deepcell_cli/commands/_swapped_args.py +153 -0
  12. deepcell_cli/commands/_version_display.py +40 -0
  13. deepcell_cli/commands/_write_opts.py +139 -0
  14. deepcell_cli/commands/account.py +123 -0
  15. deepcell_cli/commands/auth.py +610 -0
  16. deepcell_cli/commands/changes.py +307 -0
  17. deepcell_cli/commands/deck.py +594 -0
  18. deepcell_cli/commands/defs.py +3890 -0
  19. deepcell_cli/commands/describe.py +902 -0
  20. deepcell_cli/commands/doc.py +529 -0
  21. deepcell_cli/commands/doctor.py +257 -0
  22. deepcell_cli/commands/download.py +36 -0
  23. deepcell_cli/commands/edit.py +384 -0
  24. deepcell_cli/commands/example.py +161 -0
  25. deepcell_cli/commands/export.py +81 -0
  26. deepcell_cli/commands/export_docx.py +57 -0
  27. deepcell_cli/commands/export_pdf.py +66 -0
  28. deepcell_cli/commands/export_pptx.py +45 -0
  29. deepcell_cli/commands/files.py +386 -0
  30. deepcell_cli/commands/grep.py +90 -0
  31. deepcell_cli/commands/guide.py +431 -0
  32. deepcell_cli/commands/help_cmd.py +348 -0
  33. deepcell_cli/commands/impact.py +382 -0
  34. deepcell_cli/commands/import_cmd.py +208 -0
  35. deepcell_cli/commands/ingest.py +110 -0
  36. deepcell_cli/commands/merge.py +399 -0
  37. deepcell_cli/commands/query.py +718 -0
  38. deepcell_cli/commands/reasoning.py +2981 -0
  39. deepcell_cli/commands/ref.py +279 -0
  40. deepcell_cli/commands/replace.py +326 -0
  41. deepcell_cli/commands/rules.py +206 -0
  42. deepcell_cli/commands/share.py +186 -0
  43. deepcell_cli/commands/sync.py +804 -0
  44. deepcell_cli/commands/upgrade.py +185 -0
  45. deepcell_cli/commands/variant.py +353 -0
  46. deepcell_cli/commands/version.py +445 -0
  47. deepcell_cli/commands/viewer.py +54 -0
  48. deepcell_cli/commands/workspace.py +101 -0
  49. deepcell_cli/config.py +352 -0
  50. deepcell_cli/context.py +187 -0
  51. deepcell_cli/errors.py +141 -0
  52. deepcell_cli/logging_setup.py +161 -0
  53. deepcell_cli/main.py +518 -0
  54. deepcell_cli/mcp_server.py +906 -0
  55. deepcell_cli/oauth_provider.py +580 -0
  56. deepcell_cli/output.py +503 -0
  57. deepcell_cli/revision.py +164 -0
  58. deepcell_cli/stages.py +223 -0
  59. deepcell_cli/surface.py +628 -0
  60. deepcell_cli/sync_state.py +120 -0
  61. deepcell_cli/upgrade_check.py +399 -0
  62. deepcell_cli/xml_replace.py +89 -0
  63. deepcell_cli-0.6.1.dist-info/METADATA +264 -0
  64. deepcell_cli-0.6.1.dist-info/RECORD +67 -0
  65. deepcell_cli-0.6.1.dist-info/WHEEL +5 -0
  66. deepcell_cli-0.6.1.dist-info/entry_points.txt +3 -0
  67. deepcell_cli-0.6.1.dist-info/top_level.txt +1 -0
deepcell_cli/stages.py ADDED
@@ -0,0 +1,223 @@
1
+ """The one authored place a command's stage lives.
2
+
3
+ The root help carried 51 commands in 13 subsystem sections ordered by nothing,
4
+ plus an ``Other`` catch-all that ``docs/cli-help-review.md`` dimension 6
5
+ forbids by name. Three more hand-maintained groupings of the same command set
6
+ existed alongside it — the MCP tool description, ``docs/cli-commands.md``, and
7
+ the generated manifest, which carried no grouping at all — and they disagreed:
8
+ ``changes`` was Version Control in one, Sync in another, and uncategorized in
9
+ ``--help``. Nothing tested any of them.
10
+
11
+ This module is the fix. A command's stage is declared here once; ``main.py``
12
+ renders the index from it, ``surface.py`` emits it into the manifest, and the
13
+ other catalogs derive rather than restate. :func:`assert_fully_staged` turns an
14
+ unstaged command into a loud failure instead of an ``Other`` row.
15
+
16
+ **The stages are guide's stages**, in guide's order — see
17
+ ``backend/src/core/guide/staged.py``. That is the point: an agent that just
18
+ read ``guide generate/calcs`` should already know where ``defs add-calc``
19
+ lives. Two vocabularies for one workflow is the problem this removes.
20
+
21
+ **Three tiers are deliberately not stages.** Signing in, syncing, and looking
22
+ something up are not steps in building a piece of work — they surround it. A
23
+ seventh "stage" for them would be a lie about the shape of the work, so they
24
+ render as collapsed name runs under their own heading instead.
25
+ """
26
+
27
+ from __future__ import annotations
28
+
29
+ #: Display order. Not alphabetical — it is the order the work happens in, and
30
+ #: an index listing `generate` after `present` would teach the wrong shape.
31
+ STAGE_ORDER: list[str] = [
32
+ "orient",
33
+ "ingest",
34
+ "generate",
35
+ "revise",
36
+ "verify",
37
+ "present",
38
+ ]
39
+
40
+ #: One line per stage, shown as the section header. Kept in step with
41
+ #: ``guide``'s own stage summaries — the wording differs only where a command
42
+ #: index needs to say something a topic index does not.
43
+ STAGE_SUMMARY: dict[str, str] = {
44
+ "orient": "look at what exists before adding to it",
45
+ "ingest": "external data in (skip for from-scratch work)",
46
+ "generate": "create one file, then build only the surfaces the work needs",
47
+ "revise": "change a premise and reassess what depends on it",
48
+ "verify": "change one thing, see everything it affects",
49
+ "present": "deliver the work to someone else",
50
+ }
51
+
52
+ #: The non-stage tiers, in display order.
53
+ TAIL_ORDER: list[str] = ["session", "sync", "learn"]
54
+
55
+ TAIL_SUMMARY: dict[str, str] = {
56
+ "session": "who you are and where your work lands",
57
+ "sync": "local <-> cloud",
58
+ "learn": "the five reference surfaces",
59
+ }
60
+
61
+ #: Every top-level command, and the tier it renders under. A command missing
62
+ #: from this table fails :func:`assert_fully_staged` — which is the whole
63
+ #: reason the table exists, since the old catch-all made "unassigned" invisible.
64
+ #:
65
+ #: Placement notes for the ones that are genuinely arguable:
66
+ #:
67
+ #: * ``cell-meta`` is orient, not verify. It answers "what does this cell rest
68
+ #: on", which is inspection; ``relationships`` answers "what rests on this",
69
+ #: which is the impact question verify owns.
70
+ #: * ``download`` is sync, not present. It moves a file to local disk, which is
71
+ #: what ``clone`` and ``pull`` do; ``share`` and the exports hand work to a
72
+ #: person.
73
+ #: * ``rm`` is revise, not generate. Deleting is a change to existing work.
74
+ COMMAND_TIER: dict[str, str] = {
75
+ # ORIENT — look first.
76
+ "ls": "orient",
77
+ "cat": "orient",
78
+ "describe": "orient",
79
+ "query": "orient",
80
+ "cell-meta": "orient",
81
+ "grep": "orient",
82
+ # INGEST — external data in.
83
+ "import": "ingest",
84
+ "ingest": "ingest",
85
+ # GENERATE — one file, then the surfaces the work needs. The four
86
+ # surfaces of a .deepcell file each have their authoring command here:
87
+ # reasoning (ideas), defs/edit (calculations), doc (documents),
88
+ # deck (slides).
89
+ "write": "generate",
90
+ "reasoning": "generate",
91
+ "defs": "generate",
92
+ "edit": "generate",
93
+ "doc": "generate",
94
+ "deck": "generate",
95
+ # REVISE — change a premise, reassess what depends on it.
96
+ "replace": "revise",
97
+ "variant": "revise",
98
+ "changes": "revise",
99
+ "log": "revise",
100
+ "diff": "revise",
101
+ "restore": "revise",
102
+ "rm": "revise",
103
+ # VERIFY — the connectedness story: change one thing, see what it affects.
104
+ "relationships": "verify",
105
+ "claim": "verify",
106
+ "assumption": "verify",
107
+ "reasoning-diff": "verify",
108
+ # `impact` is the whole of that story in one call. The four above each
109
+ # answer a narrower question and still do; this one is the only one that
110
+ # carries a change through to the Document sections and Deck slides
111
+ # instead of stopping at the reasoning node.
112
+ "impact": "verify",
113
+ # PRESENT — deliver.
114
+ "viewer": "present",
115
+ "share": "present",
116
+ "to-excel": "present",
117
+ "to-docx": "present",
118
+ "to-pptx": "present",
119
+ "to-pdf": "present",
120
+ # SESSION — surrounds the work rather than being a step in it.
121
+ "login": "session",
122
+ "register": "session",
123
+ "logout": "session",
124
+ "whoami": "session",
125
+ "verify-email": "session",
126
+ "account": "session",
127
+ "project": "session",
128
+ "doctor": "session",
129
+ "upgrade": "session",
130
+ # SYNC — local <-> cloud.
131
+ "clone": "sync",
132
+ "status": "sync",
133
+ "pull": "sync",
134
+ "push": "sync",
135
+ "commit": "sync",
136
+ "merge": "sync",
137
+ "download": "sync",
138
+ # LEARN — the five reference surfaces.
139
+ "help": "learn",
140
+ "guide": "learn",
141
+ "rules": "learn",
142
+ "ref": "learn",
143
+ "example": "learn",
144
+ }
145
+
146
+ #: Commands whose one-line summary is worth the vertical space in the index,
147
+ #: because a reader choosing between them picks the wrong *tool* otherwise —
148
+ #: ``docs/cli-help-review.md`` dimension 6. Everything else collapses to a name
149
+ #: run, which is what buys the index its one-screen budget back.
150
+ #:
151
+ #: The sets are the sibling groups themselves: inspect-a-file, write-a-value,
152
+ #: and hand-it-over.
153
+ DISAMBIGUATED: frozenset[str] = frozenset(
154
+ {
155
+ "describe",
156
+ "query",
157
+ "grep",
158
+ "cell-meta",
159
+ "edit",
160
+ "defs",
161
+ "replace",
162
+ "write",
163
+ "reasoning",
164
+ "doc",
165
+ "deck",
166
+ "viewer",
167
+ "share",
168
+ "relationships",
169
+ "changes",
170
+ }
171
+ )
172
+
173
+ ALL_TIERS: list[str] = STAGE_ORDER + TAIL_ORDER
174
+
175
+ TIER_SUMMARY: dict[str, str] = {**STAGE_SUMMARY, **TAIL_SUMMARY}
176
+
177
+
178
+ def tier_for(command: str) -> str | None:
179
+ """The tier ``command`` renders under, or ``None`` if it is unstaged."""
180
+ return COMMAND_TIER.get(command)
181
+
182
+
183
+ def commands_in(tier: str) -> list[str]:
184
+ """Every command in ``tier``, in declaration order.
185
+
186
+ Declaration order, not alphabetical: within a stage the commands are
187
+ listed in the order the work uses them, so ``write`` precedes the surface
188
+ authoring commands rather than sorting after ``reasoning``.
189
+ """
190
+ return [name for name, t in COMMAND_TIER.items() if t == tier]
191
+
192
+
193
+ def assert_fully_staged(command_names: object) -> None:
194
+ """Raise if any live command has no tier, or any tier names a dead command.
195
+
196
+ Both directions matter. An unstaged command used to fall into an ``Other``
197
+ bucket and nobody noticed for two releases; a stale entry here would keep
198
+ a deleted command in the index just as quietly.
199
+ """
200
+ live = {str(n) for n in command_names} # type: ignore[union-attr]
201
+ declared = set(COMMAND_TIER)
202
+
203
+ unstaged = sorted(live - declared)
204
+ if unstaged:
205
+ raise AssertionError(
206
+ "Commands with no tier in stages.COMMAND_TIER: "
207
+ f"{', '.join(unstaged)}. Add each to a stage — there is no "
208
+ "catch-all bucket to fall into."
209
+ )
210
+
211
+ stale = sorted(declared - live)
212
+ if stale:
213
+ raise AssertionError(
214
+ "stages.COMMAND_TIER names commands that no longer exist: "
215
+ f"{', '.join(stale)}."
216
+ )
217
+
218
+ bad_tier = sorted(n for n, t in COMMAND_TIER.items() if t not in ALL_TIERS)
219
+ if bad_tier:
220
+ raise AssertionError(
221
+ f"Commands assigned to an unknown tier: {', '.join(bad_tier)}. "
222
+ f"Valid tiers: {', '.join(ALL_TIERS)}."
223
+ )