Remove Osaka Itinerary
L3
NotionJapan Travel Planner
Remove the itinerary items in Osaka after 6 PM from Day 1 and Day 2 travel schedules.
Created by Xiangyan Liu
2025-07-27
Conditional FilteringAutomated Migration
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-sonnet | 4 /4 | 122.8s | 9.5 | 378,762 | 1,699 | 380,460 | ||
gpt-5 | 4 /4 | 141.3s | 4.5 | 135,161 | 5,347 | 140,509 | ||
k2 | 4 /4 | 75.5s | 7.3 | 174,954 | 736 | 175,690 | ||
qwen-3-coder | 4 /4 | 109.0s | 12.5 | 571,767 | 1,296 | 573,063 | ||
claude-4-1-opus | 1 /1 | - | - | 94.1s | 8.0 | 792,892 | 1,289 | 794,181 |
o3 | 1 /4 | 102.8s | 11.3 | 231,743 | 4,417 | 236,160 | ||
deepseek-chat | 0 /4 | 112.2s | 8.3 | 404,461 | 441 | 404,902 | ||
gemini-2-5-pro | 0 /4 | 38.6s | 2.5 | 17,435 | 1,671 | 19,106 | ||
grok-4 | 0 /4 | - | - | - | - | - |
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
def get_page_title(page_result):
"""Extract title from a page result"""
properties = page_result.get('properties', {})
name_property = properties.get('Name', {})
if name_property.get('type') == 'title':
title_array = name_property.get('title', [])
if title_array and len(title_array) > 0:
return title_array[0].get('plain_text', '')
return ''
def get_page_time(page_result):
"""Extract time from Notes field"""
properties = page_result.get('properties', {})
notes_property = properties.get('Notes', {})
if notes_property.get('type') == 'rich_text':
rich_text_array = notes_property.get('rich_text', [])
if rich_text_array and len(rich_text_array) > 0:
notes_text = rich_text_array[0].get('plain_text', '')
return notes_text.strip()
return ''
def get_page_group(page_result):
"""Extract group/location from page"""
properties = page_result.get('properties', {})
group_property = properties.get('Group', {})
if group_property.get('type') == 'select':
select = group_property.get('select')
if select:
return select.get('name', '')
return ''
def get_page_day(page_result):
"""Extract day from page"""
properties = page_result.get('properties', {})
day_property = properties.get('Day', {})
if day_property.get('type') == 'select':
select = day_property.get('select')
if select:
return select.get('name', '')
return ''
def parse_time_to_minutes(time_str):
"""Convert time string to minutes for comparison
Returns None if time cannot be parsed"""
if not time_str:
return None
# Clean the time string
time_str = time_str.strip().upper()
# Remove any text after the time (e.g., "7:30 PM\n" -> "7:30 PM")
time_str = time_str.split('\n')[0].strip()
# Extract time components
try:
if 'PM' in time_str:
time_part = time_str.replace('PM', '').strip()
if ':' in time_part:
hours, minutes = time_part.split(':')
hours = int(hours)
minutes = int(minutes)
else:
hours = int(time_part)
minutes = 0
# Convert PM hours (add 12 for PM times except 12 PM)
if hours != 12:
hours += 12
return hours * 60 + minutes
elif 'AM' in time_str:
time_part = time_str.replace('AM', '').strip()
if ':' in time_part:
hours, minutes = time_part.split(':')
hours = int(hours)
minutes = int(minutes)
else:
hours = int(time_part)
minutes = 0
# Handle 12 AM (midnight)
if hours == 12:
hours = 0
return hours * 60 + minutes
except:
return None
return None
def verify(notion: Client, main_id: str = None) -> bool:
"""
Verifies that all OSAKA events after 6PM have been removed from Day 1 and Day 2 in the Japan Travel Planner.
Expected items that should be deleted (all in OSAKA, after 6PM, on Day 1 or Day 2):
1. Rikuro's Namba Main Branch - 7 PM (Day 1)
2. Shin Sekai "New World" - 8 PM (Day 2)
3. Katsudon Chiyomatsu - 7:30 PM (Day 2)
4. Ebisubashi Bridge - 9 PM (Day 1)
Note: Kuromon Ichiba Market at 6 PM should NOT be deleted (it's at 6PM, not after)
Items after 6PM on other days (Day 3-8) should NOT be deleted
"""
# Step 1: Find the main Japan Travel Planner page
if main_id:
found_id, object_type = notion_utils.find_page_or_database_by_id(notion, main_id)
if not found_id or object_type != 'page':
print("Error: Japan Travel Planner page not found.", file=sys.stderr)
return False
else:
# Try to find the page by searching
found_id = notion_utils.find_page(notion, "Japan Travel Planner")
if not found_id:
print("Error: Japan Travel Planner page not found.", file=sys.stderr)
return False
print(f"Found Japan Travel Planner page: {found_id}")
# Step 2: Find the Travel Itinerary database
all_blocks = notion_utils.get_all_blocks_recursively(notion, found_id)
travel_itinerary_db_id = None
for block in all_blocks:
if block and block.get("type") == "child_database":
title = block.get("child_database", {}).get("title", "")
if "Travel Itinerary" in title:
travel_itinerary_db_id = block.get("id")
print(f"Found Travel Itinerary database: {travel_itinerary_db_id}")
break
if not travel_itinerary_db_id:
print("Error: Travel Itinerary database not found", file=sys.stderr)
return False
# Step 3: Query the database for OSAKA items on Day 1 and Day 2
try:
query_result = notion.databases.query(
database_id=travel_itinerary_db_id,
filter={
"and": [
{"property": "Group", "select": {"equals": "Osaka"}},
{"or": [
{"property": "Day", "select": {"equals": "Day 1"}},
{"property": "Day", "select": {"equals": "Day 2"}}
]}
]
}
)
except Exception as e:
print(f"Error querying Travel Itinerary database: {e}", file=sys.stderr)
return False
# Step 4: Check for items that should have been deleted
six_pm_minutes = 18 * 60 # 6 PM in minutes (18:00)
# Expected deleted items (4 specific items after 6 PM on Day 1 and Day 2)
expected_deleted = {
"Rikuro's Namba Main Branch": {"time": "7 PM", "day": "Day 1", "found": False},
"Shin Sekai \"New World\"": {"time": "8 PM", "day": "Day 2", "found": False},
"Katsudon Chiyomatsu": {"time": "7:30 PM", "day": "Day 2", "found": False},
"Ebisubashi Bridge": {"time": "9 PM", "day": "Day 1", "found": False}
}
# Items that should remain (at or before 6 PM)
expected_remaining = {
"Kuromon Ichiba Market": {"time": "6 PM", "found": False}
}
osaka_items_after_6pm = []
osaka_items_at_or_before_6pm = []
# Debug: Show total query results
print(f"Debug: Found {len(query_result.get('results', []))} total OSAKA items on Day 1 and Day 2")
# Process all OSAKA items on Day 1 and Day 2
for page in query_result.get('results', []):
page_title = get_page_title(page).strip()
page_time = get_page_time(page)
page_group = get_page_group(page)
page_day = get_page_day(page)
if page_group != "Osaka":
continue
# Parse time to check if after 6 PM
time_minutes = parse_time_to_minutes(page_time)
if time_minutes is not None and time_minutes > six_pm_minutes:
osaka_items_after_6pm.append({
"title": page_title,
"time": page_time,
"day": page_day,
"id": page.get('id')
})
# Check if this is one of the expected deleted items
for expected_title, expected_info in expected_deleted.items():
# Clean up the titles for comparison
clean_page_title = page_title.strip().lower()
clean_expected_title = expected_title.strip().lower()
# Check for "Rikuro's" or "Rikuro's" (different apostrophe types)
if "rikuro" in clean_page_title and "rikuro" in clean_expected_title:
title_match = True
elif clean_page_title == clean_expected_title:
title_match = True
elif clean_expected_title in clean_page_title or clean_page_title in clean_expected_title:
title_match = True
else:
title_match = False
if title_match and page_day == expected_info["day"]:
print(f"Debug: Found '{page_title}' on {page_day} at {page_time} - matches expected '{expected_title}'")
expected_deleted[expected_title]["found"] = True
elif time_minutes is not None and time_minutes <= six_pm_minutes:
osaka_items_at_or_before_6pm.append({
"title": page_title,
"time": page_time,
"day": page_day,
"id": page.get('id')
})
# Check if this is one of the expected remaining items
for expected_title in expected_remaining:
if expected_title.lower() in page_title.lower() or page_title.lower() in expected_title.lower():
expected_remaining[expected_title]["found"] = True
# Step 5: Verify results
print(f"\nVerification Summary:")
print(f"=" * 50)
all_passed = True
# Check that the 4 expected items after 6 PM have been deleted
print("\n4 Items that should be deleted (after 6 PM on Day 1 and Day 2):")
for item_name, item_info in expected_deleted.items():
if item_info["found"]:
# If found = True, it means the item still exists (was not deleted)
print(f"✗ {item_name} ({item_info['day']}, {item_info['time']}) - Still exists, should be deleted", file=sys.stderr)
all_passed = False
else:
# If found = False, it means the item was deleted correctly
print(f"✓ {item_name} ({item_info['day']}, {item_info['time']}) - Correctly deleted")
# Check that items at or before 6 PM remain
print("\nItems that should remain (at or before 6 PM on Day 1 and Day 2):")
for item_name, item_info in expected_remaining.items():
if item_info["found"]:
print(f"✓ {item_name} ({item_info['time']}) - Correctly retained")
else:
print(f"✗ {item_name} ({item_info['time']}) - Missing, should not be deleted", file=sys.stderr)
all_passed = False
# Report any items after 6 PM that still exist
if osaka_items_after_6pm:
print(f"\n✗ Found {len(osaka_items_after_6pm)} OSAKA item(s) after 6 PM on Day 1/Day 2:", file=sys.stderr)
for item in osaka_items_after_6pm:
print(f" - {item['title']} at {item['time']} ({item['day']})", file=sys.stderr)
else:
print(f"\n✓ No OSAKA items found after 6 PM on Day 1/Day 2 (all correctly deleted)")
# Report count summary
print(f"\nCount Summary:")
print(f"- OSAKA items after 6 PM on Day 1/Day 2 found: {len(osaka_items_after_6pm)} (should be 0)")
print(f"- OSAKA items at/before 6 PM on Day 1/Day 2 found: {len(osaka_items_at_or_before_6pm)}")
print(f"- Expected deletions verified: {sum(1 for item in expected_deleted.values() if not item['found'])}/4")
return all_passed
def main():
"""
Executes the verification process and exits with a status code.
"""
notion = notion_utils.get_notion_client()
main_id = sys.argv[1] if len(sys.argv) > 1 else None
if verify(notion, main_id):
print("\nVerification passed: All 4 required OSAKA events after 6 PM on Day 1 and Day 2 have been removed")
sys.exit(0)
else:
print("\nVerification failed: Some OSAKA events after 6 PM on Day 1/Day 2 still exist")
sys.exit(1)
if __name__ == "__main__":
main()