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 +1 -1
- devflow_cli/commands/status.py +27 -1
- devflow_cli/core/automatic_evidence.py +27 -6
- devflow_cli/core/manifest.py +18 -0
- {devflow_cli-6.3.0.dist-info → devflow_cli-6.4.0.dist-info}/METADATA +9 -2
- {devflow_cli-6.3.0.dist-info → devflow_cli-6.4.0.dist-info}/RECORD +9 -9
- {devflow_cli-6.3.0.dist-info → devflow_cli-6.4.0.dist-info}/WHEEL +0 -0
- {devflow_cli-6.3.0.dist-info → devflow_cli-6.4.0.dist-info}/entry_points.txt +0 -0
- {devflow_cli-6.3.0.dist-info → devflow_cli-6.4.0.dist-info}/licenses/LICENSE +0 -0
devflow_cli/__init__.py
CHANGED
devflow_cli/commands/status.py
CHANGED
|
@@ -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
|
|
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
|
-
[
|
|
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
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
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:
|
devflow_cli/core/manifest.py
CHANGED
|
@@ -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
|
+
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=
|
|
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=
|
|
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=
|
|
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=
|
|
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.
|
|
91
|
-
devflow_cli-6.
|
|
92
|
-
devflow_cli-6.
|
|
93
|
-
devflow_cli-6.
|
|
94
|
-
devflow_cli-6.
|
|
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,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|