Courses Internships Relation
L3
NotionComputer Science Student Dashboard
Connect the Courses and Internship search databases with bidirectional relations and populate with sample data.
Created by Zijian Wu
2025-07-27
Database ManipulationCross Reference LinkingTemplate Population
Model Ranking
Click on the dots to view the trajectory of each task run
Model | Run Results | Pass@4 | Pass^4 | Avg Time | Avg Turns | Input Tokens | Output Tokens | Total Tokens |
---|---|---|---|---|---|---|---|---|
claude-4-1-opus | 0 /1 | - | - | 363.5s | 21.0 | 420,966 | 4,170 | 425,136 |
claude-4-sonnet | 0 /4 | 215.0s | 24.3 | 630,677 | 5,208 | 635,885 | ||
deepseek-chat | 0 /4 | 267.7s | 22.0 | 398,360 | 2,579 | 400,938 | ||
gemini-2-5-pro | 0 /4 | 60.7s | 2.0 | 8,971 | 3,183 | 12,154 | ||
gpt-5 | 0 /4 | 912.1s | 18.3 | 228,376 | 52,685 | 281,061 | ||
grok-4 | 0 /4 | 32.9s | - | - | - | - | ||
k2 | 0 /4 | 104.2s | 17.5 | 215,842 | 2,218 | 218,060 | ||
o3 | 0 /4 | 489.8s | 33.5 | 435,148 | 35,544 | 470,692 | ||
qwen-3-coder | 0 /4 | 175.5s | 30.0 | 462,319 | 3,136 | 465,455 |
Task State
Notion Workspace
This task is executed based on this Notion workspace
This workspace is cloned from notion official template marketplace.View Original Template
Instruction
Verify
Python
import sys
from notion_client import Client
from tasks.utils import notion_utils
# ---------------------------------------------------------------------------
# Constants -----------------------------------------------------------------
# ---------------------------------------------------------------------------
MAIN_PAGE_TITLE = "Computer Science Student Dashboard"
COURSES_DB_TITLE = "Courses"
INTERNSHIP_DB_TITLE = "Internship search"
COURSE_CODES = {"CS301", "CS302", "CS303"}
COURSE_RELATION_NAME = "Related Internships"
INTERNSHIP_RELATION_NAME = "Relevant Courses"
INTERNSHIP_COMPANIES = {"OpenAI", "Google"}
# ---------------------------------------------------------------------------
# Helper functions -----------------------------------------------------------
# ---------------------------------------------------------------------------
def _locate_main_page(notion: Client, main_id: str | None) -> str | None:
"""Return the page_id of the dashboard page or None if not found."""
page_id = None
if main_id:
found_id, obj_type = notion_utils.find_page_or_database_by_id(notion, main_id)
if found_id and obj_type == "page":
page_id = found_id
if not page_id:
page_id = notion_utils.find_page(notion, MAIN_PAGE_TITLE)
return page_id
def _locate_database(notion: Client, parent_page_id: str, db_title: str) -> str | None:
"""Recursively search for a child database by title and return its id."""
return notion_utils.find_database_in_block(notion, parent_page_id, db_title)
# ---------------------------------------------------------------------------
# Verification logic ---------------------------------------------------------
# ---------------------------------------------------------------------------
def verify(notion: Client, main_id: str | None = None) -> bool:
"""Verify completion of the Courses ↔ Internship relation task."""
# ------------------------------------------------------------------
# Locate main page and databases -----------------------------------
# ------------------------------------------------------------------
page_id = _locate_main_page(notion, main_id)
if not page_id:
print(f"Error: Page '{MAIN_PAGE_TITLE}' not found.", file=sys.stderr)
return False
courses_db_id = _locate_database(notion, page_id, COURSES_DB_TITLE)
internships_db_id = _locate_database(notion, page_id, INTERNSHIP_DB_TITLE)
if not courses_db_id:
print(f"Error: Database '{COURSES_DB_TITLE}' not found.", file=sys.stderr)
return False
if not internships_db_id:
print(f"Error: Database '{INTERNSHIP_DB_TITLE}' not found.", file=sys.stderr)
return False
# ------------------------------------------------------------------
# Validate relation properties -------------------------------------
# ------------------------------------------------------------------
courses_db_obj = notion.databases.retrieve(database_id=courses_db_id)
internships_db_obj = notion.databases.retrieve(database_id=internships_db_id)
courses_props = courses_db_obj.get("properties", {})
internships_props = internships_db_obj.get("properties", {})
# Courses → Internships relation
if COURSE_RELATION_NAME not in courses_props:
print(
f"Error: Property '{COURSE_RELATION_NAME}' missing in Courses database.",
file=sys.stderr,
)
return False
course_rel_prop = courses_props[COURSE_RELATION_NAME]
if (
course_rel_prop.get("type") != "relation"
or course_rel_prop["relation"].get("database_id") != internships_db_id
):
print(
"Error: Courses relation property is not configured correctly.",
file=sys.stderr,
)
return False
# Internships → Courses relation
if INTERNSHIP_RELATION_NAME not in internships_props:
print(
f"Error: Property '{INTERNSHIP_RELATION_NAME}' missing in Internship search database.",
file=sys.stderr,
)
return False
intern_rel_prop = internships_props[INTERNSHIP_RELATION_NAME]
if (
intern_rel_prop.get("type") != "relation"
or intern_rel_prop["relation"].get("database_id") != courses_db_id
):
print(
"Error: Internship relation property is not configured correctly.",
file=sys.stderr,
)
return False
# ------------------------------------------------------------------
# Validate course pages --------------------------------------------
# ------------------------------------------------------------------
course_pages = notion.databases.query(database_id=courses_db_id).get("results", [])
valid_course_count = 0
course_page_id_set = set()
internship_ids_seen: set[str] = set()
for page in course_pages:
props = page.get("properties", {})
code_rts = props.get("Code", {}).get("rich_text", [])
code_val = "".join(rt.get("plain_text", "") for rt in code_rts).strip()
if code_val not in COURSE_CODES:
continue # not one of the new course entries we care about
# Check required scalar props
title_rts = props.get("Name", {}).get("title", [])
name_ok = bool("".join(rt.get("plain_text", "") for rt in title_rts).strip())
credits_ok = props.get("Credit", {}).get("number") is not None
status_name = props.get("Status", {}).get("status", {}).get("name", "")
status_allowed = {"planned", "in progress", "completed"}
status_ok = status_name.lower() in status_allowed
# Relation must point to at least one internship
relations = props.get(COURSE_RELATION_NAME, {}).get("relation", [])
if not (name_ok and credits_ok and status_ok and relations):
print(
f"Error: Course '{code_val}' is missing required property values or relations, or wrong values.",
file=sys.stderr,
)
return False
# Collect IDs for further mutual check
course_page_id_set.add(page["id"])
internship_ids_seen.update(rel["id"] for rel in relations)
valid_course_count += 1
if valid_course_count != 3:
print(
f"Error: Expected exactly 3 new course pages with codes {COURSE_CODES}, found {valid_course_count}.",
file=sys.stderr,
)
return False
# ------------------------------------------------------------------
# Validate internship pages ----------------------------------------
# ------------------------------------------------------------------
internship_pages = notion.databases.query(database_id=internships_db_id).get(
"results", []
)
valid_intern_count = 0
internship_page_ids = set()
course_ids_seen_from_intern: set[str] = set()
for page in internship_pages:
props = page.get("properties", {})
company_rts = props.get("Company", {}).get("rich_text", [])
company = "".join(rt.get("plain_text", "") for rt in company_rts).strip()
if company not in INTERNSHIP_COMPANIES:
continue # not one of the two new internships
role_rts = props.get("Role", {}).get("title", [])
role_ok = bool("".join(rt.get("plain_text", "") for rt in role_rts).strip())
status_name = props.get("Status", {}).get("status", {}).get("name", "")
status_ok = status_name.lower() == "interested"
relations = props.get(INTERNSHIP_RELATION_NAME, {}).get("relation", [])
if not (role_ok and status_ok and relations):
print(
f"Error: Internship at '{company}' is missing required property values or relations, or wrong values.",
file=sys.stderr,
)
return False
internship_page_ids.add(page["id"])
course_ids_seen_from_intern.update(rel["id"] for rel in relations)
valid_intern_count += 1
if valid_intern_count != 2:
print(
f"Error: Expected exactly 2 new internship pages for companies {INTERNSHIP_COMPANIES}, found {valid_intern_count}.",
file=sys.stderr,
)
return False
# ------------------------------------------------------------------
# Mutual relation consistency --------------------------------------
# ------------------------------------------------------------------
# Each relation from courses should point to one of the two internships identified
if not internship_ids_seen.issubset(internship_page_ids):
print(
"Error: Some course relations point to pages outside the expected internships.",
file=sys.stderr,
)
return False
# Each relation from internships should point back to the three course pages identified
if not course_ids_seen_from_intern.issubset(course_page_id_set):
print(
"Error: Some internship relations point to pages outside the expected courses.",
file=sys.stderr,
)
return False
print(
"Success: Verified bidirectional relations, course and internship entries as required."
)
return True
# ---------------------------------------------------------------------------
# CLI entry-point -----------------------------------------------------------
# ---------------------------------------------------------------------------
def main() -> None:
notion = notion_utils.get_notion_client()
main_id = sys.argv[1] if len(sys.argv) > 1 else None
sys.exit(0 if verify(notion, main_id) else 1)
if __name__ == "__main__":
main()