devflow-cli 10.0.1__py3-none-any.whl → 10.1.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 = "10.0.1"
3
+ VERSION = "10.1.0"
4
4
 
5
5
  ACTIVITY_LINEAR_MAPPING = {
6
6
  "assess": "Backlog",
@@ -367,7 +367,7 @@ def run_adaptive(
367
367
  output_file,
368
368
  permission_mode,
369
369
  "workspace-write"
370
- if "write" in activity_contract.allowedActions
370
+ if "execute" in activity_contract.allowedActions
371
371
  else "read-only",
372
372
  )
373
373
  attempt["execution"] = execution
@@ -540,7 +540,10 @@ def reconcile_adaptive(
540
540
  reason: Optional[str] = typer.Option(
541
541
  None,
542
542
  "--reason",
543
- help="Motif obligatoire avec --result",
543
+ help=(
544
+ "Motif obligatoire avec --result ; seul, il consigne l'artefact corrige "
545
+ "d'une tentative refusee invalid-artifact"
546
+ ),
544
547
  ),
545
548
  ) -> None:
546
549
  """Valide sans relancer l'agent le travail d'une tentative agent echouee."""
@@ -561,8 +564,8 @@ def reconcile_adaptive(
561
564
  except (OSError, UnicodeDecodeError, json.JSONDecodeError, ValueError) as exc:
562
565
  fail(f"Resultat corrige invalide : {exc}")
563
566
  raise typer.Exit(int(ExitCode.USAGE)) from exc
564
- elif reason is not None:
565
- fail("--reason ne peut etre utilise qu'avec --result")
567
+ elif reason is not None and not reason.strip():
568
+ fail("--reason ne peut pas etre vide")
566
569
  raise typer.Exit(int(ExitCode.USAGE))
567
570
 
568
571
  missing_output: dict[str, str] = {}
@@ -1577,6 +1580,15 @@ def _print_run_recovery(
1577
1580
  f" devflow adaptive reconcile {issue_id} --result FICHIER.json --reason MOTIF"
1578
1581
  " # corriger la reponse refusee sans relancer l'agent"
1579
1582
  )
1583
+ if reason == "invalid-artifact" and activity in DOCUMENT_ARTIFACTS:
1584
+ console.print(
1585
+ " Corriger l'artefact refuse (aucun autre fichier), puis :"
1586
+ )
1587
+ console.print(
1588
+ f" devflow adaptive reconcile {issue_id} --reason MOTIF"
1589
+ " # consigner la correction sans relancer l'agent",
1590
+ markup=False, soft_wrap=True,
1591
+ )
1580
1592
  if reason == "agent-failed":
1581
1593
  console.print(f" devflow adaptive reconcile {issue_id} # si la trace contient une reponse finale")
1582
1594
  _print_check_command(" # verifier l'agent")
@@ -64,7 +64,10 @@ from devflow_cli.core.adaptive_workflow import (
64
64
  )
65
65
  from devflow_cli.adapters.agents import SUPPORTED_AGENT_NAMES
66
66
  from devflow_cli.core.assessment import read_assessment
67
- from devflow_cli.core.contract_schemas import ATTEMPT_SCHEMA_VERSION
67
+ from devflow_cli.core.contract_schemas import (
68
+ ATTEMPT_SCHEMA_VERSION,
69
+ validate_contract_payload,
70
+ )
68
71
  from devflow_cli.core.worklog import safe_refresh_worklog
69
72
  from devflow_cli.core.traceability import analyze_traceability
70
73
  from devflow_cli.core.validators import validate_artifact
@@ -407,6 +410,12 @@ def reconcile_current_activity(
407
410
  f"adaptive run {shlex.quote(state.issueId)}"
408
411
  )
409
412
  attempt_reason = attempt["reason"]
413
+ if (
414
+ corrected_payload is None
415
+ and correction_reason.strip()
416
+ and (attempt_reason != "invalid-artifact" or activity not in DOCUMENT_ARTIFACTS)
417
+ ):
418
+ raise ValueError(REASON_WITHOUT_RESULT_MESSAGE)
410
419
  observed_files = attempt["observedFiles"]
411
420
  execution_files = attempt["executionFiles"]
412
421
  imputed = imputed_inputs(
@@ -446,21 +455,47 @@ def reconcile_current_activity(
446
455
  raise ValueError("HEAD ou la branche a change depuis la tentative")
447
456
  # N6 : pour une activite documentaire, un fichier de la fiche autre que
448
457
  # l'artefact peut etre revenu a son etat de base (fichier en trop retire).
449
- artifact = (
450
- f"{feature_path}/{DOCUMENT_ARTIFACTS[activity]}"
458
+ artifact_name = (
459
+ document_artifact_name(activity, reopened=contract_is_reopened_plan(contract))
451
460
  if activity in DOCUMENT_ARTIFACTS
452
461
  else None
453
462
  )
463
+ artifact = f"{feature_path}/{artifact_name}" if artifact_name else None
454
464
  drifted = sorted(
455
465
  path
456
466
  for path in set(observed_files) | set(since_base)
457
467
  if observed_files.get(path) != since_base.get(path)
458
468
  and (artifact is None or path == artifact or path in since_base)
459
469
  )
460
- if drifted:
470
+ # D2 : l'artefact refuse (invalid-artifact) puis corrige a la main est la
471
+ # seule derive acceptee, sous --reason et si le validateur de run l'accepte.
472
+ artifact_correction = (
473
+ corrected_payload is None
474
+ and artifact is not None
475
+ and attempt_reason == "invalid-artifact"
476
+ and drifted == [artifact]
477
+ and since_base.get(artifact) is not None
478
+ and (feature_dir / artifact_name).is_file()
479
+ )
480
+ if artifact_correction:
481
+ if not correction_reason.strip():
482
+ raise ValueError(
483
+ "artefact corrige depuis la tentative : --reason est obligatoire "
484
+ "pour consigner la correction"
485
+ )
486
+ artifact_error = _artifact_validation_error(
487
+ feature_dir, activity, artifact_name
488
+ )
489
+ if artifact_error is not None:
490
+ return AdaptiveRunOutcome(
491
+ "invalid-artifact", activity, activity, artifact_error
492
+ )
493
+ elif drifted:
461
494
  raise ValueError(
462
495
  "fichiers modifies depuis la tentative : " + ", ".join(drifted)
463
496
  )
497
+ elif corrected_payload is None and correction_reason.strip():
498
+ raise ValueError(REASON_WITHOUT_RESULT_MESSAGE)
464
499
  raw_output = activity_raw_file(feature_dir, activity).read_text(encoding="utf-8")
465
500
  if _sha256(raw_output) != attempt["rawOutputSha256"]:
466
501
  raise ValueError("trace brute modifiee depuis la tentative")
@@ -477,6 +512,28 @@ def reconcile_current_activity(
477
512
  state,
478
513
  during_execution=[*observed_files, *execution_files],
479
514
  )
515
+ if artifact_correction:
516
+ if recovery_error:
517
+ return AdaptiveRunOutcome(
518
+ "invalid-result", activity, activity, recovery_error
519
+ )
520
+ result_error = _validation_error(
521
+ feature_dir, contract, recovered, sorted(observation.sinceBase)
522
+ )
523
+ if result_error is not None:
524
+ return AdaptiveRunOutcome(
525
+ "invalid-result", activity, activity, result_error
526
+ )
527
+ _record_artifact_correction(
528
+ feature_dir,
529
+ state.issueId,
530
+ contract,
531
+ artifact,
532
+ observed_files.get(artifact),
533
+ since_base[artifact],
534
+ correction_reason,
535
+ correction_author,
536
+ )
480
537
  if corrected_payload is not None:
481
538
  observed = sorted(observation.sinceBase)
482
539
  agent_payload = (
@@ -665,21 +722,11 @@ def _apply_activity_result(
665
722
  artifact_name = document_artifact_name(
666
723
  contract.activity, reopened=contract_is_reopened_plan(contract)
667
724
  )
668
- if artifact_name == "preflight-evidence.md":
669
- try:
670
- validate_preflight_evidence(feature_dir / artifact_name)
671
- except ValueError as exc:
672
- return refuse("invalid-artifact", str(exc))
673
- validation = None
674
- else:
675
- validation = validate_artifact(
676
- contract.activity, feature_dir / artifact_name
677
- )
678
- if validation is not None and not validation.valid:
679
- return refuse(
680
- "invalid-artifact",
681
- "; ".join(issue.message for issue in validation.issues),
682
- )
725
+ artifact_error = _artifact_validation_error(
726
+ feature_dir, contract.activity, artifact_name
727
+ )
728
+ if artifact_error is not None:
729
+ return refuse("invalid-artifact", artifact_error)
683
730
  if contract.activity == "tasks":
684
731
  try:
685
732
  traceability = analyze_traceability(
@@ -846,6 +893,22 @@ def _validated_result(
846
893
  return result
847
894
 
848
895
 
896
+ def _artifact_validation_error(
897
+ feature_dir: Path, activity: str, artifact_name: str
898
+ ) -> str | None:
899
+ """Motif de refus d'un artefact documentaire, le meme pour run et reconcile."""
900
+ if artifact_name == "preflight-evidence.md":
901
+ try:
902
+ validate_preflight_evidence(feature_dir / artifact_name)
903
+ except ValueError as exc:
904
+ return str(exc)
905
+ return None
906
+ validation = validate_artifact(activity, feature_dir / artifact_name)
907
+ if validation.valid:
908
+ return None
909
+ return "; ".join(issue.message for issue in validation.issues)
910
+
911
+
849
912
  def _validation_error(
850
913
  feature_dir: Path,
851
914
  contract: ActivityContract,
@@ -1045,14 +1108,68 @@ def _sha256(content: str) -> str:
1045
1108
  return hashlib.sha256(content.encode("utf-8")).hexdigest()
1046
1109
 
1047
1110
 
1048
- # Schema 2 : entrees avec source, agentPayloadSha256 et changedFields (KKS-509).
1049
- RECONCILE_LOG_SCHEMA_VERSION = 2
1111
+ # Schema 3 : chaque entree porte kind ("result" ou "artifact", D3 de KKS-560).
1112
+ RECONCILE_LOG_SCHEMA_VERSION = 3
1050
1113
  RECONCILE_LOG_LEGACY_MESSAGE = (
1051
1114
  "reconcile-log.json est au schema 1 (devflow 8.0.0 ou anterieure) et n'est pas "
1052
1115
  "lu par cette version : terminer ce parcours avec devflow 8.0.0 "
1053
1116
  "(uv tool install devflow-cli==8.0.0), ou deplacer ce fichier dans attempts/ "
1054
1117
  "pour conserver son historique et commencer un nouveau journal"
1055
1118
  )
1119
+ RECONCILE_LOG_SCHEMA_2_MESSAGE = (
1120
+ "reconcile-log.json est au schema 2 (devflow 10.0.2 ou anterieure) et n'est pas "
1121
+ "lu par cette version : terminer ce parcours avec devflow 10.0.2 "
1122
+ "(uv tool install devflow-cli==10.0.2), ou deplacer ce fichier dans attempts/ "
1123
+ "pour conserver son historique et commencer un nouveau journal"
1124
+ )
1125
+ REASON_WITHOUT_RESULT_MESSAGE = (
1126
+ "--reason ne peut etre utilise qu'avec --result, ou sans --result pour consigner "
1127
+ "l'artefact corrige d'une tentative refusee invalid-artifact"
1128
+ )
1129
+
1130
+
1131
+ def _load_reconcile_log(feature_dir: Path, issue_id: str) -> tuple[Path, dict]:
1132
+ """Charge le journal ou en cree un vide ; nomme l'invariant viole, sans ecrire."""
1133
+ path = feature_dir / "reconcile-log.json"
1134
+ if not path.is_file():
1135
+ return path, {
1136
+ "schemaVersion": RECONCILE_LOG_SCHEMA_VERSION,
1137
+ "issueId": issue_id,
1138
+ "entries": [],
1139
+ }
1140
+ log = json.loads(path.read_text(encoding="utf-8"))
1141
+ if isinstance(log, dict) and log.get("schemaVersion") == 1:
1142
+ raise ValueError(RECONCILE_LOG_LEGACY_MESSAGE)
1143
+ if isinstance(log, dict) and log.get("schemaVersion") == 2:
1144
+ raise ValueError(RECONCILE_LOG_SCHEMA_2_MESSAGE)
1145
+ if (
1146
+ not isinstance(log, dict)
1147
+ or log.get("schemaVersion") != RECONCILE_LOG_SCHEMA_VERSION
1148
+ or log.get("issueId") != issue_id
1149
+ or not isinstance(log.get("entries"), list)
1150
+ or not all(isinstance(entry, dict) for entry in log["entries"])
1151
+ ):
1152
+ raise ValueError("reconcile-log.json invalide")
1153
+ return path, log
1154
+
1155
+
1156
+ def _append_reconcile_entry(path: Path, log: dict, entry: dict) -> None:
1157
+ """Valide le journal complet contre son schema avant toute ecriture."""
1158
+ log["entries"].append(entry)
1159
+ validate_contract_payload("reconcile-log", log)
1160
+ _write_json_atomic(path, log)
1161
+
1162
+
1163
+ def _entry_header(log: dict, contract: ActivityContract, kind: str, reason: str, author: str) -> dict:
1164
+ return {
1165
+ "sequence": len(log["entries"]) + 1,
1166
+ "kind": kind,
1167
+ "contractId": contract.contractId,
1168
+ "activity": contract.activity,
1169
+ "recordedAt": datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ"),
1170
+ "author": author.strip() or os.environ.get("USER", "unknown"),
1171
+ "reason": reason.strip(),
1172
+ }
1056
1173
 
1057
1174
 
1058
1175
  def _record_manual_correction(
@@ -1070,33 +1187,10 @@ def _record_manual_correction(
1070
1187
  ``agentPayloadSha256`` et ``changedFields`` ne figurent que si la trace contenait
1071
1188
  une reponse de l'agent pour ce contrat (refusee par les validateurs, B1).
1072
1189
  """
1073
- path = feature_dir / "reconcile-log.json"
1074
- if path.is_file():
1075
- log = json.loads(path.read_text(encoding="utf-8"))
1076
- if isinstance(log, dict) and log.get("schemaVersion") == 1:
1077
- raise ValueError(RECONCILE_LOG_LEGACY_MESSAGE)
1078
- if (
1079
- not isinstance(log, dict)
1080
- or log.get("schemaVersion") != RECONCILE_LOG_SCHEMA_VERSION
1081
- or log.get("issueId") != issue_id
1082
- or not isinstance(log.get("entries"), list)
1083
- or not all(isinstance(entry, dict) for entry in log["entries"])
1084
- ):
1085
- raise ValueError("reconcile-log.json invalide")
1086
- else:
1087
- log = {
1088
- "schemaVersion": RECONCILE_LOG_SCHEMA_VERSION,
1089
- "issueId": issue_id,
1090
- "entries": [],
1091
- }
1190
+ path, log = _load_reconcile_log(feature_dir, issue_id)
1092
1191
  canonical = json.dumps(payload, sort_keys=True, ensure_ascii=False)
1093
1192
  entry = {
1094
- "sequence": len(log["entries"]) + 1,
1095
- "contractId": contract.contractId,
1096
- "activity": contract.activity,
1097
- "recordedAt": datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ"),
1098
- "author": author.strip() or os.environ.get("USER", "unknown"),
1099
- "reason": reason.strip(),
1193
+ **_entry_header(log, contract, "result", reason, author),
1100
1194
  "payloadSha256": _sha256(canonical),
1101
1195
  "payload": payload,
1102
1196
  "source": "manual-correction",
@@ -1110,8 +1204,33 @@ def _record_manual_correction(
1110
1204
  for key in set(agent_payload) | set(payload)
1111
1205
  if agent_payload.get(key, _MISSING) != payload.get(key, _MISSING)
1112
1206
  )
1113
- log["entries"].append(entry)
1114
- _write_json_atomic(path, log)
1207
+ _append_reconcile_entry(path, log, entry)
1208
+
1209
+
1210
+ def _record_artifact_correction(
1211
+ feature_dir: Path,
1212
+ issue_id: str,
1213
+ contract: ActivityContract,
1214
+ artifact: str,
1215
+ attempt_fingerprint: str | None,
1216
+ corrected_fingerprint: str,
1217
+ reason: str,
1218
+ author: str,
1219
+ ) -> None:
1220
+ """Consigne l'artefact corrige a la main apres un refus invalid-artifact (D2).
1221
+
1222
+ ``attemptFingerprint`` est l'empreinte de la fiche de tentative (None si l'artefact n'y
1223
+ figure pas), ``correctedFingerprint`` celle de l'artefact au moment de la reprise.
1224
+ """
1225
+ path, log = _load_reconcile_log(feature_dir, issue_id)
1226
+ entry = {
1227
+ **_entry_header(log, contract, "artifact", reason, author),
1228
+ "path": artifact,
1229
+ "attemptFingerprint": attempt_fingerprint,
1230
+ "correctedFingerprint": corrected_fingerprint,
1231
+ "source": "manual-correction",
1232
+ }
1233
+ _append_reconcile_entry(path, log, entry)
1115
1234
 
1116
1235
 
1117
1236
  _MISSING = object()
@@ -18,6 +18,7 @@ PUBLIC_CONTRACT_SCHEMAS = {
18
18
  "workflow-state": "workflow-state-v6.schema.json",
19
19
  "activity-contract": "activity-contract-v4.schema.json",
20
20
  "activity-result": "activity-result-v2.schema.json",
21
+ "reconcile-log": "reconcile-log-v3.schema.json",
21
22
  }
22
23
  # Fiche de tentative (<activite>-attempt.json) : seule definition (CT-04).
23
24
  ATTEMPT_SCHEMA_VERSION = 3
@@ -71,7 +71,6 @@ ARTIFACT_RULES: dict[str, dict] = {
71
71
  _PLACEHOLDER_BRACKET = re.compile(
72
72
  r"\[(?:TBD|TODO|XXX|[A-Z][A-Z\s]{3,})\](?!\()"
73
73
  )
74
- _PLACEHOLDER_MUSTACHE = re.compile(r"(?<!\$)\{\{[^}]+\}\}")
75
74
  _FENCE = re.compile(r"^ {0,3}(?P<marker>`{3,}|~{3,})")
76
75
  _INLINE_CODE = re.compile(r"(?P<ticks>`+)[^\r\n]*?(?P=ticks)")
77
76
 
@@ -169,14 +168,6 @@ def validate_artifact(step: str, artifact_path: Path) -> ValidationResult:
169
168
  f"{match.group()}"
170
169
  ),
171
170
  ))
172
- for match in _PLACEHOLDER_MUSTACHE.finditer(prose):
173
- issues.append(ValidationIssue(
174
- type="placeholder",
175
- message=(
176
- f"Placeholder non-remplace ligne {_line_number(prose, match.start())}: "
177
- f"{match.group()}"
178
- ),
179
- ))
180
171
 
181
172
  return ValidationResult(valid=len(issues) == 0, issues=issues)
182
173
 
@@ -0,0 +1,82 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://devflow.dev/schemas/reconcile-log/v3",
4
+ "title": "Devflow Reconcile Log v3",
5
+ "type": "object",
6
+ "required": ["schemaVersion", "issueId", "entries"],
7
+ "properties": {
8
+ "schemaVersion": {"type": "integer", "const": 3},
9
+ "issueId": {"type": "string", "minLength": 1},
10
+ "entries": {
11
+ "type": "array",
12
+ "items": {
13
+ "oneOf": [
14
+ {
15
+ "type": "object",
16
+ "required": [
17
+ "sequence",
18
+ "kind",
19
+ "contractId",
20
+ "activity",
21
+ "recordedAt",
22
+ "author",
23
+ "reason",
24
+ "payloadSha256",
25
+ "payload",
26
+ "source"
27
+ ],
28
+ "properties": {
29
+ "sequence": {"type": "integer", "minimum": 1},
30
+ "kind": {"type": "string", "const": "result"},
31
+ "contractId": {"type": "string", "minLength": 1},
32
+ "activity": {"type": "string", "minLength": 1},
33
+ "recordedAt": {"type": "string", "minLength": 1},
34
+ "author": {"type": "string"},
35
+ "reason": {"type": "string", "minLength": 1},
36
+ "payloadSha256": {"type": "string", "pattern": "^[0-9a-f]{64}$"},
37
+ "payload": {"type": "object"},
38
+ "source": {"type": "string", "const": "manual-correction"},
39
+ "agentPayloadSha256": {"type": "string", "pattern": "^[0-9a-f]{64}$"},
40
+ "changedFields": {
41
+ "type": "array",
42
+ "items": {"type": "string"}
43
+ }
44
+ },
45
+ "additionalProperties": false
46
+ },
47
+ {
48
+ "type": "object",
49
+ "required": [
50
+ "sequence",
51
+ "kind",
52
+ "contractId",
53
+ "activity",
54
+ "recordedAt",
55
+ "author",
56
+ "reason",
57
+ "path",
58
+ "attemptFingerprint",
59
+ "correctedFingerprint",
60
+ "source"
61
+ ],
62
+ "properties": {
63
+ "sequence": {"type": "integer", "minimum": 1},
64
+ "kind": {"type": "string", "const": "artifact"},
65
+ "contractId": {"type": "string", "minLength": 1},
66
+ "activity": {"type": "string", "minLength": 1},
67
+ "recordedAt": {"type": "string", "minLength": 1},
68
+ "author": {"type": "string"},
69
+ "reason": {"type": "string", "minLength": 1},
70
+ "path": {"type": "string", "minLength": 1},
71
+ "attemptFingerprint": {"type": ["string", "null"]},
72
+ "correctedFingerprint": {"type": "string", "minLength": 1},
73
+ "source": {"type": "string", "const": "manual-correction"}
74
+ },
75
+ "additionalProperties": false
76
+ }
77
+ ]
78
+ }
79
+ }
80
+ },
81
+ "additionalProperties": false
82
+ }
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: devflow-cli
3
- Version: 10.0.1
3
+ Version: 10.1.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
@@ -1,10 +1,10 @@
1
- devflow_cli/__init__.py,sha256=02pug78rvWnHvVFUZ4RtgU8ai09l4ofQA94OiCUg-RI,871
1
+ devflow_cli/__init__.py,sha256=lZsIKCNGd77qBp7LlFtTmNgqB5liD5Yu1cvqa1NxfYg,871
2
2
  devflow_cli/cli.py,sha256=DVLx3wr1Hulke2qxhgHsEvvprRuO7SVETui_VGPNQv4,1983
3
3
  devflow_cli/adapters/__init__.py,sha256=z1J7_YJHcgak2a6dTZpOUKKwf-K7UwRqGzS8XY9duC0,299
4
4
  devflow_cli/adapters/agents.py,sha256=-9zmNlFmQfP2pOGxA3_SSKij8ScR76J4-sgv4GMBWEI,18530
5
5
  devflow_cli/adapters/linear.py,sha256=xHKjMuL3fFJEDBF65pPJ-yWHpXom999UAU2A0C7_QeI,8362
6
6
  devflow_cli/commands/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
7
- devflow_cli/commands/adaptive.py,sha256=sHRLFTOtRsMEQscm1InalbIBOBk9MSJYEwwo32wZsU4,62775
7
+ devflow_cli/commands/adaptive.py,sha256=jogZ_NE0EnuGOzU-w42HM7IxUiF2AYARZWS40HKMkLU,63295
8
8
  devflow_cli/commands/assess.py,sha256=V-E3ft41ljCrqp2WLjR1Dqw-JtswcqsK2nD1-euNbNE,5655
9
9
  devflow_cli/commands/check.py,sha256=nJOHVFvgT3Nq70g-4QGrSDZVwCSetu6g7snZcfLFf9I,4421
10
10
  devflow_cli/commands/docs_sync.py,sha256=Xc0mulpNTjDyeUDumKL7VNG0eumAf3016wEM_dqXpSU,1021
@@ -16,13 +16,13 @@ devflow_cli/commands/upgrade_cmd.py,sha256=7GYe1T7SWzkDSYW9x1G-Dznw9qwKT2uI1gJUc
16
16
  devflow_cli/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
17
17
  devflow_cli/core/activity_base.py,sha256=eEC_YIr5O7WhCglA7xAEPypVzhcdC6f2h9d-SDDecVA,20475
18
18
  devflow_cli/core/activity_contracts.py,sha256=Sxu7b6lBQNNrtid0D3b9az8zPI8W4UHVgTQsNc0Y2uI,40328
19
- devflow_cli/core/adaptive_runner.py,sha256=Znc53MmtFC2iWLR-6IjwVFtViKyY7J6oWJn_HRp2Xk0,44686
19
+ devflow_cli/core/adaptive_runner.py,sha256=AkXtcE-lOjxDnabKdxvv5knx9giZXvvhzuv9LKLS7Mc,49727
20
20
  devflow_cli/core/adaptive_workflow.py,sha256=DU8iciNOeEDco5uwQUeX9E9Kc2WwaVPoRfWxdpRJyJ4,14416
21
21
  devflow_cli/core/agent_failure.py,sha256=iX4q249lAHeVdD_ZF1aObmU-FX6sjfYP9dfLSnWGAD0,3771
22
22
  devflow_cli/core/agent_run_marker.py,sha256=QW3ScA2ZpqfQdUo5ANTbenDVyY2iHpB_wTaN6VUKlzc,3451
23
23
  devflow_cli/core/assessment.py,sha256=ACtJbXq1qZjVfeERjy8Qg6-ioLfSMUBVQm2l-mtGwgI,11522
24
24
  devflow_cli/core/automatic_evidence.py,sha256=pqSnNXe6RHthII6fgoHlCNkGiFTKQ4yyRtErGUwbvas,42559
25
- devflow_cli/core/contract_schemas.py,sha256=JXI8PVgjdagTlFxnyuIkNRRrVi319Mv8GwuMxopJ_GI,8424
25
+ devflow_cli/core/contract_schemas.py,sha256=M0Twbt_SVVfuPa7udC-EJuR3pTl9pWrxQUCohIsg1h0,8477
26
26
  devflow_cli/core/docgen.py,sha256=47JoVDWetkcctgHwJZC67AVebOKgl10VB9hZ3Xr63mo,3908
27
27
  devflow_cli/core/feedback.py,sha256=07asmhX1cG4SXkoLlnSjA_UXgYnkFYoxl4u3JmOhpm0,13382
28
28
  devflow_cli/core/git.py,sha256=SsHL0OeJ8Bzc5cJC0moeBuyuwnvrJjtwnaI58TnzUSU,2536
@@ -38,7 +38,7 @@ devflow_cli/core/staleness.py,sha256=0JH_i1b8dYJmjDmQZuVToPnLOoNCN8ZZFgiSNrrBWOY
38
38
  devflow_cli/core/telemetry.py,sha256=FVR4iU9ywXIPo_5wrqWufpsp3GmHVLYiWaReaZ_DebM,2760
39
39
  devflow_cli/core/traceability.py,sha256=jfNE9MZzGkmaPer9Wa6Y18yA9Y3sqdeR-nzH9h_TB-8,2968
40
40
  devflow_cli/core/validation_approvals.py,sha256=3AHOpnW3BtY3BQrRZr38K7VNYRvbxGNhmQRYAufyhSA,9279
41
- devflow_cli/core/validators.py,sha256=fREjEx2fBW36q3vB6WJNqoGUM9ejYlQUXie5A9lNuPs,7440
41
+ devflow_cli/core/validators.py,sha256=HKGG1-td5T8cFx3rbE0iWPtddolk73qsqYreVWVT07g,7081
42
42
  devflow_cli/core/verification.py,sha256=3_iGhsXNFCs5cpBUyBCRTsmRsfuBAVa38lRgy-LXXww,20349
43
43
  devflow_cli/core/waivers.py,sha256=0w38Osjr69mDT6Lsn0ljkaq6bbggVejuhqiOnYHabs4,5586
44
44
  devflow_cli/core/worklog.py,sha256=NedQaNrydudJ_uN3bCyo7n3plAcU1-4bYcK3WbLnu9E,15834
@@ -46,6 +46,7 @@ devflow_cli/core/worktree_snapshot.py,sha256=Q2_KTkhJTGvdM6Ay4RK9OHkyPEMrHQRTb-f
46
46
  devflow_cli/schemas/activity-contract-v4.schema.json,sha256=IeduWDiJ5IV6EL7FDZWnHBjzyUt1uwig2rB-SMbcpOU,2006
47
47
  devflow_cli/schemas/activity-result-v2.schema.json,sha256=2yDf6S--mlNWMxE8h8ruwTsM3Tnaa96SJDjluc4ePbI,2772
48
48
  devflow_cli/schemas/assessment-v4.schema.json,sha256=byFBaoG_Vu-qS7vERREKThtpQa3dzNtPiFCMyEpWFVQ,2254
49
+ devflow_cli/schemas/reconcile-log-v3.schema.json,sha256=TNxw6xnv3dcwdUDqi0-SAlQnYg3_zDnCxkU6jwTfZRA,2926
49
50
  devflow_cli/schemas/workflow-state-v6.schema.json,sha256=fYyJS-6Aq-Ea7y2bVqJYSmKzdF2DvL3Nb6IdDNgFGfY,3239
50
51
  devflow_cli/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
51
52
  devflow_cli/utils/console.py,sha256=t7cpyeEluWj4v_O_KFSI59iqXK4GiSXPuxlsr8q5zoQ,771
@@ -55,8 +56,8 @@ devflow_cli/utils/strings.py,sha256=bfFXCwBDnFxshgZOYfy6mtysnjiaWO1wFnqBf7HLg4o,
55
56
  devflow_cli/resources/commands/devflow.md,sha256=R_8oExTiK2oE5-7YycePFbUeu3tpkyMpsvXVZHAegYM,2899
56
57
  devflow_cli/resources/commands/devflow.status.md,sha256=tqjQ1IboU99ztG6C4nunBHGJCvMn3qDqx3AoF4SPjCk,338
57
58
  devflow_cli/resources/templates/constitution-template.md,sha256=uSzNuwF-xIRx8cHt9gloynRjNgDGmnN5z2Xck6fCOsI,2102
58
- devflow_cli-10.0.1.dist-info/METADATA,sha256=8M7oFqF0O-qZjRgfM8WVdj3rEFhD920RBCLmYfKjHDk,10116
59
- devflow_cli-10.0.1.dist-info/WHEEL,sha256=W3fkpkm7-wf9vBI5Z-7s0eWkeM-spu78I8Neb98DeEg,87
60
- devflow_cli-10.0.1.dist-info/entry_points.txt,sha256=GVJ6bMvFpqyO5589iC4nFKeGTpGIW8aKn_QPPpSZ6kU,48
61
- devflow_cli-10.0.1.dist-info/licenses/LICENSE,sha256=v79PvnmqOdKhQiOa_QcWxng4q8GuGscLOwi7ygUpwpo,1070
62
- devflow_cli-10.0.1.dist-info/RECORD,,
59
+ devflow_cli-10.1.0.dist-info/METADATA,sha256=Jy6CrWnMaCHJZ_EcSIc42wP0VHJzcUBazJQCwhHx83k,10116
60
+ devflow_cli-10.1.0.dist-info/WHEEL,sha256=W3fkpkm7-wf9vBI5Z-7s0eWkeM-spu78I8Neb98DeEg,87
61
+ devflow_cli-10.1.0.dist-info/entry_points.txt,sha256=GVJ6bMvFpqyO5589iC4nFKeGTpGIW8aKn_QPPpSZ6kU,48
62
+ devflow_cli-10.1.0.dist-info/licenses/LICENSE,sha256=v79PvnmqOdKhQiOa_QcWxng4q8GuGscLOwi7ygUpwpo,1070
63
+ devflow_cli-10.1.0.dist-info/RECORD,,