devflow-cli 9.0.0__py3-none-any.whl → 9.0.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.
devflow_cli/__init__.py CHANGED
@@ -1,6 +1,6 @@
1
1
  """devflow CLI — workflow de développement adaptatif."""
2
2
 
3
- VERSION = "9.0.0"
3
+ VERSION = "9.0.1"
4
4
 
5
5
  SUPPORTED_AGENTS = ["claude-code", "codex", "cursor"]
6
6
 
@@ -1351,7 +1351,7 @@ def _operational_status(
1351
1351
  ) -> dict:
1352
1352
  result_file, result = _latest_activity_result(feature_dir, state.currentActivity)
1353
1353
  blockers = result.get("blockers", []) if isinstance(result, dict) else []
1354
- risks = latest_remaining_risks(feature_dir, state.activities)
1354
+ risks = latest_remaining_risks(feature_dir, state)
1355
1355
  if not isinstance(blockers, list):
1356
1356
  blockers = []
1357
1357
  stale: set[str] = set()
@@ -58,6 +58,27 @@ def _ignore_agent_traces(feature_dir) -> None:
58
58
  )
59
59
 
60
60
 
61
+ LOCK_IGNORE_RULES = (".workflow-state.lock", ".agent-run.lock", ".feature-lock")
62
+
63
+
64
+ def _ignore_cli_locks(specs_root) -> None:
65
+ """Exclut du depot les verrous de la CLI, a toute profondeur sous les specs."""
66
+ gitignore = specs_root / ".gitignore"
67
+ content = gitignore.read_text(encoding="utf-8") if gitignore.is_file() else ""
68
+ present = content.splitlines()
69
+ missing = [rule for rule in LOCK_IGNORE_RULES if rule not in present]
70
+ if not missing:
71
+ return
72
+ prefix = "" if not content or content.endswith("\n") else "\n"
73
+ gitignore.write_text(
74
+ content
75
+ + prefix
76
+ + "# Verrous de la CLI devflow : fichiers d'execution, jamais suivis.\n"
77
+ + "".join(f"{rule}\n" for rule in missing),
78
+ encoding="utf-8",
79
+ )
80
+
81
+
61
82
  def feature(
62
83
  issue_id: str = typer.Argument(..., help="Identifiant de l'issue (ex: KS-123)"),
63
84
  short_name: Optional[str] = typer.Option(None, "--short-name", help="Nom court pour le repertoire (ex: user-auth)"),
@@ -107,6 +128,7 @@ def feature(
107
128
  feature_dir.mkdir(parents=True)
108
129
  ok(f"Dossier {feature_dir} cree")
109
130
  _ignore_agent_traces(feature_dir)
131
+ _ignore_cli_locks(specs_root)
110
132
 
111
133
  console.print()
112
134
  console.print(f"Feature [bold]{issue_id}[/bold] initialisee :")
@@ -599,7 +599,7 @@ def run_automatic_verification(
599
599
  commands = regression_commands
600
600
  reuse_targeted_as_regression = True
601
601
  document_batch: list[str] | None = None
602
- if not commands and state.profile == "quick" and not guardrails_active(state):
602
+ if not commands and state.profile == "quick":
603
603
  document_batch = _observed_document_batch(state, feature_dir, project_root)
604
604
  if not commands and document_batch is None:
605
605
  return AutomaticVerificationOutcome(
@@ -9,7 +9,7 @@ import tempfile
9
9
  from pathlib import Path
10
10
  from typing import Any
11
11
 
12
- from devflow_cli.core.adaptive_workflow import read_adaptive_state
12
+ from devflow_cli.core.adaptive_workflow import AdaptiveWorkflowState, read_adaptive_state
13
13
  from devflow_cli.utils.logging import get_logger
14
14
  from devflow_cli.utils.paths import activity_result_file
15
15
 
@@ -31,7 +31,7 @@ def refresh_worklog(feature_dir: Path) -> Path:
31
31
 
32
32
  result = _read_json(activity_result_file(feature_dir, "implement"), required=False)
33
33
  review = _read_json(activity_result_file(feature_dir, "review"), required=False)
34
- risks = latest_remaining_risks(feature_dir, state.activities)
34
+ risks = latest_remaining_risks(feature_dir, state)
35
35
  rollback = _read_json(
36
36
  activity_result_file(feature_dir, "rollback-check"), required=False
37
37
  )
@@ -78,11 +78,19 @@ def refresh_worklog(feature_dir: Path) -> Path:
78
78
  return worklog_file
79
79
 
80
80
 
81
- def latest_remaining_risks(feature_dir: Path, activities: list[str]) -> list[str]:
82
- """Risques du resultat le plus recent de la route (dernier lisible), sans doublon."""
83
- for activity in reversed(activities):
81
+ def latest_remaining_risks(feature_dir: Path, state: AdaptiveWorkflowState) -> list[str]:
82
+ """Risques du resultat le plus recent de la route (dernier lisible), sans doublon.
83
+
84
+ Seuls comptent les resultats des activites completees et celui de l'activite
85
+ courante s'il date du passage en cours : un resultat reste d'avant une
86
+ reouverture est ignore.
87
+ """
88
+ for activity in reversed(state.activities):
89
+ completed = activity in state.completedActivities
90
+ if not completed and activity != state.currentActivity:
91
+ continue
84
92
  payload = _read_json(activity_result_file(feature_dir, activity), required=False)
85
- if not payload:
93
+ if not payload or (not completed and not _in_current_pass(payload, state)):
86
94
  continue
87
95
  values = payload.get("remainingRisks", [])
88
96
  risks: list[str] = []
@@ -94,6 +102,19 @@ def latest_remaining_risks(feature_dir: Path, activities: list[str]) -> list[str
94
102
  return []
95
103
 
96
104
 
105
+ def _in_current_pass(payload: dict[str, Any], state: AdaptiveWorkflowState) -> bool:
106
+ """Vrai si le resultat est observe a partir de la base de l'activite courante."""
107
+ observation = payload.get("observation")
108
+ base = state.activityBase
109
+ if not isinstance(observation, dict) or not isinstance(base, dict):
110
+ return False
111
+ observed_at = observation.get("observedAt")
112
+ recorded_at = base.get("recordedAt")
113
+ if not isinstance(observed_at, str) or not isinstance(recorded_at, str):
114
+ return False
115
+ return observed_at >= recorded_at
116
+
117
+
97
118
  def safe_refresh_worklog(feature_dir: Path) -> Path | None:
98
119
  """Actualise la vue derivee sans compromettre une transition deja validee."""
99
120
  try:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: devflow-cli
3
- Version: 9.0.0
3
+ Version: 9.0.1
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
@@ -1,17 +1,17 @@
1
- devflow_cli/__init__.py,sha256=TVrbUn4dfhBCXtCVCypThAPpg7SGLsuYX076rhwMzac,925
1
+ devflow_cli/__init__.py,sha256=Tfuh5bs4jxcmKz60Sl2SlpkjlklSnlvidwCX8PE5Qe0,925
2
2
  devflow_cli/cli.py,sha256=0_SmhJX_k7OQfp-jNV_jq9EOgWY4rTjStGIoc9pH6Ec,2686
3
3
  devflow_cli/adapters/__init__.py,sha256=RkjHPU2Lp4hSVIq2iOmyTrv2zYU9NuiIF9wEMWzLdMI,377
4
4
  devflow_cli/adapters/agents.py,sha256=01ZQb96koWMKH-mma3AtttdEjNEbu3mM89vFetD9iR8,29689
5
5
  devflow_cli/adapters/linear.py,sha256=HE1YzjBxwoj2jJ_3bmh9Pn_7Mt5u3EOLk891vMXBEj4,8700
6
6
  devflow_cli/commands/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
7
- devflow_cli/commands/adaptive.py,sha256=iCS0BvaD2Z1fgI3cUsdrpQs52w_THS-v2I8AyvJy2N8,72771
7
+ devflow_cli/commands/adaptive.py,sha256=O1azx9UIF32gidrbX2j07fE9IdStNq2fku67_Peqxmk,72760
8
8
  devflow_cli/commands/assess.py,sha256=V-E3ft41ljCrqp2WLjR1Dqw-JtswcqsK2nD1-euNbNE,5655
9
9
  devflow_cli/commands/check.py,sha256=hsfeOg9yDOTAIvNm6XhRmTIFgv7w9wC8zvrwm4ojfZs,6923
10
10
  devflow_cli/commands/context.py,sha256=hwTitOHxIpJMx1X8R1jHHy9CpE4HVZpJKkyeOujxAio,6246
11
11
  devflow_cli/commands/docs_sync.py,sha256=Xc0mulpNTjDyeUDumKL7VNG0eumAf3016wEM_dqXpSU,1021
12
12
  devflow_cli/commands/export_cmd.py,sha256=_DVgQru8z7UM9br-ntzMkNPcDL9OpY1G6S3cMPJ4Gqo,3259
13
13
  devflow_cli/commands/extension.py,sha256=W2bc1xntJmDUrvLt8GFgg3lgTcJSwmGGTDPUkrxonBo,4494
14
- devflow_cli/commands/feature.py,sha256=gomtMUUJl-0YfZZIx0PHNHBX-Rq5GhmMZE-XkP55SwE,4200
14
+ devflow_cli/commands/feature.py,sha256=IkXKdKTNK6QTTzIG3zFu5a13_MMBEsTc1xjvUjdOLVo,5006
15
15
  devflow_cli/commands/feedback.py,sha256=pKG4jCsyVcfTA7Df_qe8tYF1VzveLJ-WfR9BcV9ZtMM,10268
16
16
  devflow_cli/commands/hooks_cmd.py,sha256=BMzNBKHIpQkMj5y-2bxtCNqAa8cncGfGTWMgx6SUeeQ,6133
17
17
  devflow_cli/commands/init_cmd.py,sha256=VXR52ocqkO23J18pgij0Mhc_BTBl2PolxArjoCOuNow,5383
@@ -30,7 +30,7 @@ devflow_cli/core/adaptive_workflow.py,sha256=NgDEr67monxalcGiO3R_ACVUrZu_OX6LQRh
30
30
  devflow_cli/core/agent_failure.py,sha256=iX4q249lAHeVdD_ZF1aObmU-FX6sjfYP9dfLSnWGAD0,3771
31
31
  devflow_cli/core/agent_run_marker.py,sha256=QW3ScA2ZpqfQdUo5ANTbenDVyY2iHpB_wTaN6VUKlzc,3451
32
32
  devflow_cli/core/assessment.py,sha256=ACtJbXq1qZjVfeERjy8Qg6-ioLfSMUBVQm2l-mtGwgI,11522
33
- devflow_cli/core/automatic_evidence.py,sha256=wBsOwQvwNSETefSMkZK6tcb3aDErgbVK9WANknT8HN4,42592
33
+ devflow_cli/core/automatic_evidence.py,sha256=pqSnNXe6RHthII6fgoHlCNkGiFTKQ4yyRtErGUwbvas,42559
34
34
  devflow_cli/core/catalog.py,sha256=nLPc78JkbISaSxJnHlWiMi_lvepaumbfwcjgLuVy7Zc,3102
35
35
  devflow_cli/core/contract_schemas.py,sha256=JXI8PVgjdagTlFxnyuIkNRRrVi319Mv8GwuMxopJ_GI,8424
36
36
  devflow_cli/core/docgen.py,sha256=47JoVDWetkcctgHwJZC67AVebOKgl10VB9hZ3Xr63mo,3908
@@ -53,7 +53,7 @@ devflow_cli/core/validation_approvals.py,sha256=3AHOpnW3BtY3BQrRZr38K7VNYRvbxGNh
53
53
  devflow_cli/core/validators.py,sha256=fREjEx2fBW36q3vB6WJNqoGUM9ejYlQUXie5A9lNuPs,7440
54
54
  devflow_cli/core/verification.py,sha256=rvbdAdLyrZYb20oauti7D8nV5TDFBIf_8-hqLahfRag,23576
55
55
  devflow_cli/core/waivers.py,sha256=9XXzMmoWCn-2Dc3486WhZwtGJQLQPXjP0qAaLuL_3qU,13299
56
- devflow_cli/core/worklog.py,sha256=itKIgzduDvl5STv3B_Yle9qi9W11Xhbg4_bDyCFVBqQ,14850
56
+ devflow_cli/core/worklog.py,sha256=NedQaNrydudJ_uN3bCyo7n3plAcU1-4bYcK3WbLnu9E,15834
57
57
  devflow_cli/core/worktree_snapshot.py,sha256=Q2_KTkhJTGvdM6Ay4RK9OHkyPEMrHQRTb-f-Eptek-8,5255
58
58
  devflow_cli/schemas/activity-contract-v4.schema.json,sha256=IeduWDiJ5IV6EL7FDZWnHBjzyUt1uwig2rB-SMbcpOU,2006
59
59
  devflow_cli/schemas/activity-result-v2.schema.json,sha256=2yDf6S--mlNWMxE8h8ruwTsM3Tnaa96SJDjluc4ePbI,2772
@@ -90,8 +90,8 @@ devflow_cli/resources/templates/contracts/api-template.md,sha256=rC5v7JBz71PznCn
90
90
  devflow_cli/resources/templates/contracts/components-template.md,sha256=XIWfEXfC72sNmL5OA3V-7xIywkNDU2DBPLfyiagOWcs,484
91
91
  devflow_cli/resources/templates/contracts/interfaces-template.md,sha256=kf8B7b6HsmN7jyRlLNU7RnZl0rTMlI5s97yVRyI-6yc,336
92
92
  devflow_cli/resources/templates/contracts/services-template.md,sha256=cFafKCyLmq_a7aR7G0LXAaMO2z4Fuflq6iKdxfVg0vg,477
93
- devflow_cli-9.0.0.dist-info/METADATA,sha256=P54H3nX_kUKvDUIgpC69PPpSkrT59fM-yLGl1Q2K9rs,10403
94
- devflow_cli-9.0.0.dist-info/WHEEL,sha256=W3fkpkm7-wf9vBI5Z-7s0eWkeM-spu78I8Neb98DeEg,87
95
- devflow_cli-9.0.0.dist-info/entry_points.txt,sha256=GVJ6bMvFpqyO5589iC4nFKeGTpGIW8aKn_QPPpSZ6kU,48
96
- devflow_cli-9.0.0.dist-info/licenses/LICENSE,sha256=v79PvnmqOdKhQiOa_QcWxng4q8GuGscLOwi7ygUpwpo,1070
97
- devflow_cli-9.0.0.dist-info/RECORD,,
93
+ devflow_cli-9.0.1.dist-info/METADATA,sha256=-KXUYGCIKFccREWb0WIeBhrIvsbwWK-3e5vMFLU_zQ0,10403
94
+ devflow_cli-9.0.1.dist-info/WHEEL,sha256=W3fkpkm7-wf9vBI5Z-7s0eWkeM-spu78I8Neb98DeEg,87
95
+ devflow_cli-9.0.1.dist-info/entry_points.txt,sha256=GVJ6bMvFpqyO5589iC4nFKeGTpGIW8aKn_QPPpSZ6kU,48
96
+ devflow_cli-9.0.1.dist-info/licenses/LICENSE,sha256=v79PvnmqOdKhQiOa_QcWxng4q8GuGscLOwi7ygUpwpo,1070
97
+ devflow_cli-9.0.1.dist-info/RECORD,,