[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6KG5EG56KG5SDHSVSWRB350":3,"skill-same:01M6KG5EG56KG5SDHSVSWRB350":72},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":23,"publishedAt":39,"linkOnly":40,"markdownContent":41,"markdownBody":42,"frontMatter":43,"refName":44,"commitSha":45,"skillDirectory":46,"forksCount":14,"repositoryHtmlUrl":47,"repositoryHomepageUrl":6,"ownerHtmlUrl":48,"ownerBlogUrl":49,"ownerDescription":50,"updatedAt":51,"install":52,"resources":65},"01M6KG5EG56KG5SDHSVSWRB350","spreadsheet-direct-verification",null,"Use a deterministic Python\u002Fopenpyxl inspection pass to verify workbook structure, counts, marked rows, and output-file existence when delegated spreadsheet summaries seem inconsistent.","xyliu-cs\u002FOpenSpace-GDPval","xyliu-cs","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F89236536?v=4","01M6KF8Z1V4TXS86CKSH48BY8T","xy","01M6KF8Z67443W0SHXM85JEF0B",0,"MIT","https:\u002F\u002Fgithub.com\u002Fxyliu-cs\u002FOpenSpace-GDPval\u002Fblob\u002Fmain\u002Fgdpval_bench\u002Fskills\u002Fspreadsheet-direct-verification\u002FSKILL.md",[18],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000004","电子表格","SCENARIO","使用场景",[24,25,26,27,28,29,30,31,32,33,34,35,36,37,38],"verification","spreadsheet","direct","spreadsheet direct verification","python","file","verify","use","deterministic","structure","output","workbook","openpyxl","marked","summaries","2026-11-10 10:12:30",false,"---\nname: spreadsheet-direct-verification\ndescription: Use a deterministic Python\u002Fopenpyxl inspection pass to verify workbook structure, counts, marked rows, and output-file existence when delegated spreadsheet summaries seem inconsistent.\n---\n\n# Spreadsheet Direct Verification\n\nUse this workflow when a higher-level or delegated agent has interacted with spreadsheet files, but its summaries or claims are inconsistent, incomplete, or hard to trust.\n\nThe goal is to replace uncertain narrative summaries with a direct, reproducible inspection from disk before you finalize your answer.\n\n## When to use this\n\nApply this skill when any of the following happen:\n\n- A delegated agent reports conflicting workbook facts across messages\n- Sheet names, row counts, headers, or output paths are inconsistent\n- The agent says a file was created or modified, but did not verify it from disk\n- The task depends on exact workbook contents, especially after edits\n- You need a trustworthy final summary of what actually exists on disk\n\n## Core principle\n\nWhen spreadsheet state matters, trust a deterministic script over a conversational summary.\n\nInspect the workbook directly with Python and `openpyxl`, and print a compact report covering:\n\n- workbook path\n- whether the file exists\n- sheet names\n- per-sheet headers\n- per-sheet row counts\n- totals for \"marked\" rows, if relevant to the task\n- whether expected output files exist\n\nUse the script output as the basis for your final response.\n\n## Workflow\n\n1. Identify the workbook(s) and expected output file(s).\n2. Determine what \"marked row\" means for the task.\n   - Examples:\n     - rows with a non-empty marker column\n     - rows with `x`, `yes`, `true`, or `1`\n     - rows highlighted by a prior workflow that also wrote a marker column\n3. Run a direct Python inspection on the files from disk.\n4. Compare the script output against any delegated summary.\n5. If they differ, treat the script as authoritative.\n6. Only then provide the final user-facing summary.\n\n## Minimum verification checklist\n\nBefore finalizing, verify and record:\n\n- exact input workbook path inspected\n  - exact output workbook path inspected\n  - whether each file exists\n  - all sheet names in each workbook\n  - header row for each relevant sheet\n  - number of non-empty data rows per sheet\n  - number of marked rows per sheet, if applicable\n  - whether modifications appear in the saved output file\n\n## Production planning validation checklist\n\nFor manufacturing and production planning spreadsheets, extend the verification to include:\n\n1. **Max daily minutes per press**: Verify that no press exceeds the daily labor minute limit (e.g., 450 minutes per day per press).\n   - Sum labor minutes grouped by press and date\n   - Flag any press-date combinations exceeding the threshold\n\n2. **Max weekly hours per team member**: Verify that no team member exceeds weekly hour limits (e.g., 37.5 hours per week).\n   - Sum assigned hours grouped by team member and week\n   - Flag any team-member-week combinations exceeding the threshold\n\n3. **Required roles per press**: Verify that each press assignment includes all required roles (e.g., 1 operator + 1 water spider per press).\n   - Count distinct role assignments per press per shift or date\n   - Flag any press assignments missing required roles\n\n4. **Minimum changeover requirements per press**: Verify that required changeovers are scheduled (e.g., minimum 3 changeovers per press per week).\n   - Count changeover events grouped by press and time period\n   - Flag any press-period combinations below the minimum threshold\n\n### Example production planning verification script extension\n\nExtend the base inspection script with these production-specific checks:\n\n```python\n# Add to the INPUTS list if you have separate labor\u002Fassignment sheets\n# Extend MARKER_CANDIDATES for production-specific columns\nPRODUCTION_MARKER_CANDIDATES = MARKER_CANDIDATES | {\"press\", \"team_member\", \"role\", \"changeover\", \"date\", \"week\"}\n\n# Production constraint thresholds (adjust per task)\nMAX_DAILY_MINUTES_PER_PRESS = 450\nMAX_WEEKLY_HOURS_PER_MEMBER = 37.5\nREQUIRED_ROLES_PER_PRESS = {\"operator\", \"water_spider\"}  # or {\"Operator\", \"Water Spider\"}\nMIN_CHANGEOVERS_PER_PRESS_PER_WEEK = 3\n\ndef validate_production_constraints(ws, headers):\n    \"\"\"Return a dict of constraint violations found in the worksheet.\"\"\"\n    violations = {\n        \"daily_minutes_exceeded\": [],\n        \"weekly_hours_exceeded\": [],\n        \"missing_roles\": [],\n        \"insufficient_changeovers\": [],\n    }\n    \n    if not headers:\n        return violations\n    \n    normalized_headers = [normalize(h).lower() for h in headers]\n    \n    # Find column indices\n    press_idx = next((i for i, h in enumerate(normalized_headers) if \"press\" in h), None)\n    member_idx = next((i for i, h in enumerate(normalized_headers) if \"member\" in h or \"team\" in h), None)\n    role_idx = next((i for i, h in enumerate(normalized_headers) if \"role\" in h), None)\n    minutes_idx = next((i for i, h in enumerate(normalized_headers) if \"minute\" in h or \"labor\" in h), None)\n    date_idx = next((i for i, h in enumerate(normalized_headers) if \"date\" in h), None)\n    changeover_idx = next((i for i, h in enumerate(normalized_headers) if \"changeover\" in h), None)\n    \n    # Aggregate data\n    press_daily_minutes = {}  # (press, date) -> total minutes\n    member_weekly_hours = {}  # (member, week) -> total hours\n    press_roles = {}  # (press, date) -> set of roles\n    press_changeovers = {}  # (press, week) -> count\n    \n    for row in ws.iter_rows(min_row=2, values_only=True):\n        if not any(v is not None and str(v).strip() != \"\" for v in row):\n            continue\n        \n        press = normalize(row[press_idx]) if press_idx is not None and press_idx \u003C len(row) else None\n        member = normalize(row[member_idx]) if member_idx is not None and member_idx \u003C len(row) else None\n        role = normalize(row[role_idx]).lower() if role_idx is not None and role_idx \u003C len(row) else None\n        minutes = float(row[minutes_idx]) if minutes_idx is not None and minutes_idx \u003C len(row) and row[minutes_idx] else 0\n        date_val = row[date_idx] if date_idx is not None and date_idx \u003C len(row) else None\n        is_changeover = row[changeover_idx] if changeover_idx is not None and changeover_idx \u003C len(row) else None\n        \n        # Derive week from date if available\n        week = None\n        date_str = \"\"\n        if date_val:\n            try:\n                from datetime import datetime\n                if isinstance(date_val, datetime):\n                    week = date_val.isocalendar()[1]\n                date_str = str(date_val)\n            except:\n                date_str = str(date_val) if date_val else \"\"\n                week = None\n        else:\n            date_str = \"\"\n        \n        # Aggregate daily minutes per press\n        if press and minutes:\n            key = (press, date_str)\n            press_daily_minutes[key] = press_daily_minutes.get(key, 0) + minutes\n        \n        # Aggregate weekly hours per member (assume minutes -> hours)\n        if member and minutes and week:\n            key = (member, week)\n            member_weekly_hours[key] = member_weekly_hours.get(key, 0) + minutes \u002F 60\n        \n        # Track roles per press per date\n        if press and role and date_str:\n            key = (press, date_str)\n            if key not in press_roles:\n                press_roles[key] = set()\n            press_roles[key].add(role)\n        \n        # Count changeovers per press per week\n        if press and is_changeover and week:\n            if is_truthy(is_changeover) or str(is_changeover).lower() in {\"yes\", \"true\", \"1\", \"y\", \"x\"}:\n                key = (press, week)\n                press_changeovers[key] = press_changeovers.get(key, 0) + 1\n    \n    # Check violations\n    for (press, date), total in press_daily_minutes.items():\n        if total > MAX_DAILY_MINUTES_PER_PRESS:\n            violations[\"daily_minutes_exceeded\"].append(f\"{press} on {date}: {total} min\")\n    \n    for (member, week), total in member_weekly_hours.items():\n        if total > MAX_WEEKLY_HOURS_PER_MEMBER:\n            violations[\"weekly_hours_exceeded\"].append(f\"{member} week {week}: {total:.1f} hrs\")\n    \n    for (press, date), roles in press_roles.items():\n        missing = REQUIRED_ROLES_PER_PRESS - roles\n        if missing:\n            violations[\"missing_roles\"].append(f\"{press} on {date}: missing {missing}\")\n    \n    for (press, week), count in press_changeovers.items():\n        if count \u003C MIN_CHANGEOVERS_PER_PRESS_PER_WEEK:\n            violations[\"insufficient_changeovers\"].append(f\"{press} week {week}: {count} changeovers\")\n    \n    return violations\n```\n\nWhen validating production planning workbooks, run this extended script and report any constraint violations found.\n\n## Recommended approach\n\nUse a standalone Python script snippet instead of relying on ad hoc tool narration. This makes the inspection:\n\n- reproducible\n- easy to rerun\n- less prone to memory or interpretation errors\n- suitable for attaching exact findings to the final answer\n\n## Example inspection script\n\nAdapt this script to the task. It is intentionally simple and explicit.\n\n```python\nfrom pathlib import Path\nfrom openpyxl import load_workbook\n\nINPUTS = [\n    \"input.xlsx\",\n    \"output.xlsx\",\n]\n\nMARKER_CANDIDATES = {\"mark\", \"marked\", \"flag\", \"selected\", \"include\", \"status\"}\n\nTRUTHY = {\"x\", \"yes\", \"true\", \"1\", \"y\"}\n\ndef normalize(value):\n    if value is None:\n        return \"\"\n    return str(value).strip()\n\ndef is_truthy(value):\n    return normalize(value).lower() in TRUTHY\n\ndef first_nonempty_row(ws, max_scan=10):\n    for row in ws.iter_rows(min_row=1, max_row=min(ws.max_row, max_scan), values_only=True):\n        if any(v is not None and str(v).strip() != \"\" for v in row):\n            return list(row)\n    return []\n\ndef data_row_count(ws):\n    count = 0\n    for row in ws.iter_rows(min_row=2, values_only=True):\n        if any(v is not None and str(v).strip() != \"\" for v in row):\n            count += 1\n    return count\n\ndef marked_row_count(ws, headers):\n    if not headers:\n        return 0, None\n    normalized_headers = [normalize(h).lower() for h in headers]\n    marker_idx = None\n    for i, h in enumerate(normalized_headers):\n        if h in MARKER_CANDIDATES:\n            marker_idx = i\n            break\n    if marker_idx is None:\n        return 0, None\n\n    count = 0\n    for row in ws.iter_rows(min_row=2, values_only=True):\n        if not any(v is not None and str(v).strip() != \"\" for v in row):\n            continue\n        value = row[marker_idx] if marker_idx \u003C len(row) else None\n        if is_truthy(value):\n            count += 1\n    return count, headers[marker_idx]\n\nfor file_str in INPUTS:\n    path = Path(file_str)\n    print(f\"FILE: {path}\")\n    print(f\"EXISTS: {path.exists()}\")\n\n    if not path.exists():\n        print()\n        continue\n\n    wb = load_workbook(path, data_only=False)\n    print(f\"SHEETS: {wb.sheetnames}\")\n\n    for ws in wb.worksheets:\n        headers = first_nonempty_row(ws)\n        rows = data_row_count(ws)\n        marked_count, marker_name = marked_row_count(ws, headers)\n\n        print(f\"  SHEET: {ws.title}\")\n        print(f\"    HEADERS: {headers}\")\n        print(f\"    DATA_ROWS: {rows}\")\n        if marker_name is not None:\n            print(f\"    MARKER_COLUMN: {marker_name}\")\n            print(f\"    MARKED_ROWS: {marked_count}\")\n        else:\n            print(\"    MARKER_COLUMN: \u003Cnot found>\")\n    print()\n```\n\n## How to adapt the script safely\n\nAdjust only the task-specific parts:\n\n- `INPUTS`: the exact workbook paths to verify\n- `MARKER_CANDIDATES`: possible names of the marker column\n- `TRUTHY`: accepted values that count as marked\n- row counting logic, if headers do not start on row 1\n- any expected output file paths to confirm\n\nDo not weaken the script by replacing direct inspection with summary text from another agent.\n\n## If the workbook layout is unusual\n\nHandle these cases explicitly:\n\n### Header row is not row 1\n\nSearch the first few rows for the first non-empty row or the row containing expected header names.\n\n### Multiple tables in one sheet\n\nLimit verification to the relevant region and state that assumption.\n\n### Marked rows are based on formatting, not a marker column\n\nIf required, inspect formatting directly with `openpyxl`, but prefer a visible marker column whenever possible. If formatting-based logic is necessary, document exactly what you counted.\n\n### Formula-driven workbooks\n\nIf you need displayed values, consider `load_workbook(..., data_only=True)` in a separate pass. If you need formulas and saved values, inspect both modes and note which one you used.\n\n## Final response pattern\n\nAfter running the verification script, summarize findings using facts from the output only. Include:\n\n- file verified\n- sheets present\n- row counts\n- marked-row totals\n- output file existence\n- any discrepancy discovered between delegated claims and actual disk state\n\nExample final phrasing:\n\n- \"I verified the workbook directly from disk with `openpyxl`.\"\n- \"The output file exists at `...`.\"\n- \"The workbook contains sheets `...`.\"\n- \"Sheet `...` has `N` data rows and `M` marked rows.\"\n- \"A prior delegated summary was inconsistent, so I used the direct inspection results as authoritative.\"\n\n## Decision rule\n\nIf delegated spreadsheet summaries and direct inspection disagree:\n\n- trust the direct inspection\n- cite the discrepancy internally\n- base the final answer on the deterministic script output\n\n## Anti-patterns to avoid\n\nDo not:\n\n- finalize based only on a delegated agent's prose summary\n- assume a workbook was saved without checking file existence\n- quote row counts without reading the workbook from disk\n- report sheet names from memory when they can be enumerated directly\n- mix speculative statements with verified spreadsheet facts\n\n## Why this skill is reusable\n\nThis pattern applies broadly to spreadsheet tasks involving:\n\n- workbook edits\n- filtering or marking rows\n- creating output copies\n- validating agent-performed file changes\n- reconciling conflicting intermediate reports\n\nWhenever workbook facts are important and agent summaries are unreliable, a direct `openpyxl` verification pass is the safe fallback.\n","# Spreadsheet Direct Verification\n\nUse this workflow when a higher-level or delegated agent has interacted with spreadsheet files, but its summaries or claims are inconsistent, incomplete, or hard to trust.\n\nThe goal is to replace uncertain narrative summaries with a direct, reproducible inspection from disk before you finalize your answer.\n\n## When to use this\n\nApply this skill when any of the following happen:\n\n- A delegated agent reports conflicting workbook facts across messages\n- Sheet names, row counts, headers, or output paths are inconsistent\n- The agent says a file was created or modified, but did not verify it from disk\n- The task depends on exact workbook contents, especially after edits\n- You need a trustworthy final summary of what actually exists on disk\n\n## Core principle\n\nWhen spreadsheet state matters, trust a deterministic script over a conversational summary.\n\nInspect the workbook directly with Python and `openpyxl`, and print a compact report covering:\n\n- workbook path\n- whether the file exists\n- sheet names\n- per-sheet headers\n- per-sheet row counts\n- totals for \"marked\" rows, if relevant to the task\n- whether expected output files exist\n\nUse the script output as the basis for your final response.\n\n## Workflow\n\n1. Identify the workbook(s) and expected output file(s).\n2. Determine what \"marked row\" means for the task.\n   - Examples:\n     - rows with a non-empty marker column\n     - rows with `x`, `yes`, `true`, or `1`\n     - rows highlighted by a prior workflow that also wrote a marker column\n3. Run a direct Python inspection on the files from disk.\n4. Compare the script output against any delegated summary.\n5. If they differ, treat the script as authoritative.\n6. Only then provide the final user-facing summary.\n\n## Minimum verification checklist\n\nBefore finalizing, verify and record:\n\n- exact input workbook path inspected\n  - exact output workbook path inspected\n  - whether each file exists\n  - all sheet names in each workbook\n  - header row for each relevant sheet\n  - number of non-empty data rows per sheet\n  - number of marked rows per sheet, if applicable\n  - whether modifications appear in the saved output file\n\n## Production planning validation checklist\n\nFor manufacturing and production planning spreadsheets, extend the verification to include:\n\n1. **Max daily minutes per press**: Verify that no press exceeds the daily labor minute limit (e.g., 450 minutes per day per press).\n   - Sum labor minutes grouped by press and date\n   - Flag any press-date combinations exceeding the threshold\n\n2. **Max weekly hours per team member**: Verify that no team member exceeds weekly hour limits (e.g., 37.5 hours per week).\n   - Sum assigned hours grouped by team member and week\n   - Flag any team-member-week combinations exceeding the threshold\n\n3. **Required roles per press**: Verify that each press assignment includes all required roles (e.g., 1 operator + 1 water spider per press).\n   - Count distinct role assignments per press per shift or date\n   - Flag any press assignments missing required roles\n\n4. **Minimum changeover requirements per press**: Verify that required changeovers are scheduled (e.g., minimum 3 changeovers per press per week).\n   - Count changeover events grouped by press and time period\n   - Flag any press-period combinations below the minimum threshold\n\n### Example production planning verification script extension\n\nExtend the base inspection script with these production-specific checks:\n\n```python\n# Add to the INPUTS list if you have separate labor\u002Fassignment sheets\n# Extend MARKER_CANDIDATES for production-specific columns\nPRODUCTION_MARKER_CANDIDATES = MARKER_CANDIDATES | {\"press\", \"team_member\", \"role\", \"changeover\", \"date\", \"week\"}\n\n# Production constraint thresholds (adjust per task)\nMAX_DAILY_MINUTES_PER_PRESS = 450\nMAX_WEEKLY_HOURS_PER_MEMBER = 37.5\nREQUIRED_ROLES_PER_PRESS = {\"operator\", \"water_spider\"}  # or {\"Operator\", \"Water Spider\"}\nMIN_CHANGEOVERS_PER_PRESS_PER_WEEK = 3\n\ndef validate_production_constraints(ws, headers):\n    \"\"\"Return a dict of constraint violations found in the worksheet.\"\"\"\n    violations = {\n        \"daily_minutes_exceeded\": [],\n        \"weekly_hours_exceeded\": [],\n        \"missing_roles\": [],\n        \"insufficient_changeovers\": [],\n    }\n    \n    if not headers:\n        return violations\n    \n    normalized_headers = [normalize(h).lower() for h in headers]\n    \n    # Find column indices\n    press_idx = next((i for i, h in enumerate(normalized_headers) if \"press\" in h), None)\n    member_idx = next((i for i, h in enumerate(normalized_headers) if \"member\" in h or \"team\" in h), None)\n    role_idx = next((i for i, h in enumerate(normalized_headers) if \"role\" in h), None)\n    minutes_idx = next((i for i, h in enumerate(normalized_headers) if \"minute\" in h or \"labor\" in h), None)\n    date_idx = next((i for i, h in enumerate(normalized_headers) if \"date\" in h), None)\n    changeover_idx = next((i for i, h in enumerate(normalized_headers) if \"changeover\" in h), None)\n    \n    # Aggregate data\n    press_daily_minutes = {}  # (press, date) -> total minutes\n    member_weekly_hours = {}  # (member, week) -> total hours\n    press_roles = {}  # (press, date) -> set of roles\n    press_changeovers = {}  # (press, week) -> count\n    \n    for row in ws.iter_rows(min_row=2, values_only=True):\n        if not any(v is not None and str(v).strip() != \"\" for v in row):\n            continue\n        \n        press = normalize(row[press_idx]) if press_idx is not None and press_idx \u003C len(row) else None\n        member = normalize(row[member_idx]) if member_idx is not None and member_idx \u003C len(row) else None\n        role = normalize(row[role_idx]).lower() if role_idx is not None and role_idx \u003C len(row) else None\n        minutes = float(row[minutes_idx]) if minutes_idx is not None and minutes_idx \u003C len(row) and row[minutes_idx] else 0\n        date_val = row[date_idx] if date_idx is not None and date_idx \u003C len(row) else None\n        is_changeover = row[changeover_idx] if changeover_idx is not None and changeover_idx \u003C len(row) else None\n        \n        # Derive week from date if available\n        week = None\n        date_str = \"\"\n        if date_val:\n            try:\n                from datetime import datetime\n                if isinstance(date_val, datetime):\n                    week = date_val.isocalendar()[1]\n                date_str = str(date_val)\n            except:\n                date_str = str(date_val) if date_val else \"\"\n                week = None\n        else:\n            date_str = \"\"\n        \n        # Aggregate daily minutes per press\n        if press and minutes:\n            key = (press, date_str)\n            press_daily_minutes[key] = press_daily_minutes.get(key, 0) + minutes\n        \n        # Aggregate weekly hours per member (assume minutes -> hours)\n        if member and minutes and week:\n            key = (member, week)\n            member_weekly_hours[key] = member_weekly_hours.get(key, 0) + minutes \u002F 60\n        \n        # Track roles per press per date\n        if press and role and date_str:\n            key = (press, date_str)\n            if key not in press_roles:\n                press_roles[key] = set()\n            press_roles[key].add(role)\n        \n        # Count changeovers per press per week\n        if press and is_changeover and week:\n            if is_truthy(is_changeover) or str(is_changeover).lower() in {\"yes\", \"true\", \"1\", \"y\", \"x\"}:\n                key = (press, week)\n                press_changeovers[key] = press_changeovers.get(key, 0) + 1\n    \n    # Check violations\n    for (press, date), total in press_daily_minutes.items():\n        if total > MAX_DAILY_MINUTES_PER_PRESS:\n            violations[\"daily_minutes_exceeded\"].append(f\"{press} on {date}: {total} min\")\n    \n    for (member, week), total in member_weekly_hours.items():\n        if total > MAX_WEEKLY_HOURS_PER_MEMBER:\n            violations[\"weekly_hours_exceeded\"].append(f\"{member} week {week}: {total:.1f} hrs\")\n    \n    for (press, date), roles in press_roles.items():\n        missing = REQUIRED_ROLES_PER_PRESS - roles\n        if missing:\n            violations[\"missing_roles\"].append(f\"{press} on {date}: missing {missing}\")\n    \n    for (press, week), count in press_changeovers.items():\n        if count \u003C MIN_CHANGEOVERS_PER_PRESS_PER_WEEK:\n            violations[\"insufficient_changeovers\"].append(f\"{press} week {week}: {count} changeovers\")\n    \n    return violations\n```\n\nWhen validating production planning workbooks, run this extended script and report any constraint violations found.\n\n## Recommended approach\n\nUse a standalone Python script snippet instead of relying on ad hoc tool narration. This makes the inspection:\n\n- reproducible\n- easy to rerun\n- less prone to memory or interpretation errors\n- suitable for attaching exact findings to the final answer\n\n## Example inspection script\n\nAdapt this script to the task. It is intentionally simple and explicit.\n\n```python\nfrom pathlib import Path\nfrom openpyxl import load_workbook\n\nINPUTS = [\n    \"input.xlsx\",\n    \"output.xlsx\",\n]\n\nMARKER_CANDIDATES = {\"mark\", \"marked\", \"flag\", \"selected\", \"include\", \"status\"}\n\nTRUTHY = {\"x\", \"yes\", \"true\", \"1\", \"y\"}\n\ndef normalize(value):\n    if value is None:\n        return \"\"\n    return str(value).strip()\n\ndef is_truthy(value):\n    return normalize(value).lower() in TRUTHY\n\ndef first_nonempty_row(ws, max_scan=10):\n    for row in ws.iter_rows(min_row=1, max_row=min(ws.max_row, max_scan), values_only=True):\n        if any(v is not None and str(v).strip() != \"\" for v in row):\n            return list(row)\n    return []\n\ndef data_row_count(ws):\n    count = 0\n    for row in ws.iter_rows(min_row=2, values_only=True):\n        if any(v is not None and str(v).strip() != \"\" for v in row):\n            count += 1\n    return count\n\ndef marked_row_count(ws, headers):\n    if not headers:\n        return 0, None\n    normalized_headers = [normalize(h).lower() for h in headers]\n    marker_idx = None\n    for i, h in enumerate(normalized_headers):\n        if h in MARKER_CANDIDATES:\n            marker_idx = i\n            break\n    if marker_idx is None:\n        return 0, None\n\n    count = 0\n    for row in ws.iter_rows(min_row=2, values_only=True):\n        if not any(v is not None and str(v).strip() != \"\" for v in row):\n            continue\n        value = row[marker_idx] if marker_idx \u003C len(row) else None\n        if is_truthy(value):\n            count += 1\n    return count, headers[marker_idx]\n\nfor file_str in INPUTS:\n    path = Path(file_str)\n    print(f\"FILE: {path}\")\n    print(f\"EXISTS: {path.exists()}\")\n\n    if not path.exists():\n        print()\n        continue\n\n    wb = load_workbook(path, data_only=False)\n    print(f\"SHEETS: {wb.sheetnames}\")\n\n    for ws in wb.worksheets:\n        headers = first_nonempty_row(ws)\n        rows = data_row_count(ws)\n        marked_count, marker_name = marked_row_count(ws, headers)\n\n        print(f\"  SHEET: {ws.title}\")\n        print(f\"    HEADERS: {headers}\")\n        print(f\"    DATA_ROWS: {rows}\")\n        if marker_name is not None:\n            print(f\"    MARKER_COLUMN: {marker_name}\")\n            print(f\"    MARKED_ROWS: {marked_count}\")\n        else:\n            print(\"    MARKER_COLUMN: \u003Cnot found>\")\n    print()\n```\n\n## How to adapt the script safely\n\nAdjust only the task-specific parts:\n\n- `INPUTS`: the exact workbook paths to verify\n- `MARKER_CANDIDATES`: possible names of the marker column\n- `TRUTHY`: accepted values that count as marked\n- row counting logic, if headers do not start on row 1\n- any expected output file paths to confirm\n\nDo not weaken the script by replacing direct inspection with summary text from another agent.\n\n## If the workbook layout is unusual\n\nHandle these cases explicitly:\n\n### Header row is not row 1\n\nSearch the first few rows for the first non-empty row or the row containing expected header names.\n\n### Multiple tables in one sheet\n\nLimit verification to the relevant region and state that assumption.\n\n### Marked rows are based on formatting, not a marker column\n\nIf required, inspect formatting directly with `openpyxl`, but prefer a visible marker column whenever possible. If formatting-based logic is necessary, document exactly what you counted.\n\n### Formula-driven workbooks\n\nIf you need displayed values, consider `load_workbook(..., data_only=True)` in a separate pass. If you need formulas and saved values, inspect both modes and note which one you used.\n\n## Final response pattern\n\nAfter running the verification script, summarize findings using facts from the output only. Include:\n\n- file verified\n- sheets present\n- row counts\n- marked-row totals\n- output file existence\n- any discrepancy discovered between delegated claims and actual disk state\n\nExample final phrasing:\n\n- \"I verified the workbook directly from disk with `openpyxl`.\"\n- \"The output file exists at `...`.\"\n- \"The workbook contains sheets `...`.\"\n- \"Sheet `...` has `N` data rows and `M` marked rows.\"\n- \"A prior delegated summary was inconsistent, so I used the direct inspection results as authoritative.\"\n\n## Decision rule\n\nIf delegated spreadsheet summaries and direct inspection disagree:\n\n- trust the direct inspection\n- cite the discrepancy internally\n- base the final answer on the deterministic script output\n\n## Anti-patterns to avoid\n\nDo not:\n\n- finalize based only on a delegated agent's prose summary\n- assume a workbook was saved without checking file existence\n- quote row counts without reading the workbook from disk\n- report sheet names from memory when they can be enumerated directly\n- mix speculative statements with verified spreadsheet facts\n\n## Why this skill is reusable\n\nThis pattern applies broadly to spreadsheet tasks involving:\n\n- workbook edits\n- filtering or marking rows\n- creating output copies\n- validating agent-performed file changes\n- reconciling conflicting intermediate reports\n\nWhenever workbook facts are important and agent summaries are unreliable, a direct `openpyxl` verification pass is the safe fallback.\n",{"name":5,"description":7},"main","af1b40a42167d09c30b3a63000aa14ace4c1e229","gdpval_bench\u002Fskills\u002Fspreadsheet-direct-verification","https:\u002F\u002Fgithub.com\u002Fxyliu-cs\u002FOpenSpace-GDPval","https:\u002F\u002Fgithub.com\u002Fxyliu-cs","https:\u002F\u002Fxyliu-cs.github.io","PhD Student in CS, CUHK-Shenzhen.","2026-04-06 20:32:15",{"source":8,"skillName":5,"commands":53,"prompt":63,"zipAvailable":64},[54,57,60],{"tool":55,"command":56},"npx","npx skills add xyliu-cs\u002FOpenSpace-GDPval --skill spreadsheet-direct-verification",{"tool":58,"command":59},"bunx","bunx skills add xyliu-cs\u002FOpenSpace-GDPval --skill spreadsheet-direct-verification",{"tool":61,"command":62},"pnpm","pnpm dlx skills add xyliu-cs\u002FOpenSpace-GDPval --skill spreadsheet-direct-verification","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Fxyliu-cs\u002FOpenSpace-GDPval\u002Fblob\u002Fmain\u002Fgdpval_bench\u002Fskills\u002Fspreadsheet-direct-verification\u002FSKILL.md",true,[66],{"path":67,"resourceType":68,"resourceTypeDesc":69,"sizeBytes":70,"sourceHtmlUrl":71},".skill_id","OTHER","其他",45,"https:\u002F\u002Fgithub.com\u002Fxyliu-cs\u002FOpenSpace-GDPval\u002Fblob\u002Fmain\u002Fgdpval_bench\u002Fskills\u002Fspreadsheet-direct-verification\u002F.skill_id",[73,86,94,110,135,155],{"skillNo":74,"name":75,"nameZh":6,"description":76,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":77,"categories":78,"keywords":79,"publishedAt":39},"01M6KG8MF1S664SWBDENYRSCK8","zip-export-deliverable","Ensures codebase deliverables are properly exported as ZIP archives through a dedicated finalization step","https:\u002F\u002Fgithub.com\u002Fxyliu-cs\u002FOpenSpace-GDPval\u002Fblob\u002Fmain\u002Fgdpval_bench\u002Fskills\u002Fzip-export-deliverable\u002FSKILL.md",[],[80,81,82,83,84,85],"zip export deliverable","zip","export","deliverables","codebase","as",{"skillNo":87,"name":88,"nameZh":6,"description":89,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":90,"categories":91,"keywords":92,"publishedAt":39},"01M6KG8GAZWHHEK7VNJDW0ME21","zip-deliverable-finalization","Ensure codebase deliverables are properly packaged as ZIP exports in a dedicated final step","https:\u002F\u002Fgithub.com\u002Fxyliu-cs\u002FOpenSpace-GDPval\u002Fblob\u002Fmain\u002Fgdpval_bench\u002Fskills\u002Fzip-deliverable-finalization\u002FSKILL.md",[],[93,81,83,84,85],"zip deliverable finalization",{"skillNo":95,"name":96,"nameZh":6,"description":97,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":98,"categories":99,"keywords":100,"publishedAt":39},"01M6KG8CMQQ1PYMNTSRZ9VS1MD","zero-iteration-failure-analysis","Identify and handle agent failures with 0 iterations as pre-execution system issues","https:\u002F\u002Fgithub.com\u002Fxyliu-cs\u002FOpenSpace-GDPval\u002Fblob\u002Fmain\u002Fgdpval_bench\u002Fskills\u002Fzero-iteration-failure-analysis\u002FSKILL.md",[],[101,102,103,104,105,106,107,108,85,109],"failure analysis","ZeRO","analysis","iteration","zero iteration failure analysis","with","issues","execution","system",{"skillNo":111,"name":112,"nameZh":6,"description":113,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":114,"categories":115,"keywords":121,"publishedAt":39},"01M6KG86W3PA07FT9W58YHHERM","write-file-fallback-report","Generate professional documents using write_file when primary data sources fail, leveraging embedded domain knowledge instead of external retrieval","https:\u002F\u002Fgithub.com\u002Fxyliu-cs\u002FOpenSpace-GDPval\u002Fblob\u002Fmain\u002Fgdpval_bench\u002Fskills\u002Fwrite-file-fallback-report\u002FSKILL.md",[116],{"categoryNo":117,"categoryName":118,"taxonomyType":119,"taxonomyTypeDesc":120},"01JBSEEDCAT000000000000034","行政与办公人员","PROFESSION","适用职业",[122,123,29,124,125,126,127,128,129,130,131,132,133,134],"fallback","write","report","write file fallback report","domain","professional","sources","retrieval","generate","embedded","documents","data","knowledge",{"skillNo":136,"name":137,"nameZh":6,"description":138,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":139,"categories":140,"keywords":144,"publishedAt":39},"01M6KG82GAEY3GG77CMGCK1C2T","fallback-doc-with-delegation","Generate professional documents after tool failures using shell_agent for complex formats or write_file for simple text\u002Fmarkdown","https:\u002F\u002Fgithub.com\u002Fxyliu-cs\u002FOpenSpace-GDPval\u002Fblob\u002Fmain\u002Fgdpval_bench\u002Fskills\u002Fwrite-file-fallback-report-enhanced\u002FSKILL.md",[141],{"categoryNo":142,"categoryName":143,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000023","Skill与智能体开发",[145,106,122,146,147,148,132,130,29,149,150,151,123,152,127,153,154],"fallback doc with delegation","doc","delegation","shell","markdown","tool","text","simple","formats","for",{"skillNo":156,"name":157,"nameZh":6,"description":158,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":159,"categories":160,"keywords":162,"publishedAt":39},"01M6KG7WT7GX5NYCGEFHW22NV7","context-anchored-fallback-report","Generate documents with write_file when retrieval tools fail, with explicit guardrails against task context drift","https:\u002F\u002Fgithub.com\u002Fxyliu-cs\u002FOpenSpace-GDPval\u002Fblob\u002Fmain\u002Fgdpval_bench\u002Fskills\u002Fwrite-file-fallback-report-enhanced-4bc5c2\u002FSKILL.md",[161],{"categoryNo":117,"categoryName":118,"taxonomyType":119,"taxonomyTypeDesc":120},[122,124,163,164,130,29,165,166,123,167,168,129,106,169,132],"context","context anchored fallback report","Guardrails","Tools","task","drift","context drift"]