@guanlin4924/devflow-pi 0.1.102 → 0.1.104
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.
package/README.md
CHANGED
package/package.json
CHANGED
|
@@ -14,6 +14,14 @@ def sha256(path: Path) -> str:
|
|
|
14
14
|
return hashlib.sha256(path.read_bytes()).hexdigest()
|
|
15
15
|
|
|
16
16
|
|
|
17
|
+
def input_present(path):
|
|
18
|
+
"""A declared input without a trailing "/" may still be a rendered
|
|
19
|
+
directory (e.g. wireframes/screens); accept it when it holds a file."""
|
|
20
|
+
if path.is_file():
|
|
21
|
+
return True
|
|
22
|
+
return path.is_dir() and any(child.is_file() for child in path.rglob("*"))
|
|
23
|
+
|
|
24
|
+
|
|
17
25
|
def within(root: Path, relative: str) -> Path:
|
|
18
26
|
if not isinstance(relative, str) or not relative or Path(relative).is_absolute() or "\x00" in relative:
|
|
19
27
|
raise ValueError("invalid relative path")
|
|
@@ -166,8 +174,11 @@ def preflight(root: Path, feature: str, step: str, contract_path: str,
|
|
|
166
174
|
elif path.exists() or stage != "entry":
|
|
167
175
|
issues.append({"code": "MISSING_INPUT_FACT", "index": index, "path": relative})
|
|
168
176
|
elif producer == "existing":
|
|
169
|
-
if not path
|
|
177
|
+
if not input_present(path):
|
|
170
178
|
issues.append({"code": "MISSING_INPUT_FACT", "index": index, "path": relative})
|
|
179
|
+
elif path.is_dir():
|
|
180
|
+
# A rendered directory has no single-file fingerprint.
|
|
181
|
+
evidence.append({"kind": "input_collection", "path": relative})
|
|
171
182
|
elif obligation.get("sha256") is not None and obligation.get("sha256") != sha256(path):
|
|
172
183
|
issues.append({"code": "STALE_INPUT_FACT", "index": index, "path": relative})
|
|
173
184
|
else:
|
|
@@ -40,7 +40,13 @@ def read_handoff(root: Path, relative: str, evidence: list[dict], issues: list[d
|
|
|
40
40
|
except ValueError:
|
|
41
41
|
issues.append({"code": "PREVIOUS_OUTPUT_MISSING", "path": output_relative})
|
|
42
42
|
continue
|
|
43
|
-
if
|
|
43
|
+
if output_path.is_dir() and item.get("sha256") is None:
|
|
44
|
+
# Directory outputs (e.g. wireframes/screens) are recorded without a hash.
|
|
45
|
+
if review_preflight.input_present(output_path):
|
|
46
|
+
evidence.append({"kind": "previous_output_collection", "path": output_relative})
|
|
47
|
+
else:
|
|
48
|
+
issues.append({"code": "PREVIOUS_OUTPUT_MISSING", "path": output_relative})
|
|
49
|
+
elif not output_path.is_file():
|
|
44
50
|
issues.append({"code": "PREVIOUS_OUTPUT_MISSING", "path": output_relative})
|
|
45
51
|
elif item.get("sha256") != review_preflight.sha256(output_path):
|
|
46
52
|
issues.append({"code": "PREVIOUS_OUTPUT_CHANGED", "path": output_relative})
|
|
@@ -123,7 +129,7 @@ def startup_preflight(root: Path, feature: str, step: str,
|
|
|
123
129
|
collection = relative.endswith("/")
|
|
124
130
|
try:
|
|
125
131
|
target = review_preflight.within(root, rendered)
|
|
126
|
-
exists = target.is_dir() if collection else
|
|
132
|
+
exists = target.is_dir() if collection else review_preflight.input_present(target)
|
|
127
133
|
except ValueError:
|
|
128
134
|
exists = False
|
|
129
135
|
# Same rule as gate_runtime.rb: a collection input may be absent at entry.
|
package/src/constants.ts
CHANGED