devflow-cli 6.1.0__py3-none-any.whl → 6.1.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 = "6.1.0"
3
+ VERSION = "6.1.1"
4
4
 
5
5
  SUPPORTED_AGENTS = ["claude-code", "codex", "cursor"]
6
6
 
@@ -377,7 +377,7 @@ def run_adaptive(
377
377
  attempt["contract"] = activity_contract
378
378
  attempt["startedAt"] = _utc_now()
379
379
  try:
380
- before = snapshot_worktree(project_root)
380
+ before = snapshot_worktree(project_root, feature_dir)
381
381
  with tempfile.TemporaryDirectory(prefix="devflow-adaptive-") as temp_dir:
382
382
  temp_path = Path(temp_dir)
383
383
  schema_file = temp_path / "output-schema.json"
@@ -403,7 +403,7 @@ def run_adaptive(
403
403
  if output_file.is_file()
404
404
  else execution.stdout
405
405
  )
406
- after = snapshot_worktree(project_root)
406
+ after = snapshot_worktree(project_root, feature_dir)
407
407
  observed = tuple(changed_paths(before, after))
408
408
  attempt["changedFileCount"] = len(observed)
409
409
  audit_payload = {
@@ -296,7 +296,7 @@ def reconcile_current_activity(
296
296
  raise ValueError(
297
297
  "la tentative ne correspond pas au contrat de l'activite courante"
298
298
  )
299
- snapshot = snapshot_worktree(project_root_for_feature(feature_dir))
299
+ snapshot = snapshot_worktree(project_root_for_feature(feature_dir), feature_dir)
300
300
  if snapshot.head != attempt.get("head") or snapshot.branch != attempt.get("branch"):
301
301
  raise ValueError("HEAD ou la branche a change depuis la tentative")
302
302
  drifted = sorted(
@@ -784,7 +784,7 @@ def _record_failed_attempt(
784
784
  ) -> None:
785
785
  """Consigne les faits d'une tentative refusee pour une reprise controlee."""
786
786
  try:
787
- snapshot = snapshot_worktree(project_root_for_feature(feature_dir))
787
+ snapshot = snapshot_worktree(project_root_for_feature(feature_dir), feature_dir)
788
788
  except (OSError, ValueError):
789
789
  return
790
790
  payload = {
@@ -208,7 +208,7 @@ def _active_attempt_files(feature_dir: Path, activity: str) -> list[str]:
208
208
  or not all(isinstance(path, str) for path in carried)
209
209
  ):
210
210
  raise StaleAttemptError(f"fiche de tentative {activity} invalide")
211
- snapshot = snapshot_worktree(project_root_for_feature(feature_dir))
211
+ snapshot = snapshot_worktree(project_root_for_feature(feature_dir), feature_dir)
212
212
  if snapshot.head != payload["head"] or snapshot.branch != payload["branch"]:
213
213
  raise StaleAttemptError(
214
214
  f"HEAD ou la branche a change depuis la tentative {activity}"
@@ -243,7 +243,7 @@ def _still_modified(feature_dir: Path, files: list[str]) -> list[str]:
243
243
  if not files:
244
244
  return []
245
245
  try:
246
- snapshot = snapshot_worktree(project_root_for_feature(feature_dir))
246
+ snapshot = snapshot_worktree(project_root_for_feature(feature_dir), feature_dir)
247
247
  except (OSError, ValueError):
248
248
  return files
249
249
  return [path for path in files if path in snapshot.files]
@@ -17,8 +17,19 @@ class WorktreeSnapshot:
17
17
  files: dict[str, str]
18
18
 
19
19
 
20
- def snapshot_worktree(project_root: Path) -> WorktreeSnapshot:
21
- """Capture HEAD, branche et contenu des fichiers modifies/non suivis."""
20
+ # Traces brutes d'agent ecrites par devflow ; ignorees par le .gitignore de la feature.
21
+ TRACE_SUFFIX = ".raw.txt"
22
+
23
+
24
+ def snapshot_worktree(
25
+ project_root: Path, feature_dir: Path | None = None
26
+ ) -> WorktreeSnapshot:
27
+ """Capture HEAD, branche et contenu des fichiers modifies/non suivis.
28
+
29
+ Avec ``feature_dir``, les fichiers ignores par git dans ce seul dossier
30
+ sont aussi captures, hors traces brutes : un projet qui ignore ``.specify``
31
+ doit tout de meme voir les artefacts de sa feature.
32
+ """
22
33
  head = _git_text(project_root, ["rev-parse", "--verify", "HEAD"], allow_failure=True)
23
34
  branch = _git_text(project_root, ["branch", "--show-current"], allow_failure=True)
24
35
  tracked = _git_paths(
@@ -30,7 +41,15 @@ def snapshot_worktree(project_root: Path) -> WorktreeSnapshot:
30
41
  project_root,
31
42
  ["ls-files", "--others", "--exclude-standard", "-z"],
32
43
  )
33
- paths = sorted(set(tracked) | set(untracked))
44
+ paths = set(tracked) | set(untracked)
45
+ subtree = _subtree(project_root, feature_dir)
46
+ if subtree is not None:
47
+ ignored = _git_paths(
48
+ project_root,
49
+ ["ls-files", "--others", "--ignored", "--exclude-standard", "-z", "--", subtree],
50
+ )
51
+ paths |= {path for path in ignored if not path.endswith(TRACE_SUFFIX)}
52
+ paths = sorted(paths)
34
53
  return WorktreeSnapshot(
35
54
  head=head,
36
55
  branch=branch,
@@ -64,6 +83,15 @@ def changed_paths(before: WorktreeSnapshot, after: WorktreeSnapshot) -> list[str
64
83
  return sorted(path for path in paths if before.files.get(path) != after.files.get(path))
65
84
 
66
85
 
86
+ def _subtree(project_root: Path, feature_dir: Path | None) -> str | None:
87
+ if feature_dir is None:
88
+ return None
89
+ try:
90
+ return feature_dir.resolve().relative_to(project_root.resolve()).as_posix()
91
+ except ValueError:
92
+ return None
93
+
94
+
67
95
  def _git_text(project_root: Path, args: list[str], *, allow_failure: bool = False) -> str:
68
96
  result = subprocess.run(
69
97
  ["git", *args],
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: devflow-cli
3
- Version: 6.1.0
3
+ Version: 6.1.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,10 +1,10 @@
1
- devflow_cli/__init__.py,sha256=V6VdLY92DeDOFcFZuXg6acBYhESo1FOcJ9dHirgqF4Y,1002
1
+ devflow_cli/__init__.py,sha256=VmCwbQc6bNPKKQvcsirS32ZlbjHbOt8DbCAfd3EcBfA,1002
2
2
  devflow_cli/cli.py,sha256=nst8kP2QneJZJg6K5bBf9uO8Nj9lYmoHrEhcxA7nsIM,2129
3
3
  devflow_cli/adapters/__init__.py,sha256=RkjHPU2Lp4hSVIq2iOmyTrv2zYU9NuiIF9wEMWzLdMI,377
4
4
  devflow_cli/adapters/agents.py,sha256=8_y70AIhmtuR8kyPN3Wpj0-i76k9wd_uaycVKTqC96g,26503
5
5
  devflow_cli/adapters/linear.py,sha256=MyqI2tHx7NNHY1KRfeYZ_Zjc-6_xhZPWD4oS-j7wnNY,2659
6
6
  devflow_cli/commands/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
7
- devflow_cli/commands/adaptive.py,sha256=K44vv2Sr2G25AXoDafWIMF1lrgC8sZQCH-SOYO52IxY,45771
7
+ devflow_cli/commands/adaptive.py,sha256=_CICxGw27XOSnXteudn75IriY12zz5jhcZoH__zNfns,45797
8
8
  devflow_cli/commands/assess.py,sha256=GrWGGZjvBAgHWzSlUdtS-IfYocacA6VYxWduDvBunzg,4395
9
9
  devflow_cli/commands/check.py,sha256=M_sbcH1L3FEa4DF9gm46LEADlJndRKlaEDoysIBHv8k,6668
10
10
  devflow_cli/commands/context.py,sha256=hwTitOHxIpJMx1X8R1jHHy9CpE4HVZpJKkyeOujxAio,6246
@@ -23,7 +23,7 @@ devflow_cli/commands/usage.py,sha256=ehH1AH5J-XfkebFx6qLBwpKN-MOoX2uUbq4LejBpNsk
23
23
  devflow_cli/commands/verify.py,sha256=sKmoHfA-PRWoDbgLC0nW2nvd89Zdktlkep0sxF7q3jQ,3968
24
24
  devflow_cli/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
25
25
  devflow_cli/core/activity_contracts.py,sha256=U9AknLNFIusjuh4MonY_8i3__uDeo_NF2z3zfGJynA8,42631
26
- devflow_cli/core/adaptive_runner.py,sha256=_JmnglYkqN3HhV7UZdfSkCiR_O141rHIoEl1XEuIOFw,33687
26
+ devflow_cli/core/adaptive_runner.py,sha256=o9HHPNZJyA9u_zui9pNZrzMkH_jzszbI-GMweoRjqB8,33713
27
27
  devflow_cli/core/adaptive_workflow.py,sha256=qsjkahK9yklf6LjyQn69PVl9v0AoX2YPQiG2_umpb_U,13065
28
28
  devflow_cli/core/agent_failure.py,sha256=iX4q249lAHeVdD_ZF1aObmU-FX6sjfYP9dfLSnWGAD0,3771
29
29
  devflow_cli/core/assessment.py,sha256=l5QRntLJyBx3MdN-kepmMAsruHdJsG4TDgSdgOSHkqU,10062
@@ -38,7 +38,7 @@ devflow_cli/core/manifest.py,sha256=964iYthqhzf3qQgxN4hZ33BvS2r7BKDZoKdiOWRybag,
38
38
  devflow_cli/core/omissions.py,sha256=-9dqaQLRIy-1t6it7gecKn_0KpqbEjPIT0ec86KvXCk,7449
39
39
  devflow_cli/core/operational.py,sha256=ZEWh6DKJfHYLpV9r3vZwaDFREQwlJF0wTtgB1VleXog,1204
40
40
  devflow_cli/core/redaction.py,sha256=o_1MDtCyvRLrk_dWlV6_7E6_mPVB1B5a0cCfTBj9j0Q,1973
41
- devflow_cli/core/remediation.py,sha256=D7spH-xO1KezSY3YVuAl4ZdFCKhXKGSYVWgnLHC4Dp4,13549
41
+ devflow_cli/core/remediation.py,sha256=FknpUBR9WGZkmeDf6F2HINKKm3rG4AB5C7NTgrPhPVc,13575
42
42
  devflow_cli/core/scanner.py,sha256=bcoC91Nc0Hw2P7aHpL-9ITxynLZhLTEKpOXo553a-18,4395
43
43
  devflow_cli/core/staleness.py,sha256=Bn4jN8r601Ifn0AU8BHZy-Z-5NLPjj_JTK-V0KU9TUM,5256
44
44
  devflow_cli/core/telemetry.py,sha256=emcYo6Qikc86TYKT5Mc_9-3Thkt3nztkPZrpTy9VlvA,6952
@@ -48,7 +48,7 @@ devflow_cli/core/validators.py,sha256=c2T6NAe80sPh2uS8gCQfyiCkLT3eBPLizCbDsE0PgN
48
48
  devflow_cli/core/verification.py,sha256=a2-pAnMQqBhGnV87LwhMc03zFRjDECB7sWYGxQu21lo,16879
49
49
  devflow_cli/core/waivers.py,sha256=w3bza1OicSxAViYU2hvbrylQTNVgmN7Rd9y2L6Wm2OE,11302
50
50
  devflow_cli/core/worklog.py,sha256=w_R_K-xI7gx9lYQhcjJbI_nBQqztMHsOPWj1tQCXjjA,12668
51
- devflow_cli/core/worktree_snapshot.py,sha256=8YDAQwJ1lBbChck2IQUM2iEAAMv27tHedtfELS10nnU,3701
51
+ devflow_cli/core/worktree_snapshot.py,sha256=5ycGW5sYSeoht-ofUqoNhrscZuhTJlynfObzisJal90,4669
52
52
  devflow_cli/schemas/activity-contract-v3.schema.json,sha256=_R6oKY2K3LxNCIATQunDM7e41J6w4Dg15TrN3B-NL0c,1977
53
53
  devflow_cli/schemas/activity-result-v1.schema.json,sha256=UybTDGJcPZ_CJoD0oAlgBWJOEsQTp06KRnogoa1pFFY,3140
54
54
  devflow_cli/schemas/assessment-v3.schema.json,sha256=aCybk-TaE5aJDKA2dhadSq58a-t2hFy6A-hCDlIl2Yo,1798
@@ -85,8 +85,8 @@ devflow_cli/resources/templates/contracts/api-template.md,sha256=rC5v7JBz71PznCn
85
85
  devflow_cli/resources/templates/contracts/components-template.md,sha256=XIWfEXfC72sNmL5OA3V-7xIywkNDU2DBPLfyiagOWcs,484
86
86
  devflow_cli/resources/templates/contracts/interfaces-template.md,sha256=kf8B7b6HsmN7jyRlLNU7RnZl0rTMlI5s97yVRyI-6yc,336
87
87
  devflow_cli/resources/templates/contracts/services-template.md,sha256=cFafKCyLmq_a7aR7G0LXAaMO2z4Fuflq6iKdxfVg0vg,477
88
- devflow_cli-6.1.0.dist-info/METADATA,sha256=pyKyYa6gEGIGPOV9ubk6oEFDCisB1iDACGsJF9odu1Q,4061
89
- devflow_cli-6.1.0.dist-info/WHEEL,sha256=W3fkpkm7-wf9vBI5Z-7s0eWkeM-spu78I8Neb98DeEg,87
90
- devflow_cli-6.1.0.dist-info/entry_points.txt,sha256=GVJ6bMvFpqyO5589iC4nFKeGTpGIW8aKn_QPPpSZ6kU,48
91
- devflow_cli-6.1.0.dist-info/licenses/LICENSE,sha256=v79PvnmqOdKhQiOa_QcWxng4q8GuGscLOwi7ygUpwpo,1070
92
- devflow_cli-6.1.0.dist-info/RECORD,,
88
+ devflow_cli-6.1.1.dist-info/METADATA,sha256=KHMl28FYPV7eUHT9Hn6GH4VwneeUhK_H8Zb9NaD5Kqs,4061
89
+ devflow_cli-6.1.1.dist-info/WHEEL,sha256=W3fkpkm7-wf9vBI5Z-7s0eWkeM-spu78I8Neb98DeEg,87
90
+ devflow_cli-6.1.1.dist-info/entry_points.txt,sha256=GVJ6bMvFpqyO5589iC4nFKeGTpGIW8aKn_QPPpSZ6kU,48
91
+ devflow_cli-6.1.1.dist-info/licenses/LICENSE,sha256=v79PvnmqOdKhQiOa_QcWxng4q8GuGscLOwi7ygUpwpo,1070
92
+ devflow_cli-6.1.1.dist-info/RECORD,,