import sys
from typing import Dict, Set
from notion_client import Client
from tasks.utils import notion_utils
def _check_db_schema(db_props: Dict[str, Dict], required: Dict[str, str]) -> bool:
"""Return True if every required property exists with the correct type."""
for prop_name, expected_type in required.items():
if prop_name not in db_props:
print(
f"Error: Property '{prop_name}' missing from database.", file=sys.stderr
)
return False
actual_type = db_props[prop_name]["type"]
if actual_type != expected_type:
print(
f"Error: Property '{prop_name}' has type '{actual_type}', expected '{expected_type}'.",
file=sys.stderr,
)
return False
return True
def verify(notion: Client, main_id: str | None = None) -> bool: # noqa: C901
"""Programmatically verify the onboarding system described in description.md."""
DB_TITLE = "Employee Onboarding Checklist"
HUB_PAGE_TITLE = "Onboarding Hub"
DEPARTMENT_OPTIONS: Set[str] = {
"Product",
"Marketing",
"Sales",
"HR",
"Engineering",
}
REQUIRED_DB_PROPERTIES = {
"Employee Name": "title",
"Start Date": "date",
"Department": "select",
}
# 1. Locate onboarding database
db_id = notion_utils.find_database(notion, DB_TITLE)
if not db_id:
print(f"Error: Database '{DB_TITLE}' not found.", file=sys.stderr)
return False
try:
db_obj = notion.databases.retrieve(database_id=db_id)
except Exception as exc:
print(f"Error retrieving database: {exc}", file=sys.stderr)
return False
db_props = db_obj.get("properties", {})
if not _check_db_schema(db_props, REQUIRED_DB_PROPERTIES):
return False
# Extra: validate select options
dept_options = {opt["name"] for opt in db_props["Department"]["select"]["options"]}
if not DEPARTMENT_OPTIONS.issubset(dept_options):
print(
f"Error: Department select options must include {sorted(DEPARTMENT_OPTIONS)}. Current: {sorted(dept_options)}",
file=sys.stderr,
)
return False
# Check there are at least 3 entries in the database
try:
db_pages = notion.databases.query(database_id=db_id).get("results", [])
except Exception as exc:
print(f"Error querying database: {exc}", file=sys.stderr)
return False
if len(db_pages) < 3:
print(
"Error: Less than 3 onboarding entries found in the database.",
file=sys.stderr,
)
return False
# 2. Locate Onboarding Hub page
hub_page_id = notion_utils.find_page(notion, HUB_PAGE_TITLE)
if not hub_page_id:
print(f"Error: Page '{HUB_PAGE_TITLE}' not found.", file=sys.stderr)
return False
# 3. Ensure the onboarding database is embedded in the hub page
embedded_db_id = notion_utils.find_database_in_block(notion, hub_page_id, DB_TITLE)
if embedded_db_id != db_id:
print(
"Error: The Employee Onboarding Checklist database is not embedded in the Onboarding Hub page.",
file=sys.stderr,
)
return False
# 4. Analyse blocks within the hub page for linked mentions, timeline, and feedback form
all_blocks = notion_utils.get_all_blocks_recursively(notion, hub_page_id)
seen_link_targets: Set[str] = set()
numbered_list_count = 0
todo_count = 0
for blk in all_blocks:
blk_type = blk.get("type")
# Direct link-to-page blocks
if blk_type == "link_to_page":
info = blk.get("link_to_page", {})
target_id = info.get("page_id") or info.get("database_id")
if target_id:
seen_link_targets.add(target_id)
continue
# Rich-text mentions inside content blocks
if blk_type in {
"paragraph",
"numbered_list_item",
"bulleted_list_item",
"to_do",
}:
content = blk.get(blk_type, {})
for rt in content.get("rich_text", []):
if rt.get("type") == "mention":
mention = rt.get("mention", {})
if mention.get("type") in {"page", "database"}:
target_id = mention.get("page", {}).get("id") or mention.get(
"database", {}
).get("id")
if target_id:
seen_link_targets.add(target_id)
# Count numbered list items
if blk_type == "numbered_list_item":
numbered_list_count += 1
# Count to-do items in Feedback Form
if blk_type == "to_do":
todo_count += 1
if len(seen_link_targets) < 3:
print(
"Error: Fewer than 3 linked mentions to benefit policy pages found in the Benefits Overview section.",
file=sys.stderr,
)
return False
if numbered_list_count < 7:
print(
"Error: Numbered list contains fewer than 7 steps in the 30-Day Timeline section.",
file=sys.stderr,
)
return False
if todo_count < 3:
print(
"Error: Feedback Form section contains fewer than 3 to-do items.",
file=sys.stderr,
)
return False
print(
"Success: Verified Employee Onboarding Checklist database, Onboarding Hub page, and all required sections."
)
return True
def main():
notion = notion_utils.get_notion_client()
main_id = sys.argv[1] if len(sys.argv) > 1 else None
if verify(notion, main_id):
sys.exit(0)
else:
sys.exit(1)
if __name__ == "__main__":
main()