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 +1 -1
- devflow_cli/commands/adaptive.py +16 -4
- devflow_cli/core/adaptive_runner.py +167 -48
- devflow_cli/core/contract_schemas.py +1 -0
- devflow_cli/core/validators.py +0 -9
- devflow_cli/schemas/reconcile-log-v3.schema.json +82 -0
- {devflow_cli-10.0.1.dist-info → devflow_cli-10.1.0.dist-info}/METADATA +1 -1
- {devflow_cli-10.0.1.dist-info → devflow_cli-10.1.0.dist-info}/RECORD +11 -10
- {devflow_cli-10.0.1.dist-info → devflow_cli-10.1.0.dist-info}/WHEEL +0 -0
- {devflow_cli-10.0.1.dist-info → devflow_cli-10.1.0.dist-info}/entry_points.txt +0 -0
- {devflow_cli-10.0.1.dist-info → devflow_cli-10.1.0.dist-info}/licenses/LICENSE +0 -0
devflow_cli/__init__.py
CHANGED
devflow_cli/commands/adaptive.py
CHANGED
|
@@ -367,7 +367,7 @@ def run_adaptive(
|
|
|
367
367
|
output_file,
|
|
368
368
|
permission_mode,
|
|
369
369
|
"workspace-write"
|
|
370
|
-
if "
|
|
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=
|
|
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
|
|
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
|
|
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
|
-
|
|
450
|
-
|
|
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
|
-
|
|
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
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
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
|
|
1049
|
-
RECONCILE_LOG_SCHEMA_VERSION =
|
|
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
|
|
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
|
-
|
|
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
|
|
1114
|
-
|
|
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
|
devflow_cli/core/validators.py
CHANGED
|
@@ -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,10 +1,10 @@
|
|
|
1
|
-
devflow_cli/__init__.py,sha256=
|
|
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=
|
|
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=
|
|
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=
|
|
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=
|
|
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.
|
|
59
|
-
devflow_cli-10.0.
|
|
60
|
-
devflow_cli-10.0.
|
|
61
|
-
devflow_cli-10.0.
|
|
62
|
-
devflow_cli-10.0.
|
|
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,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|