Skip to content

Commit 8fb88ad

Browse files
authored
Merge pull request #642 from Fr-e-d/contrib/sync-1785367832
sync: update 1 file(s) in core/
2 parents a0071dd + 1bbd006 commit 8fb88ad

1 file changed

Lines changed: 33 additions & 0 deletions

File tree

.gaai/core/hooks/pre-push.d/16-backlog-dep-integrity.sh

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,15 @@
1010
# or any done/*.yaml). Genuinely dangling: a typo, or an item deleted
1111
# instead of archived. Nothing can ever resolve it.
1212
#
13+
# ERROR — the document is not a mapping carrying `items:`. The daemon's shell
14+
# helpers query the backlog with `yq '.items[] | ...'`; a bare
15+
# top-level sequence makes every one of them fail. PyYAML is happy
16+
# either way, so a checker written in Python will not notice — which
17+
# is exactly how this shipped: a repair script rebuilt the file from
18+
# its rows and silently dropped the `cutover_state:` / `items:`
19+
# header, and the recovery scan went blind for hours while reporting
20+
# that it had nothing to evaluate.
21+
#
1322
# ERROR — a row whose `artefact` filename names a DIFFERENT row. Editing a
1423
# backlog by hand can displace a row's tail onto its neighbour: the
1524
# YAML stays valid, so nothing complains, while a row now carries
@@ -65,6 +74,17 @@ def load(path):
6574
return doc or []
6675
6776
77+
def top_level_shape(path):
78+
"""The shape the daemon's yq queries require, not the shape PyYAML tolerates."""
79+
with open(path, encoding="utf-8") as fh:
80+
doc = yaml.safe_load(fh)
81+
if not isinstance(doc, dict):
82+
return f"a top-level {type(doc).__name__}, not a mapping"
83+
if "items" not in doc:
84+
return "a mapping with no `items:` key"
85+
return None
86+
87+
6888
try:
6989
active = load(active_path)
7090
except Exception as exc:
@@ -126,6 +146,19 @@ for item in active:
126146
if item.get("status") in (None, ""):
127147
statusless.append(item["id"])
128148
149+
shape_problem = top_level_shape(active_path)
150+
if shape_problem:
151+
print("", file=sys.stderr)
152+
print(f"❌ pre-push: {os.path.basename(active_path)} is {shape_problem} — push aborted.",
153+
file=sys.stderr)
154+
print(" The daemon queries this file with `yq '.items[] | ...'`, which fails outright", file=sys.stderr)
155+
print(" on a bare sequence — every shell helper then returns empty, and the recovery", file=sys.stderr)
156+
print(" scan reports it has nothing to evaluate while stories sit stranded.", file=sys.stderr)
157+
print(" PyYAML accepts both shapes, so this survives any Python-side check.", file=sys.stderr)
158+
print(" Fix: restore the `cutover_state:` block and the `items:` key above the rows.", file=sys.stderr)
159+
print("", file=sys.stderr)
160+
sys.exit(1)
161+
129162
seen, duplicates = set(), set()
130163
for item in active:
131164
if not isinstance(item, dict) or not isinstance(item.get("id"), str):

0 commit comments

Comments
 (0)