devflow-cli 6.3.0__py3-none-any.whl → 6.4.0__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.
devflow_cli/__init__.py CHANGED
@@ -1,6 +1,6 @@
1
1
  """devflow CLI — workflow de développement adaptatif."""
2
2
 
3
- VERSION = "6.3.0"
3
+ VERSION = "6.4.0"
4
4
 
5
5
  SUPPORTED_AGENTS = ["claude-code", "codex", "cursor"]
6
6
 
@@ -10,21 +10,47 @@ import typer
10
10
  from devflow_cli import ARTIFACTS
11
11
  from devflow_cli.core.adaptive_workflow import read_adaptive_state
12
12
  from devflow_cli.core.assessment import read_assessment
13
+ from devflow_cli.core.manifest import stale_commands
13
14
  from devflow_cli.core.staleness import get_staleness
14
15
  from devflow_cli.utils.console import console, make_table, warn
15
- from devflow_cli.utils.paths import iter_feature_dirs, resolve_feature_dir
16
+ from devflow_cli.utils.paths import (
17
+ get_claude_dir,
18
+ get_devflow_root,
19
+ iter_feature_dirs,
20
+ resolve_feature_dir,
21
+ )
16
22
 
17
23
 
18
24
  def status(
19
25
  issue_id: Optional[str] = typer.Argument(None, help="ID de la feature (optionnel)"),
20
26
  ) -> None:
21
27
  """Lecture rapide du statut d'une feature ou liste toutes les features."""
28
+ _warn_stale_commands()
22
29
  if issue_id is None:
23
30
  _list_features()
24
31
  else:
25
32
  _show_feature(issue_id)
26
33
 
27
34
 
35
+ def _warn_stale_commands() -> None:
36
+ """Signale les commandes /devflow installees d'une autre version, sans les modifier."""
37
+ try:
38
+ stale = stale_commands(get_devflow_root(), get_claude_dir())
39
+ except (OSError, AttributeError, ValueError) as exc:
40
+ warn(
41
+ "Commandes /devflow installees non verifiables "
42
+ f"({type(exc).__name__}). Lancer : devflow upgrade --dry-run"
43
+ )
44
+ return
45
+ if not stale:
46
+ return
47
+ paths = ", ".join(s.path for s in stale)
48
+ warn(
49
+ f"Commandes /devflow installees differentes de la CLI : {paths}. "
50
+ "Lancer : devflow upgrade"
51
+ )
52
+
53
+
28
54
  def _list_features() -> None:
29
55
  """Liste les espaces de feature et leur progression adaptative."""
30
56
  table = make_table(
@@ -6,6 +6,7 @@ import hashlib
6
6
  import json
7
7
  import os
8
8
  import re
9
+ import shutil
9
10
  import tempfile
10
11
  from dataclasses import dataclass, replace
11
12
  from datetime import datetime, timezone
@@ -53,6 +54,10 @@ MAVEN_TEST_SUMMARY_RE = re.compile(
53
54
  )
54
55
 
55
56
 
57
+ class RegressionInterpreterUnavailable(RuntimeError):
58
+ """Aucun interpreteur Python n'est disponible pour la regression."""
59
+
60
+
56
61
  @dataclass(frozen=True)
57
62
  class AutomaticVerificationOutcome:
58
63
  passed: bool
@@ -220,10 +225,21 @@ def select_regression_commands(
220
225
  if commands:
221
226
  return commands
222
227
  if (project_root / "pyproject.toml").is_file() and (project_root / "src").is_dir():
228
+ if (project_root / "uv.lock").is_file():
229
+ interpreter = ["uv", "run", "python"]
230
+ else:
231
+ name = next(
232
+ (name for name in ("python3", "python") if shutil.which(name)), None
233
+ )
234
+ if name is None:
235
+ raise RegressionInterpreterUnavailable(
236
+ "ni python3 ni python dans le PATH pour AUTO-REGRESSION-PYTHON"
237
+ )
238
+ interpreter = [name]
223
239
  return [
224
240
  ValidationCommand(
225
241
  "AUTO-REGRESSION-PYTHON",
226
- ["python", "-m", "compileall", "-q", "src"],
242
+ [*interpreter, "-m", "compileall", "-q", "src"],
227
243
  True,
228
244
  300,
229
245
  )
@@ -453,11 +469,16 @@ def run_automatic_verification(
453
469
  return AutomaticVerificationOutcome(False, "invalid-implementation-result", str(exc))
454
470
 
455
471
  commands = select_validation_commands(project_root, changed_files)
456
- regression_commands = (
457
- select_regression_commands(project_root, changed_files)
458
- if state.profile in {"standard", "deep", "critical"}
459
- else []
460
- )
472
+ try:
473
+ regression_commands = (
474
+ select_regression_commands(project_root, changed_files)
475
+ if state.profile in {"standard", "deep", "critical"}
476
+ else []
477
+ )
478
+ except RegressionInterpreterUnavailable as exc:
479
+ return AutomaticVerificationOutcome(
480
+ False, "regression-interpreter-unavailable", str(exc)
481
+ )
461
482
  security_commands: list[ValidationCommand] = []
462
483
  if state.profile in {"standard", "deep", "critical"}:
463
484
  try:
@@ -177,3 +177,21 @@ def compare_manifests(
177
177
  ))
178
178
 
179
179
  return results
180
+
181
+
182
+ def stale_commands(devflow_root: Path, claude_dir: Path) -> list[TemplateStatus]:
183
+ """Commandes /devflow installees qui ne correspondent pas a la version de la CLI.
184
+
185
+ Lecture seule. Liste vide si aucune commande devflow n'est installee
186
+ (installation codex ou cursor seule).
187
+ """
188
+ source = compute_source_manifest(devflow_root)
189
+ source["templates"] = {
190
+ path: digest
191
+ for path, digest in source["templates"].items()
192
+ if path.startswith("commands/")
193
+ }
194
+ statuses = compare_manifests(source, load_manifest(claude_dir), claude_dir)
195
+ if all(s.status == "new" for s in statuses):
196
+ return []
197
+ return [s for s in statuses if s.status != "current"]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: devflow-cli
3
- Version: 6.3.0
3
+ Version: 6.4.0
4
4
  Summary: Spec-Driven Development workflow CLI
5
5
  Project-URL: Homepage, https://github.com/sopequenoteck/devflow
6
6
  Project-URL: Repository, https://github.com/sopequenoteck/devflow
@@ -46,10 +46,17 @@ Les routes exactes et leurs preuves sont générées dans
46
46
  ## Installation
47
47
 
48
48
  ```bash
49
- uv tool install devflow-cli==X.Y.Z # version publiée, voir CHANGELOG.md
49
+ uv tool install --refresh devflow-cli==X.Y.Z # version publiée, voir CHANGELOG.md
50
50
  devflow init --ai codex
51
51
  ```
52
52
 
53
+ Après chaque mise à jour de la CLI, lancer `devflow upgrade` : il met à jour
54
+ les commandes `/devflow` installées dans `~/.claude`, que l'installation de la
55
+ CLI ne touche pas. `--refresh` évite qu'`uv` ignore une version tout juste
56
+ publiée. Tant que les commandes installées diffèrent de la CLI,
57
+ `devflow status` affiche un avertissement avec cette commande ; rien n'est
58
+ modifié sans vous.
59
+
53
60
  Installer toujours depuis PyPI, à une version précise, jamais depuis le
54
61
  dossier du dépôt. Les versions publiées sont listées dans
55
62
  [CHANGELOG.md](CHANGELOG.md).
@@ -1,4 +1,4 @@
1
- devflow_cli/__init__.py,sha256=EaJQ7YnyA-lEJmnyXiOSovWHa-5JC1C3VWMJ_7Wol4M,1002
1
+ devflow_cli/__init__.py,sha256=Ui1UQOVsR3D0756HGM1Dq0I82t1pS1q9B-g4AmmeaCU,1002
2
2
  devflow_cli/cli.py,sha256=SY0nIY0R1XjoVxGzSPn7Qcojsh6bMHHmiSKigZBndWE,2216
3
3
  devflow_cli/adapters/__init__.py,sha256=RkjHPU2Lp4hSVIq2iOmyTrv2zYU9NuiIF9wEMWzLdMI,377
4
4
  devflow_cli/adapters/agents.py,sha256=8_y70AIhmtuR8kyPN3Wpj0-i76k9wd_uaycVKTqC96g,26503
@@ -17,7 +17,7 @@ devflow_cli/commands/hooks_cmd.py,sha256=440K9AmXt6nF99JV2v6ActvG7-Pp1u6rYScEHRN
17
17
  devflow_cli/commands/init_cmd.py,sha256=VXR52ocqkO23J18pgij0Mhc_BTBl2PolxArjoCOuNow,5383
18
18
  devflow_cli/commands/linear.py,sha256=i066d5ryyBzZVfrSudbD0VWg9fSLivnB8yNe4vAMMW0,972
19
19
  devflow_cli/commands/stale.py,sha256=UiaUb48lrXmPyjfvbFkChfLE-rs58KhgKu-zgL_NBIo,3182
20
- devflow_cli/commands/status.py,sha256=b7r8lFcUOuph57BPSQzSVGr4039sIzrsSV1gW77KM54,7244
20
+ devflow_cli/commands/status.py,sha256=CKBWSbV-iLBxrRN7X0FA6bahY3Rj6fF3K0yiySfYU4s,8022
21
21
  devflow_cli/commands/traceability.py,sha256=DhUOBzSmKVk17j1Qz0yxD5zD2-iNWaR9F133VNPjy70,1767
22
22
  devflow_cli/commands/upgrade_cmd.py,sha256=d5uBFUPzPsCJDLxhQBFaeHWJv3GWWLmPpkYHRVd1gwM,5664
23
23
  devflow_cli/commands/usage.py,sha256=ehH1AH5J-XfkebFx6qLBwpKN-MOoX2uUbq4LejBpNsk,3148
@@ -28,7 +28,7 @@ devflow_cli/core/adaptive_runner.py,sha256=o9HHPNZJyA9u_zui9pNZrzMkH_jzszbI-GMwe
28
28
  devflow_cli/core/adaptive_workflow.py,sha256=qsjkahK9yklf6LjyQn69PVl9v0AoX2YPQiG2_umpb_U,13065
29
29
  devflow_cli/core/agent_failure.py,sha256=iX4q249lAHeVdD_ZF1aObmU-FX6sjfYP9dfLSnWGAD0,3771
30
30
  devflow_cli/core/assessment.py,sha256=l5QRntLJyBx3MdN-kepmMAsruHdJsG4TDgSdgOSHkqU,10062
31
- devflow_cli/core/automatic_evidence.py,sha256=DAd74AWeLF1L8ySlTgQ3tVJMgbVKfB1ZqxDv1iYm7NE,36909
31
+ devflow_cli/core/automatic_evidence.py,sha256=xDCsxrNzZh1bWfltRnmv-aI4F_yAA7bKc5o_UKWQ3NQ,37715
32
32
  devflow_cli/core/catalog.py,sha256=nLPc78JkbISaSxJnHlWiMi_lvepaumbfwcjgLuVy7Zc,3102
33
33
  devflow_cli/core/contract_schemas.py,sha256=ugHrC4vcRpf3Dn_4JGHdBIkVr_TjnKu5dvvy3b0yKec,4480
34
34
  devflow_cli/core/docgen.py,sha256=EPDP0EKIToGYN1inQRj3CSYzADNtLTI_YCFYU4YWRuM,3075
@@ -36,7 +36,7 @@ devflow_cli/core/feedback.py,sha256=ZdlEnM8mQuFpGHQ_fn1pG3L3XvLrNwkBNSw_MozJkbo,
36
36
  devflow_cli/core/git.py,sha256=o7Vk_n8b3-cAQa3CR1FblTZUvMDez7Ik4D9lrYI0njY,2561
37
37
  devflow_cli/core/hooks.py,sha256=p_NC0mR0Qa0a-LvfWhDQqqcAwxC5qRRk-lPHKUHGpiA,7942
38
38
  devflow_cli/core/installer.py,sha256=MfcGZKoOcQc2qviNnGShoD0P_MqOgRuVHX7YwCrG2vw,6259
39
- devflow_cli/core/manifest.py,sha256=964iYthqhzf3qQgxN4hZ33BvS2r7BKDZoKdiOWRybag,6322
39
+ devflow_cli/core/manifest.py,sha256=h058_m5-HJrYsNUdgfwnKts2riHiYPXUwMzPImHOs2g,7023
40
40
  devflow_cli/core/omissions.py,sha256=-9dqaQLRIy-1t6it7gecKn_0KpqbEjPIT0ec86KvXCk,7449
41
41
  devflow_cli/core/operational.py,sha256=ZEWh6DKJfHYLpV9r3vZwaDFREQwlJF0wTtgB1VleXog,1204
42
42
  devflow_cli/core/redaction.py,sha256=o_1MDtCyvRLrk_dWlV6_7E6_mPVB1B5a0cCfTBj9j0Q,1973
@@ -87,8 +87,8 @@ devflow_cli/resources/templates/contracts/api-template.md,sha256=rC5v7JBz71PznCn
87
87
  devflow_cli/resources/templates/contracts/components-template.md,sha256=XIWfEXfC72sNmL5OA3V-7xIywkNDU2DBPLfyiagOWcs,484
88
88
  devflow_cli/resources/templates/contracts/interfaces-template.md,sha256=kf8B7b6HsmN7jyRlLNU7RnZl0rTMlI5s97yVRyI-6yc,336
89
89
  devflow_cli/resources/templates/contracts/services-template.md,sha256=cFafKCyLmq_a7aR7G0LXAaMO2z4Fuflq6iKdxfVg0vg,477
90
- devflow_cli-6.3.0.dist-info/METADATA,sha256=cdAoiz3DaCyQ8xqfA75HC_OGg8kfiPRWXeLnDGxjM2A,4275
91
- devflow_cli-6.3.0.dist-info/WHEEL,sha256=W3fkpkm7-wf9vBI5Z-7s0eWkeM-spu78I8Neb98DeEg,87
92
- devflow_cli-6.3.0.dist-info/entry_points.txt,sha256=GVJ6bMvFpqyO5589iC4nFKeGTpGIW8aKn_QPPpSZ6kU,48
93
- devflow_cli-6.3.0.dist-info/licenses/LICENSE,sha256=v79PvnmqOdKhQiOa_QcWxng4q8GuGscLOwi7ygUpwpo,1070
94
- devflow_cli-6.3.0.dist-info/RECORD,,
90
+ devflow_cli-6.4.0.dist-info/METADATA,sha256=sIFKdtUiqyazlfCHRZ9Tp4vJvOVDawKsMZ6GS0vU4oU,4684
91
+ devflow_cli-6.4.0.dist-info/WHEEL,sha256=W3fkpkm7-wf9vBI5Z-7s0eWkeM-spu78I8Neb98DeEg,87
92
+ devflow_cli-6.4.0.dist-info/entry_points.txt,sha256=GVJ6bMvFpqyO5589iC4nFKeGTpGIW8aKn_QPPpSZ6kU,48
93
+ devflow_cli-6.4.0.dist-info/licenses/LICENSE,sha256=v79PvnmqOdKhQiOa_QcWxng4q8GuGscLOwi7ygUpwpo,1070
94
+ devflow_cli-6.4.0.dist-info/RECORD,,