specify-cli 1.2.1__py3-none-any.whl → 1.2.2__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.
- specify_cli/bundles/command_init.py +6 -1
- specify_cli/bundles/manifest.py +11 -0
- specify_cli/events/__init__.py +30 -11
- specify_cli/extensions/_command_update_transaction.py +15 -0
- specify_cli/integrations/command_switch.py +21 -0
- specify_cli/integrations/zcode/__init__.py +30 -0
- specify_cli/presets/catalog/command_remove.py +8 -1
- specify_cli/workflows/_commands.py +18 -0
- specify_cli/workflows/command_resume.py +6 -0
- specify_cli/workflows/command_run.py +2 -0
- specify_cli/workflows/engine.py +5 -0
- {specify_cli-1.2.1.dist-info → specify_cli-1.2.2.dist-info}/METADATA +1 -1
- {specify_cli-1.2.1.dist-info → specify_cli-1.2.2.dist-info}/RECORD +16 -16
- {specify_cli-1.2.1.dist-info → specify_cli-1.2.2.dist-info}/WHEEL +0 -0
- {specify_cli-1.2.1.dist-info → specify_cli-1.2.2.dist-info}/entry_points.txt +0 -0
- {specify_cli-1.2.1.dist-info → specify_cli-1.2.2.dist-info}/licenses/LICENSE +0 -0
specify_cli/bundles/manifest.py
CHANGED
|
@@ -211,6 +211,17 @@ class BundleManifest:
|
|
|
211
211
|
errors.append(
|
|
212
212
|
f"{ref.kind[:-1]} '{ref.id}' has invalid version '{ref.version}'."
|
|
213
213
|
)
|
|
214
|
+
# Preset and extension installs refuse a priority below 1, which
|
|
215
|
+
# would otherwise surface only mid-install, after earlier components.
|
|
216
|
+
if (
|
|
217
|
+
ref.kind in ("extensions", "presets")
|
|
218
|
+
and ref.priority is not None
|
|
219
|
+
and ref.priority < 1
|
|
220
|
+
):
|
|
221
|
+
errors.append(
|
|
222
|
+
f"{ref.kind[:-1]} '{ref.id}' priority must be 1 or higher, "
|
|
223
|
+
f"got {ref.priority}."
|
|
224
|
+
)
|
|
214
225
|
|
|
215
226
|
for ref in self.presets:
|
|
216
227
|
if ref.priority is None:
|
specify_cli/events/__init__.py
CHANGED
|
@@ -32,6 +32,8 @@ import typer
|
|
|
32
32
|
from ..integrations._file_changes import unlink as _unlink_file, write_text as _write_text
|
|
33
33
|
|
|
34
34
|
if TYPE_CHECKING:
|
|
35
|
+
from collections.abc import Iterable
|
|
36
|
+
|
|
35
37
|
from ..integrations.base import IntegrationBase
|
|
36
38
|
from ..integrations.manifest import IntegrationManifest
|
|
37
39
|
|
|
@@ -2153,13 +2155,15 @@ def _remove_opencode_entries(config_path: Path) -> bool:
|
|
|
2153
2155
|
if existing is None:
|
|
2154
2156
|
return False
|
|
2155
2157
|
plugins = existing.get("plugin", [])
|
|
2156
|
-
|
|
2157
|
-
|
|
2158
|
-
|
|
2159
|
-
|
|
2160
|
-
|
|
2161
|
-
|
|
2162
|
-
|
|
2158
|
+
ref = "./.opencode/plugin/speckit-events.ts"
|
|
2159
|
+
# No Spec Kit plugin ref to strip: leave the user's file untouched.
|
|
2160
|
+
if not isinstance(plugins, list) or ref not in plugins:
|
|
2161
|
+
return False
|
|
2162
|
+
plugins = [p for p in plugins if p != ref]
|
|
2163
|
+
if plugins:
|
|
2164
|
+
existing["plugin"] = plugins
|
|
2165
|
+
else:
|
|
2166
|
+
existing.pop("plugin", None)
|
|
2163
2167
|
if not existing:
|
|
2164
2168
|
_unlink_file(config_path, missing_ok=True)
|
|
2165
2169
|
return True
|
|
@@ -2376,8 +2380,9 @@ def _remove_copilot_entries(dst: Path) -> bool:
|
|
|
2376
2380
|
if not isinstance(existing, dict):
|
|
2377
2381
|
return False
|
|
2378
2382
|
hooks = existing.get("hooks", {})
|
|
2379
|
-
|
|
2380
|
-
|
|
2383
|
+
# Nothing Specify-owned to strip: leave the user's file untouched.
|
|
2384
|
+
if not isinstance(hooks, dict) or not _has_marked_entry(hooks.values()):
|
|
2385
|
+
return False
|
|
2381
2386
|
cleaned: dict[str, list] = {}
|
|
2382
2387
|
for event, entries in hooks.items():
|
|
2383
2388
|
if not isinstance(entries, list):
|
|
@@ -2505,7 +2510,8 @@ def _remove_json_root_entries(dst: Path) -> bool:
|
|
|
2505
2510
|
existing = _load_user_json(dst)
|
|
2506
2511
|
if existing is None:
|
|
2507
2512
|
return False
|
|
2508
|
-
|
|
2513
|
+
# Nothing Specify-owned to strip: leave the user's file untouched.
|
|
2514
|
+
if not isinstance(existing, dict) or not _has_marked_entry(existing.values()):
|
|
2509
2515
|
return False
|
|
2510
2516
|
cleaned: dict[str, Any] = {}
|
|
2511
2517
|
for event, entries in existing.items():
|
|
@@ -2627,7 +2633,10 @@ def _remove_json_entries(dst: Path) -> bool:
|
|
|
2627
2633
|
if existing is None:
|
|
2628
2634
|
return False
|
|
2629
2635
|
hooks = existing.get("hooks", {})
|
|
2630
|
-
|
|
2636
|
+
# Nothing Specify-owned to strip: leave the user's file untouched, so a
|
|
2637
|
+
# no-op event refresh neither reformats nor deletes it (the JSON
|
|
2638
|
+
# counterpart of the TOML guard added for #4563).
|
|
2639
|
+
if not isinstance(hooks, dict) or not _has_marked_entry(hooks.values()):
|
|
2631
2640
|
return False
|
|
2632
2641
|
cleaned: dict[str, list] = {}
|
|
2633
2642
|
for event, entries in hooks.items():
|
|
@@ -2671,6 +2680,16 @@ def _has_marker(entry: Any) -> bool:
|
|
|
2671
2680
|
return False
|
|
2672
2681
|
|
|
2673
2682
|
|
|
2683
|
+
def _has_marked_entry(groups: Iterable[Any]) -> bool:
|
|
2684
|
+
"""Return True if any list among *groups* holds a Specify-marked entry."""
|
|
2685
|
+
return any(
|
|
2686
|
+
_has_marker(entry)
|
|
2687
|
+
for entries in groups
|
|
2688
|
+
if isinstance(entries, list)
|
|
2689
|
+
for entry in entries
|
|
2690
|
+
)
|
|
2691
|
+
|
|
2692
|
+
|
|
2674
2693
|
def register(app: typer.Typer) -> None:
|
|
2675
2694
|
"""Attach the event command group to the root application."""
|
|
2676
2695
|
from . import command_run # noqa: F401 -- registers handler
|
|
@@ -564,6 +564,10 @@ def run_update_command(extension: str | None) -> None:
|
|
|
564
564
|
if cfg_file.is_file():
|
|
565
565
|
shutil.copy2(cfg_file, new_extension_dir / cfg_file.name)
|
|
566
566
|
|
|
567
|
+
# Scaffold config templates the new version declares, as
|
|
568
|
+
# `extension add` does; the configs restored above are kept.
|
|
569
|
+
scaffolded, _, unscaffolded = manager.scaffold_config(extension_id)
|
|
570
|
+
|
|
567
571
|
# 9. Restore metadata from backup (installed_at, enabled state)
|
|
568
572
|
if backup_registry_entry and isinstance(backup_registry_entry, dict):
|
|
569
573
|
init_options = _commands.load_init_options(project_root)
|
|
@@ -630,6 +634,17 @@ def run_update_command(extension: str | None) -> None:
|
|
|
630
634
|
console.print(
|
|
631
635
|
f" [green]✓[/green] Updated to v{update.available}"
|
|
632
636
|
)
|
|
637
|
+
config_home = f".specify/extensions/{_escape_markup(extension_id)}"
|
|
638
|
+
for cfg in scaffolded:
|
|
639
|
+
console.print(
|
|
640
|
+
f" Config scaffolded: {config_home}/{_escape_markup(cfg)}"
|
|
641
|
+
)
|
|
642
|
+
if unscaffolded:
|
|
643
|
+
console.print(
|
|
644
|
+
" [yellow]Warning:[/yellow] Config templates not scaffolded: "
|
|
645
|
+
f"{_escape_markup(', '.join(unscaffolded))}. "
|
|
646
|
+
"Verify the extension manifest and template files."
|
|
647
|
+
)
|
|
633
648
|
if cleanup_error is not None:
|
|
634
649
|
console.print(
|
|
635
650
|
" [yellow]Warning:[/yellow] Could not fully remove "
|
|
@@ -19,6 +19,17 @@ from ._lifecycle import external_lifecycle, lifecycle_owns_rollback, lifecycle_s
|
|
|
19
19
|
from ._helpers import _MANIFEST_READ_ERRORS, _SharedTemplateRefreshError, _clear_init_options_for_integration, _cli_error_detail, _cli_phase_label, _get_speckit_version, _read_integration_json, _register_extensions_for_agent, _register_presets_for_agent, _remove_integration_json, _resolve_integration_options, _resolve_script_type, _set_default_integration, _set_default_integration_or_exit, _unregister_extensions_for_agent, _unregister_presets_for_agent, _write_integration_json
|
|
20
20
|
|
|
21
21
|
|
|
22
|
+
def _missing_required_options(integration, parsed_options) -> list[str]:
|
|
23
|
+
"""Return the integration's required options that are absent or blank."""
|
|
24
|
+
parsed = parsed_options or {}
|
|
25
|
+
missing = []
|
|
26
|
+
for option in integration.options():
|
|
27
|
+
value = parsed.get(option.name.lstrip("-").replace("-", "_"))
|
|
28
|
+
if option.required and (value is None or (isinstance(value, str) and not value.strip())):
|
|
29
|
+
missing.append(option.name)
|
|
30
|
+
return missing
|
|
31
|
+
|
|
32
|
+
|
|
22
33
|
@integration_app.command("switch")
|
|
23
34
|
@external_lifecycle("switch")
|
|
24
35
|
def integration_switch(
|
|
@@ -131,6 +142,16 @@ def integration_switch(
|
|
|
131
142
|
target_integration, current, target, integration_options
|
|
132
143
|
)
|
|
133
144
|
target_integration.is_skills_mode(target_parsed_options, project_root)
|
|
145
|
+
# Required options are otherwise only enforced by setup(), which runs
|
|
146
|
+
# after Phase 1 has already removed the current integration.
|
|
147
|
+
missing_options = _missing_required_options(target_integration, target_parsed_options)
|
|
148
|
+
if missing_options:
|
|
149
|
+
console.print(
|
|
150
|
+
f"[red]Error:[/red] Integration '{escape(target)}' requires "
|
|
151
|
+
f"{', '.join(missing_options)} in --integration-options."
|
|
152
|
+
)
|
|
153
|
+
console.print("No files were changed.")
|
|
154
|
+
raise typer.Exit(1)
|
|
134
155
|
|
|
135
156
|
# Phase 1: Uninstall current integration (if any)
|
|
136
157
|
if installed_key:
|
|
@@ -8,6 +8,10 @@ for template- and script-driven workflows such as spec-kit.
|
|
|
8
8
|
|
|
9
9
|
from __future__ import annotations
|
|
10
10
|
|
|
11
|
+
from collections.abc import Mapping, Sequence
|
|
12
|
+
from pathlib import Path
|
|
13
|
+
from typing import Any
|
|
14
|
+
|
|
11
15
|
from ..base import IntegrationOption, SkillsIntegration
|
|
12
16
|
|
|
13
17
|
|
|
@@ -40,3 +44,29 @@ class ZcodeIntegration(SkillsIntegration):
|
|
|
40
44
|
help="Install as agent skills (default for ZCode)",
|
|
41
45
|
),
|
|
42
46
|
]
|
|
47
|
+
|
|
48
|
+
def build_exec_args(
|
|
49
|
+
self,
|
|
50
|
+
prompt: str,
|
|
51
|
+
*,
|
|
52
|
+
model: str | None = None,
|
|
53
|
+
output_json: bool = True,
|
|
54
|
+
integration_args: Sequence[str] | None = None,
|
|
55
|
+
integration_options: Mapping[str, Any] | None = None,
|
|
56
|
+
project_root: Path | None = None,
|
|
57
|
+
) -> list[str] | None:
|
|
58
|
+
"""Build CLI arguments for non-interactive ``zcode`` execution.
|
|
59
|
+
|
|
60
|
+
``SkillsIntegration``'s default appends ``--model``, which the ZCode
|
|
61
|
+
CLI does not define. Its argument parser is strict, so a dispatched
|
|
62
|
+
step exits 1 with ``Unknown option '--model'`` whenever a ``model``
|
|
63
|
+
is configured. ``model`` is deliberately dropped: ZCode has no
|
|
64
|
+
per-invocation model flag and switches models in-session with
|
|
65
|
+
``/model``. ``-p`` and ``--output-format json`` are both valid.
|
|
66
|
+
"""
|
|
67
|
+
self.validate_runtime_config(integration_args, integration_options)
|
|
68
|
+
args = [self._resolve_executable(), "-p", prompt]
|
|
69
|
+
self._apply_extra_args_env_var(args)
|
|
70
|
+
if output_json:
|
|
71
|
+
args.extend(["--output-format", "json"])
|
|
72
|
+
return args
|
|
@@ -44,11 +44,18 @@ def preset_catalog_remove(
|
|
|
44
44
|
"[red]Error:[/red] Invalid catalog config: 'catalogs' must be a list."
|
|
45
45
|
)
|
|
46
46
|
raise typer.Exit(1)
|
|
47
|
+
for index, entry in enumerate(catalogs):
|
|
48
|
+
if not isinstance(entry, dict):
|
|
49
|
+
console.print(
|
|
50
|
+
f"[red]Error:[/red] Invalid catalog entry at index {index}: "
|
|
51
|
+
f"expected a mapping, got {type(entry).__name__}"
|
|
52
|
+
)
|
|
53
|
+
raise typer.Exit(1)
|
|
47
54
|
# Rendering only — the raw name drives the comparison below.
|
|
48
55
|
safe_name = _escape_markup(str(name))
|
|
49
56
|
|
|
50
57
|
original_count = len(catalogs)
|
|
51
|
-
catalogs = [c for c in catalogs if
|
|
58
|
+
catalogs = [c for c in catalogs if c.get("name") != name]
|
|
52
59
|
|
|
53
60
|
if len(catalogs) == original_count:
|
|
54
61
|
console.print(f"[red]Error:[/red] Catalog '{safe_name}' not found.")
|
|
@@ -79,6 +79,24 @@ def _fail_workflow_execution(
|
|
|
79
79
|
raise typer.Exit(1) from exc
|
|
80
80
|
|
|
81
81
|
|
|
82
|
+
def _fail_recorded_run(
|
|
83
|
+
exc: Exception, *, json_output: bool, state: Any, resume: bool = False,
|
|
84
|
+
) -> None:
|
|
85
|
+
"""Report *exc* as the run's outcome when the engine recorded it as one.
|
|
86
|
+
|
|
87
|
+
``WorkflowEngine.execute``/``resume`` persist an exception raised while
|
|
88
|
+
steps run (an expression error, say) as the run's ``failed`` status and
|
|
89
|
+
error, and mark that exception on the in-memory state, before re-raising
|
|
90
|
+
it. Errors raised before that point, such as input validation or a refused
|
|
91
|
+
resume, are not marked even when a loaded failed run carries the same
|
|
92
|
+
message, so this returns and the caller reports them as before.
|
|
93
|
+
"""
|
|
94
|
+
if state is not None and getattr(state, "_recorded_exception", None) is exc:
|
|
95
|
+
_fail_workflow_execution(
|
|
96
|
+
exc, json_output=json_output, state=state, resume=resume
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
|
|
82
100
|
def _open_workflow_registry(project_root: Path, out=None):
|
|
83
101
|
"""Construct a WorkflowRegistry, exiting cleanly on an unreadable file.
|
|
84
102
|
|
|
@@ -110,9 +110,15 @@ def workflow_resume(
|
|
|
110
110
|
exc, json_output=json_output, state=engine._execution_state.get(), resume=True,
|
|
111
111
|
)
|
|
112
112
|
except ValueError as exc:
|
|
113
|
+
cli._fail_recorded_run(
|
|
114
|
+
exc, json_output=json_output, state=engine._execution_state.get(), resume=True,
|
|
115
|
+
)
|
|
113
116
|
err.print(f"[red]Error:[/red] {cli._escape_markup(str(exc))}")
|
|
114
117
|
raise cli.typer.Exit(1)
|
|
115
118
|
except Exception as exc:
|
|
119
|
+
cli._fail_recorded_run(
|
|
120
|
+
exc, json_output=json_output, state=engine._execution_state.get(), resume=True,
|
|
121
|
+
)
|
|
116
122
|
err.print(f"[red]Resume failed:[/red] {cli._escape_markup(str(exc))}")
|
|
117
123
|
raise cli.typer.Exit(1)
|
|
118
124
|
|
|
@@ -159,9 +159,11 @@ def workflow_run(
|
|
|
159
159
|
except OSError as exc:
|
|
160
160
|
cli._fail_workflow_execution(exc, json_output=json_output, state=engine._execution_state.get())
|
|
161
161
|
except ValueError as exc:
|
|
162
|
+
cli._fail_recorded_run(exc, json_output=json_output, state=engine._execution_state.get())
|
|
162
163
|
err.print(f"[red]Error:[/red] {cli._escape_markup(str(exc))}")
|
|
163
164
|
raise cli.typer.Exit(1)
|
|
164
165
|
except Exception as exc:
|
|
166
|
+
cli._fail_recorded_run(exc, json_output=json_output, state=engine._execution_state.get())
|
|
165
167
|
err.print(f"[red]Workflow failed:[/red] {cli._escape_markup(str(exc))}")
|
|
166
168
|
raise cli.typer.Exit(1)
|
|
167
169
|
|
specify_cli/workflows/engine.py
CHANGED
|
@@ -714,6 +714,9 @@ class RunState:
|
|
|
714
714
|
self.step_results: dict[str, dict[str, Any]] = {}
|
|
715
715
|
self.execution: dict[str, Any] | None = None
|
|
716
716
|
self._checkpoint_failed = False
|
|
717
|
+
# The exception this process just recorded as the run's failure (never
|
|
718
|
+
# persisted), so the CLI can tell it apart from an older failure.
|
|
719
|
+
self._recorded_exception: BaseException | None = None
|
|
717
720
|
# Guards step_results mutation and save() so a concurrent fan-out cannot
|
|
718
721
|
# mutate the dict while save() is serializing it (which would raise
|
|
719
722
|
# "dictionary changed size during iteration").
|
|
@@ -1148,6 +1151,7 @@ class WorkflowEngine:
|
|
|
1148
1151
|
raise
|
|
1149
1152
|
state.status = RunStatus.FAILED
|
|
1150
1153
|
state.error = str(exc)
|
|
1154
|
+
state._recorded_exception = exc
|
|
1151
1155
|
state.append_log({"event": "workflow_failed", "error": str(exc)})
|
|
1152
1156
|
state.save()
|
|
1153
1157
|
raise
|
|
@@ -1262,6 +1266,7 @@ class WorkflowEngine:
|
|
|
1262
1266
|
raise
|
|
1263
1267
|
state.status = RunStatus.FAILED
|
|
1264
1268
|
state.error = str(exc)
|
|
1269
|
+
state._recorded_exception = exc
|
|
1265
1270
|
state.append_log({"event": "resume_failed", "error": str(exc)})
|
|
1266
1271
|
state.save()
|
|
1267
1272
|
raise
|
|
@@ -58,7 +58,7 @@ specify_cli/bundles/catalogs.py,sha256=cg-7YiYRwYgKrk488Nkg8I3j-O6KfcbESsEdrX_Zm
|
|
|
58
58
|
specify_cli/bundles/command_add.py,sha256=AeO_JEMWqV8XDQUgTPSy28u0Luw-0efnH8_aX9P4uo8,1118
|
|
59
59
|
specify_cli/bundles/command_build.py,sha256=DVqW3TpLZkHWverkqBE7MurWyx81wL69r7mAwtAvrkU,1116
|
|
60
60
|
specify_cli/bundles/command_info.py,sha256=UZqgnUIxJ0bA000UCt5x4N5IfyLB9D91SiTRhrfxoJU,7515
|
|
61
|
-
specify_cli/bundles/command_init.py,sha256=
|
|
61
|
+
specify_cli/bundles/command_init.py,sha256=r7sWADfl9xV9kBf6E84db3VQARn7mKKhGo6q9GGtVjI,1761
|
|
62
62
|
specify_cli/bundles/command_install.py,sha256=BNXVLxnzqIUUSSX8temWOBRMDcXJzfoUrxr2AnTcXAk,6045
|
|
63
63
|
specify_cli/bundles/command_list.py,sha256=JqtewKGBXsab-3V9U8oKSRupL6nBOYTde76gkHkA9pc,1524
|
|
64
64
|
specify_cli/bundles/command_remove.py,sha256=MeXUWiNbi_z_6kyA7bfUA_Wb0z-jWNMqc4qDJ1s0GFg,1042
|
|
@@ -68,7 +68,7 @@ specify_cli/bundles/command_validate.py,sha256=gxxHK5TxuWztfWz7B5_bscJhZ5d_qrW1P
|
|
|
68
68
|
specify_cli/bundles/component_catalog.py,sha256=GfDXhGooqM54BJE3mbnBa73x7HO4bPFBoNAjVGxVIs0,6002
|
|
69
69
|
specify_cli/bundles/conflict.py,sha256=pM2GdgNsSUrnaQ3N0RFL0BCZ9yry4pChfE7VI3QN1IU,2371
|
|
70
70
|
specify_cli/bundles/installer.py,sha256=kyUcQAAnmYGl9m9hem4Dtcjxj6mAYVhele3RJy0XnLA,18011
|
|
71
|
-
specify_cli/bundles/manifest.py,sha256=
|
|
71
|
+
specify_cli/bundles/manifest.py,sha256=c2MzDCcV-56cNOofFfYcEKq_pNb8u_TkQ_1E-o7-1AM,11940
|
|
72
72
|
specify_cli/bundles/packager.py,sha256=uS8e9hUIa38Oo78AsmxTgR5vobT6ncGdbYUerozUu7c,6487
|
|
73
73
|
specify_cli/bundles/primitives.py,sha256=bmrsaANt-RSmOEG-sYIWC0qP7jwfWW7DHDRIkeCM-mI,27596
|
|
74
74
|
specify_cli/bundles/project.py,sha256=HTXiPsibosAvU3I9xUjg3MCpeB9acxf3nKLq_1XVkIc,6526
|
|
@@ -83,13 +83,13 @@ specify_cli/bundles/catalog/__init__.py,sha256=0lmWgrtdajbD2w0HnBVfiTTLUFo4SN25M
|
|
|
83
83
|
specify_cli/bundles/catalog/command_add.py,sha256=EMV0zUbs8RPAayzwqfslIZQLJLsZlPb_aowOl3vcIX8,1543
|
|
84
84
|
specify_cli/bundles/catalog/command_list.py,sha256=zUoT6u0qxa6Ywaa-cfWKnpPxYNkfEa4VQGs9OW4Ch8o,1319
|
|
85
85
|
specify_cli/bundles/catalog/command_remove.py,sha256=KZ7zVP7MZespNWbRVvgr1bhpD0-uf-lgwOFlojOJrXU,894
|
|
86
|
-
specify_cli/events/__init__.py,sha256=
|
|
86
|
+
specify_cli/events/__init__.py,sha256=3EQQ-nltcZNVCNaj5H6cE6yhAiOzFXKRak7Qo08JAvQ,119410
|
|
87
87
|
specify_cli/events/command_run.py,sha256=oFh_whU3m9kiPU4FgdRD1bxKiQLCoAvKKb8cPNdHQD0,2296
|
|
88
88
|
specify_cli/extensions/__init__.py,sha256=6FRCn7PEKWbsxWjBJWe87u9tIFDIrKzGx29xi3AwEMg,278139
|
|
89
89
|
specify_cli/extensions/_catalog_versions.py,sha256=ElzFMhU2asQGWYoK9nmsKSNdbzzJpMZll2RfkVRIp9E,5554
|
|
90
90
|
specify_cli/extensions/_command_update_artifacts.py,sha256=GJ4GYR9wuVoeWtNNy806ULEzFRp_jt3ZHmcVbY2afHY,5943
|
|
91
91
|
specify_cli/extensions/_command_update_discovery.py,sha256=R7LeqdCqE488PXV2XN5uQbQ3HhzKcxUwofVCajwMyKo,4987
|
|
92
|
-
specify_cli/extensions/_command_update_transaction.py,sha256=
|
|
92
|
+
specify_cli/extensions/_command_update_transaction.py,sha256=Z6QNMuwzLfShOyrDpyprflI3mUPXCH-4z0uich2a6iw,47557
|
|
93
93
|
specify_cli/extensions/_commands.py,sha256=9PtGA3mwPjL1Ju22LWScW1PwQat5QrzV3xMk3GPPkgE,27744
|
|
94
94
|
specify_cli/extensions/command_add.py,sha256=-rhAknnboLRoOLWC9kbywJjglQMY0VmwFCclGIQhQI4,17919
|
|
95
95
|
specify_cli/extensions/command_disable.py,sha256=8owd9vu93g0lHjt5vJJa9xlaftd9s1sm5oHXcnTos9A,2740
|
|
@@ -122,7 +122,7 @@ specify_cli/integrations/command_list.py,sha256=EwU88UfsVecNJFXRs1daZrqz8Yl_EBK6
|
|
|
122
122
|
specify_cli/integrations/command_scaffold.py,sha256=wAECcT8a2eD_HLO1KWQcUNsiGGAQJAkQmuo81Z6IWyE,2132
|
|
123
123
|
specify_cli/integrations/command_search.py,sha256=VmdCj397uoaDW1OWS6y5WZZVFQLzfEiTuC_cvrb7qGw,4374
|
|
124
124
|
specify_cli/integrations/command_status.py,sha256=SJf-2MhQ_lYvhqQ3IrRjb4_Fz0YYAo6MWXpGL9a1Rn0,3339
|
|
125
|
-
specify_cli/integrations/command_switch.py,sha256=
|
|
125
|
+
specify_cli/integrations/command_switch.py,sha256=iI7ot6KR57V8MOk4eQBYxEFCiBnvgD-ApeZ3LCwgN0Y,18774
|
|
126
126
|
specify_cli/integrations/command_uninstall.py,sha256=_ZtEaKIfHGNOR0j9JkeWvbc0P-abkzPUOL_IBECpsGo,7647
|
|
127
127
|
specify_cli/integrations/command_upgrade.py,sha256=slHER4CZhNyscvz3AFAAlj8RdnxpUFcUiIJmQVfIBQQ,16948
|
|
128
128
|
specify_cli/integrations/command_use.py,sha256=XU4w-jTJNw6ZqXO5d0wEyN8z851JzwHu7gmTecITOQU,2655
|
|
@@ -172,7 +172,7 @@ specify_cli/integrations/shai/__init__.py,sha256=43uPKmbeZ-EDnGlkM9qsYzrsIe94HVp
|
|
|
172
172
|
specify_cli/integrations/tabnine/__init__.py,sha256=bNZoaopS368kvACXVikqZbZUlNjvyj6T8tI0M4tUJhc,1711
|
|
173
173
|
specify_cli/integrations/trae/__init__.py,sha256=dTD001UlAz1vlgQtvD4U6mu_tNNiC_nQdYII80QidjQ,1097
|
|
174
174
|
specify_cli/integrations/vibe/__init__.py,sha256=xVdJHyWCPa6dBewSjZWueWH6x8UfSUBsxGGQvb2y-iM,9255
|
|
175
|
-
specify_cli/integrations/zcode/__init__.py,sha256=
|
|
175
|
+
specify_cli/integrations/zcode/__init__.py,sha256=nD0w4U9lIUd5VXaqM_17zIGuXLRvBlHCAcUqvSJKsJ8,2422
|
|
176
176
|
specify_cli/integrations/zed/__init__.py,sha256=XyEDpaBIu0mv_dbyQl24qusuhIK2RzKmitnTPCQ1GKU,838
|
|
177
177
|
specify_cli/mcp_server/__init__.py,sha256=TWT51FaEX8Ysa8aZKHmxIJs6Ig416mWfqP1fPTj1qKE,176
|
|
178
178
|
specify_cli/mcp_server/_worker.py,sha256=YiduD0lVSQ-Rdkb0US1ti2HbeBzlgt1Pp79jtzfiM3E,135
|
|
@@ -202,7 +202,7 @@ specify_cli/presets/command_update.py,sha256=qRp5GHyrEZBDsClxc3Xyr7BikSj21NvG5Jk
|
|
|
202
202
|
specify_cli/presets/catalog/__init__.py,sha256=AAl1Y6faar4Tuy_KE2nh6qzQMQolcQkkF_rxNcvru2Y,725
|
|
203
203
|
specify_cli/presets/catalog/command_add.py,sha256=YNpmX0nGnoAS07ViEumVa4-XEZWvWR3Pu2PVFadxgDI,4194
|
|
204
204
|
specify_cli/presets/catalog/command_list.py,sha256=SwPs8HgtgQMG25fBPIkTR0TDrkcKS4TaNgfidKVf0KE,2783
|
|
205
|
-
specify_cli/presets/catalog/command_remove.py,sha256=
|
|
205
|
+
specify_cli/presets/catalog/command_remove.py,sha256=ZwoUnrCBCFuW4Xq_Opm1bFsuxfvgVUIXemUJBHOHKFo,2572
|
|
206
206
|
specify_cli/selfs/__init__.py,sha256=mvW41FasanvjzTr82hnUv3qrCbdNJpLqk_LxdiGRVqU,722
|
|
207
207
|
specify_cli/selfs/command_check.py,sha256=dwBJ2cBBkOMMLjF5to-IIEQqUvqjOj8AziZBcpsx4ds,3040
|
|
208
208
|
specify_cli/selfs/command_upgrade.py,sha256=i1VtdtEOTPagj-0LiTXOLpNxgWzpUk77_OSZu6HKX2A,7877
|
|
@@ -210,7 +210,7 @@ specify_cli/workflows/__init__.py,sha256=Ru8Da8hHxrJfC77eRJxDSxco_k-Vkw9NMXRMCYE
|
|
|
210
210
|
specify_cli/workflows/_catalog_cache.py,sha256=BSkhiY6lanh5rSZ9CgkDY_wyAtuV9SFsTPJNA7ia3fY,7166
|
|
211
211
|
specify_cli/workflows/_command_resume_state.py,sha256=zXcVBeT9gipLwAyHqmLUzhFh0TeypUX-bsEaj_vfikc,1798
|
|
212
212
|
specify_cli/workflows/_command_run_ownership.py,sha256=5-BFmNhqVkwaQTzpZRpf9mGulNpvir2EfI-znOFFv64,7843
|
|
213
|
-
specify_cli/workflows/_commands.py,sha256=
|
|
213
|
+
specify_cli/workflows/_commands.py,sha256=ZoJRl8iL9gHomXP2_aYuIGW3426Ve0PE1jVSRutHpr0,63437
|
|
214
214
|
specify_cli/workflows/_execution.py,sha256=zkzU8GAHZd23qzro3kp-PzeF3NzYhwHmZtPmCek9kM8,40687
|
|
215
215
|
specify_cli/workflows/base.py,sha256=pdM89fOJFHN4d0lxg0PHT459buVSJ-98F4EtHKvy48k,4519
|
|
216
216
|
specify_cli/workflows/command_add.py,sha256=ls4R1JTaH4AYp3AgeL7oMW7EAm2xdcfui9iY8FYJqKQ,23332
|
|
@@ -220,13 +220,13 @@ specify_cli/workflows/command_info.py,sha256=XGkBcu5x0UnoI5XOjrN05vK7u8a2IqXLQ2_
|
|
|
220
220
|
specify_cli/workflows/command_list.py,sha256=a2L9eKlk4AeUibr2AmoS29HyIychmH4X6Ptk9ilTYYg,1429
|
|
221
221
|
specify_cli/workflows/command_remove.py,sha256=m8fL9UOIO5Oh_BZBuzSgPiD2nPdCcbRPkn26ZriS0cI,4796
|
|
222
222
|
specify_cli/workflows/command_resolve.py,sha256=Go2mDhvEDN_NPNpHXNiTMt_PANR2Cn36sRkKu_CiwlU,525
|
|
223
|
-
specify_cli/workflows/command_resume.py,sha256=
|
|
224
|
-
specify_cli/workflows/command_run.py,sha256=
|
|
223
|
+
specify_cli/workflows/command_resume.py,sha256=UCU_KddQ8u1X2Lsa8AwKrgcBRh7P75X80pafBmTVvr8,6265
|
|
224
|
+
specify_cli/workflows/command_run.py,sha256=9hvuYYYBwyfqT_nmnb1Wi7l0MrGR6Vf0h1krHL9az1A,8130
|
|
225
225
|
specify_cli/workflows/command_search.py,sha256=ytgqLqvX0jR46c8jxdtvHNWIKxZJQQLXg7te9YTslD8,1700
|
|
226
226
|
specify_cli/workflows/command_status.py,sha256=dLpAJRvfBhVJS4kJEG5aNXjiAMvoSzVTluMHuHiCyiQ,5252
|
|
227
227
|
specify_cli/workflows/command_update.py,sha256=U1oWvlg_nrI1j1gyzikCycLIEhRulMcFTY2HVA8Y_l0,5810
|
|
228
228
|
specify_cli/workflows/composition.py,sha256=j5cJU2WgRUr3CKn9OAfZr_4fFz_fC1-oEAS6H2ImlsY,6116
|
|
229
|
-
specify_cli/workflows/engine.py,sha256=
|
|
229
|
+
specify_cli/workflows/engine.py,sha256=aHCgxTx1YxD_Mj4HVIMA15zUs1h0ezYHZqDp1Pfl5KI,67234
|
|
230
230
|
specify_cli/workflows/expressions.py,sha256=wu0UpabUWqUieKa1f40IGL-PgFjqCl5gDGw6xBUOktk,69727
|
|
231
231
|
specify_cli/workflows/catalog/__init__.py,sha256=hi48lfC4OBFnd-l4P009GP_Y8n219ohmBp6lMLeaFX0,1690
|
|
232
232
|
specify_cli/workflows/catalog/_domain.py,sha256=je47vVMdcE3XDlgoedd5YhsBEDqtdpLW8Az6Pz9y95k,36248
|
|
@@ -372,8 +372,8 @@ specify_cli/core_pack/templates/vscode-settings.json,sha256=PbOh2EF9OKVrQF9gtgDc
|
|
|
372
372
|
specify_cli/core_pack/workflows/assess/workflow.yml,sha256=AAnpPIQ-6dlpBHXZOX8LM8bcbSAGEWKI0u5YzN_xIag,1768
|
|
373
373
|
specify_cli/core_pack/workflows/bugfix/workflow.yml,sha256=0zcr3uE4Be-FJobRYL36Q-y85WQRRZzXxK0BxxKmP-s,1302
|
|
374
374
|
specify_cli/core_pack/workflows/speckit/workflow.yml,sha256=F3dhxeffKBJr7qBDtctFrq95WAkMAi3BGscTmUIvz7w,2118
|
|
375
|
-
specify_cli-1.2.
|
|
376
|
-
specify_cli-1.2.
|
|
377
|
-
specify_cli-1.2.
|
|
378
|
-
specify_cli-1.2.
|
|
379
|
-
specify_cli-1.2.
|
|
375
|
+
specify_cli-1.2.2.dist-info/METADATA,sha256=Yq9gc8IuZxX_2oFTdXmRWiNFfRHQZHyH7p4rKUL9nv4,12736
|
|
376
|
+
specify_cli-1.2.2.dist-info/WHEEL,sha256=W3fkpkm7-wf9vBI5Z-7s0eWkeM-spu78I8Neb98DeEg,87
|
|
377
|
+
specify_cli-1.2.2.dist-info/entry_points.txt,sha256=zO7Jooxo-O6FCM02xdzsNB8WNakvnPDv5bpZr1P4Pmo,45
|
|
378
|
+
specify_cli-1.2.2.dist-info/licenses/LICENSE,sha256=JRC0RrwfDPlwJFMHXSDNiGMeIOVkJljttzJdnB61NPc,1060
|
|
379
|
+
specify_cli-1.2.2.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|