NEO-112: enforce objective id uniqueness per quest in CI
Move obj_ids_seen to quest scope so duplicate objective ids are rejected across steps, matching CT.M1 documentation and E7M1-04 HTTP projection expectations (Bugbot PR #151).pull/151/head
parent
50956bac11
commit
a4ed4abadb
|
|
@ -44,7 +44,7 @@ NEO-112 delivers the Epic 7 Slice 1 **content foundation**: three JSON Schemas (
|
||||||
|
|
||||||
- Nit: `quest-objective-def.schema.json` lists all kind-specific fields in `properties` plus `oneOf` branches, so schema validation may accept wrong-field-at-wrong-kind (e.g. `recipeId` on `encounter_complete`) if both are present — plan adopted this tradeoff; CI cross-ref gate still catches unknown ids.
|
- Nit: `quest-objective-def.schema.json` lists all kind-specific fields in `properties` plus `oneOf` branches, so schema validation may accept wrong-field-at-wrong-kind (e.g. `recipeId` on `encounter_complete`) if both are present — plan adopted this tradeoff; CI cross-ref gate still catches unknown ids.
|
||||||
|
|
||||||
- Nit: Duplicate step/objective ids are enforced **within** a quest only, not globally across quests — acceptable for prototype; E7M1-04 HTTP projection should namespace by quest id.
|
- ~~Nit: Duplicate step/objective ids are enforced **within** a quest only, not globally across quests — acceptable for prototype; E7M1-04 HTTP projection should namespace by quest id.~~ **Superseded (Bugbot):** objective duplicate check was incorrectly scoped per-step; fixed in `validate_content.py` to quest-level (step ids remain per-quest; objective ids now per-quest too). Cross-quest uniqueness still not enforced (acceptable for prototype).
|
||||||
|
|
||||||
- Nit: Branch bundles the full E7M1 backlog decomposition (~390 lines) with E7M1-01 implementation — large diff but intentional and documented.
|
- Nit: Branch bundles the full E7M1 backlog decomposition (~390 lines) with E7M1-01 implementation — large diff but intentional and documented.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -905,6 +905,7 @@ def _validate_quest_catalogs(
|
||||||
steps = row.get("steps")
|
steps = row.get("steps")
|
||||||
if isinstance(steps, list):
|
if isinstance(steps, list):
|
||||||
step_ids_seen: set[str] = set()
|
step_ids_seen: set[str] = set()
|
||||||
|
obj_ids_seen: set[str] = set()
|
||||||
for si, step in enumerate(steps):
|
for si, step in enumerate(steps):
|
||||||
if not isinstance(step, dict):
|
if not isinstance(step, dict):
|
||||||
continue
|
continue
|
||||||
|
|
@ -920,7 +921,6 @@ def _validate_quest_catalogs(
|
||||||
step_ids_seen.add(sid)
|
step_ids_seen.add(sid)
|
||||||
objectives = step.get("objectives")
|
objectives = step.get("objectives")
|
||||||
if isinstance(objectives, list):
|
if isinstance(objectives, list):
|
||||||
obj_ids_seen: set[str] = set()
|
|
||||||
for oi, obj in enumerate(objectives):
|
for oi, obj in enumerate(objectives):
|
||||||
if not isinstance(obj, dict):
|
if not isinstance(obj, dict):
|
||||||
continue
|
continue
|
||||||
|
|
@ -929,7 +929,7 @@ def _validate_quest_catalogs(
|
||||||
if oid in obj_ids_seen:
|
if oid in obj_ids_seen:
|
||||||
print(
|
print(
|
||||||
f"error: {rel} quests[{i}] steps[{si}] objectives[{oi}]: "
|
f"error: {rel} quests[{i}] steps[{si}] objectives[{oi}]: "
|
||||||
f"duplicate objective id {oid!r}",
|
f"duplicate objective id {oid!r} within quest",
|
||||||
file=sys.stderr,
|
file=sys.stderr,
|
||||||
)
|
)
|
||||||
errors += 1
|
errors += 1
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue