{"id":"0bd90beb-597b-4692-8b69-295ee63b8705","entityType":"agent","slug":"clawhub-jeromeex-ovitalmap-parcel-csv","name":"OvitalMap Parcel CSV","canonicalUrl":"https://www.xpersona.co/agent/clawhub-jeromeex-ovitalmap-parcel-csv","canonicalPath":"/agent/clawhub-jeromeex-ovitalmap-parcel-csv","generatedAt":"2026-10-11T10:50:23.842Z","source":"CLAWHUB","claimStatus":"UNCLAIMED","verificationTier":"NONE","summary":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-11T06:50:12.624Z","emptyReason":null},"description":"Convert parcel boundaries into OvitalMap-compatible CSV files, assign stable parcel codes, and maintain deduplicated country and master archives. Use for WGS84, DMS, or UTM coordinates supplied as text or images, including archive re-exports and coordinate corrections. Do not use it as cadastral or legal validation.","descriptionLabel":"Source description","evidenceSummary":"Capability contract not published. No trust telemetry is available yet. 1.1K downloads reported by the source. Last updated 10/11/2026.","installCommand":"clawhub skill install s17fqp1p7fy20kfj7hwd6ax4z1885ne8:ovitalmap-parcel-csv","sourceUrl":"https://clawhub.ai/jeromeex/ovitalmap-parcel-csv","homepage":"https://clawhub.ai/jeromeex/skills/ovitalmap-parcel-csv","primaryLinks":[{"label":"View on ClawHub","url":"https://clawhub.ai/jeromeex/ovitalmap-parcel-csv","kind":"source"},{"label":"Homepage","url":"https://clawhub.ai/jeromeex/skills/ovitalmap-parcel-csv","kind":"homepage"}],"safetyScore":84,"overallRank":62,"popularityScore":61,"trustScore":null,"claimedByName":null,"isOwner":false,"seoDescription":"OvitalMap Parcel CSV technical dossier on Xpersona with agent coverage, OPENCLEW support, and live trust metadata."},"coverage":{"evidence":{"source":"public-profile","verified":false,"confidence":"medium","updatedAt":"2026-10-11T06:50:12.624Z","emptyReason":null},"protocols":[{"protocol":"OPENCLEW","label":"OpenClaw","status":"self-declared","notes":"Declared in the public agent profile."}],"capabilities":[],"verifiedCount":0,"selfDeclaredCount":1,"capabilityMatrix":{"rows":[{"key":"OPENCLEW","type":"protocol","support":"unknown","confidenceSource":"profile","notes":"Listed on profile"}],"flattenedTokens":"protocol:OPENCLEW|unknown|profile"}},"adoption":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-11T06:50:12.624Z","emptyReason":null},"stars":null,"forks":null,"downloads":1130,"packageName":null,"latestVersion":"3.0.1","tractionLabel":"1.1K downloads"},"release":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-11T06:50:12.557Z","emptyReason":null},"lastUpdatedAt":"2026-10-11T06:50:12.624Z","lastCrawledAt":"2026-10-11T06:50:12.557Z","lastIndexedAt":null,"nextCrawlAt":"2026-10-12T06:50:12.557Z","lastVerifiedAt":null,"highlights":[{"version":"3.0.1","createdAt":"2026-09-04T13:06:00.108Z","changelog":"Prepared for portable public use: added runtime metadata and MIT-0 licensing, replaced hard-coded Chinese replies with language-neutral workflow messages, removed Chinese-specific provider heuristics and legacy interfaces, and retained validated OvitalMap CSV/archive safeguards.","fileCount":16,"zipByteSize":31290},{"version":"3.0.0","createdAt":"2026-07-23T10:57:55.353Z","changelog":"ovitalmap-parcel-csv v2.1.2 - Major workflow revision: all data extraction, conversion, code assignment, and archiving now flow through explicit Python scripts using JSON input/output, prohibiting any in-conversation \"LLM reasoning\" for these tasks. - New scripts added for coordinate conversion, batch rule checking, archive actions, and response protocols. - References covering CSV contract, user interaction, and edge cases added for clarity and compatibility. - Archive and provider handling: now enforce strict blocking on errors and ambiguous provider/country/ID assignments—never proceed or guess; always request explicit confirmation where required by pipeline output. - Batch and archive deduplication made idempotent and conflict-resilient: parcel code reuse and per-parcel resolution are strictly script-driven. - All file delivery instructions, CSV labeling (顶点表/边界表), and language rules codified and enforced. - Removed obsolete skill-card documentation; see reference files for contributor guidelines.","fileCount":17,"zipByteSize":32372},{"version":"2.1.1","createdAt":"2026-06-29T07:21:16.430Z","changelog":"- Documentation update in SKILL.md for clarity and thoroughness; content only, no logic changes. - Removed obsolete `.clawhub/origin.json` metadata file. - No changes to core processing or scripts; skill behavior remains identical. - Improved instructions and structure in the SKILL.md for maintainability and easier onboarding.","fileCount":10,"zipByteSize":30624},{"version":"2.1.0","createdAt":"2026-06-29T07:15:07.905Z","changelog":"**Summary:** - Added `.clawhub/origin.json` for origin tracking or metadata. - No changes to workflow or user-facing features.","fileCount":11,"zipByteSize":31276},{"version":"2.0.3","createdAt":"2026-06-10T14:29:49.586Z","changelog":"ovitalmap-parcel-csv 2.0.3 - Internal scripts updated: archive_manager.py, csv_builder.py, parcel_pipeline.py, utils.py. - Likely improvements in code structure, handling, or bug fixes across key data processing and pipeline orchestration scripts. - No user-facing command or workflow changes documented in SKILL.md.","fileCount":10,"zipByteSize":29937},{"version":"2.0.2","createdAt":"2026-06-10T14:18:46.238Z","changelog":"Version 2.0.2 - Updated scripting conventions: LLM now must check and override anomalous script results (e.g. implausible country, duplicate handling errors), making scripts tools but not final authorities. - No core logic or workflow changes—functionality remains focused on parsing parcel coordinates, generating CSVs, and managing per-country archives.","fileCount":10,"zipByteSize":29658},{"version":"2.0.1","createdAt":"2026-06-10T02:42:50.068Z","changelog":"**Country detection now handled by the LLM, not by script.** - `country_locator.py` now only normalizes and validates coordinates; it no longer determines country codes. - The LLM is responsible for country determination based on coordinate ranges, document text, and conversation context. - All methodology and workflow steps updated to reflect this LLM-led country identification process. - Documented script interface/contract adjustments and clarified input/output expectations.","fileCount":10,"zipByteSize":29157},{"version":"2.0.0","createdAt":"2026-06-10T01:48:46.443Z","changelog":"**Major update: introduces modular Python scripting for all data processing and key workflow changes.** - All data processing, QC, CSV generation, and archiving now run via dedicated Python scripts in the `scripts/` directory instead of LLM-only logic. - Country code format switched from ISO 3166-1 alpha-3 (e.g., CHN) to alpha-2 (e.g., CN) for compatibility with automated Nominatim geo lookups. - Code assignment, duplicate checks, and provider name matching are all managed via script workflows, centralizing archive logic and batch processing. - Updated system workflow: stepwise orchestration using `parcel_pipeline.py`, separating coordinate/provider resolution, duplicate detection, code assignment, CSV generation, and archiving. - Added/removed files: introduces 7 Python scripts for all operations; documentation file `skill-card.md` removed. - Skill description, procedures, and examples revised to reflect script-based operation and new conventions.","fileCount":10,"zipByteSize":32419}]},"execution":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No published capability contract is available yet."},"installCommand":"clawhub skill install s17fqp1p7fy20kfj7hwd6ax4z1885ne8:ovitalmap-parcel-csv","setupComplexity":"low","setupSteps":["Install using `clawhub skill install s17fqp1p7fy20kfj7hwd6ax4z1885ne8:ovitalmap-parcel-csv` in an isolated environment before connecting it to live workloads.","No published capability contract is available yet, so validate auth and request/response behavior manually.","Review the upstream CLAWHUB listing at https://clawhub.ai/jeromeex/ovitalmap-parcel-csv before using production credentials."],"contract":{"contractStatus":"missing","authModes":[],"requires":[],"forbidden":[],"supportsMcp":false,"supportsA2a":false,"supportsStreaming":false,"inputSchemaRef":null,"outputSchemaRef":null,"dataRegion":null,"contractUpdatedAt":null,"sourceUpdatedAt":null,"freshnessSeconds":null},"invocationGuide":{"preferredApi":{"snapshotUrl":"https://www.xpersona.co/api/v1/agents/clawhub-jeromeex-ovitalmap-parcel-csv/snapshot","contractUrl":"https://www.xpersona.co/api/v1/agents/clawhub-jeromeex-ovitalmap-parcel-csv/contract","trustUrl":"https://www.xpersona.co/api/v1/agents/clawhub-jeromeex-ovitalmap-parcel-csv/trust"},"curlExamples":["curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-jeromeex-ovitalmap-parcel-csv/snapshot\"","curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-jeromeex-ovitalmap-parcel-csv/contract\"","curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-jeromeex-ovitalmap-parcel-csv/trust\""],"jsonRequestTemplate":{"query":"summarize this repo","constraints":{"maxLatencyMs":2000,"protocolPreference":["OPENCLEW"]}},"jsonResponseTemplate":{"ok":true,"result":{"summary":"...","confidence":0.9},"meta":{"source":"CLAWHUB","generatedAt":"2026-10-11T10:50:23.839Z"}},"retryPolicy":{"maxAttempts":3,"backoffMs":[500,1500,3500],"retryableConditions":["HTTP_429","HTTP_503","NETWORK_TIMEOUT"]}},"endpoints":{"dossierUrl":"https://www.xpersona.co/api/v1/agents/clawhub-jeromeex-ovitalmap-parcel-csv/dossier","snapshotUrl":"https://www.xpersona.co/api/v1/agents/clawhub-jeromeex-ovitalmap-parcel-csv/snapshot","contractUrl":"https://www.xpersona.co/api/v1/agents/clawhub-jeromeex-ovitalmap-parcel-csv/contract","trustUrl":"https://www.xpersona.co/api/v1/agents/clawhub-jeromeex-ovitalmap-parcel-csv/trust"}},"reliability":{"evidence":{"source":"runtime-metrics","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No trust, reliability, or runtime telemetry is available."},"trust":{"status":"unavailable","handshakeStatus":"UNKNOWN","verificationFreshnessHours":null,"reputationScore":null,"p95LatencyMs":null,"successRate30d":null,"fallbackRate":null,"attempts30d":null,"trustUpdatedAt":null,"trustConfidence":"unknown","sourceUpdatedAt":null,"freshnessSeconds":null},"decisionGuardrails":{"doNotUseIf":["Contract metadata is missing or unavailable for deterministic execution."],"safeUseWhen":[],"riskFlags":["missing_or_unavailable_contract","trust_data_unavailable","schema_references_missing"],"operationalConfidence":"low"},"executionMetrics":{"observedLatencyMsP50":null,"observedLatencyMsP95":null,"estimatedCostUsd":null,"uptime30d":null,"rateLimitRpm":null,"rateLimitBurst":null,"lastVerifiedAt":null,"verificationSource":null},"runtimeMetrics":{"successRate":null,"avgLatencyMs":null,"avgCostUsd":null,"hallucinationRate":null,"retryRate":null,"disputeRate":null,"p50Latency":null,"p95Latency":null,"lastUpdated":null}},"benchmarks":{"evidence":{"source":"no-benchmark-data","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No benchmark suites or observed failure patterns are available."},"suites":[],"failurePatterns":[]},"artifacts":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-11T06:50:12.624Z","emptyReason":null},"readme":"Skill: OvitalMap Parcel CSV\n\nOwner: jeromeex\n\nSummary: Convert parcel boundaries into OvitalMap-compatible CSV files, assign stable parcel codes, and maintain deduplicated country and master archives. Use for WGS84, DMS, or UTM coordinates supplied as text or images, including archive re-exports and coordinate corrections. Do not use it as cadastral or legal validation.\n\nTags: latest:3.0.1\n\nVersion history:\n\nv3.0.1 | 2026-09-04T13:06:00.108Z | user\n\nPrepared for portable public use: added runtime metadata and MIT-0 licensing, replaced hard-coded Chinese replies with language-neutral workflow messages, removed Chinese-specific provider heuristics and legacy interfaces, and retained validated OvitalMap CSV/archive safeguards.\n\nv3.0.0 | 2026-07-23T10:57:55.353Z | user\n\novitalmap-parcel-csv v2.1.2\n\n- Major workflow revision: all data extraction, conversion, code assignment, and archiving now flow through explicit Python scripts using JSON input/output, prohibiting any in-conversation \"LLM reasoning\" for these tasks.\n- New scripts added for coordinate conversion, batch rule checking, archive actions, and response protocols.\n- References covering CSV contract, user interaction, and edge cases added for clarity and compatibility.\n- Archive and provider handling: now enforce strict blocking on errors and ambiguous provider/country/ID assignments—never proceed or guess; always request explicit confirmation where required by pipeline output.\n- Batch and archive deduplication made idempotent and conflict-resilient: parcel code reuse and per-parcel resolution are strictly script-driven.\n- All file delivery instructions, CSV labeling (顶点表/边界表), and language rules codified and enforced.\n- Removed obsolete skill-card documentation; see reference files for contributor guidelines.\n\nv2.1.1 | 2026-06-29T07:21:16.430Z | auto\n\n- Documentation update in SKILL.md for clarity and thoroughness; content only, no logic changes.\n- Removed obsolete `.clawhub/origin.json` metadata file.\n- No changes to core processing or scripts; skill behavior remains identical.\n- Improved instructions and structure in the SKILL.md for maintainability and easier onboarding.\n\nv2.1.0 | 2026-06-29T07:15:07.905Z | user\n\n**Summary:** \n- Added `.clawhub/origin.json` for origin tracking or metadata.\n- No changes to workflow or user-facing features.\n\nv2.0.3 | 2026-06-10T14:29:49.586Z | auto\n\novitalmap-parcel-csv 2.0.3\n\n- Internal scripts updated: archive_manager.py, csv_builder.py, parcel_pipeline.py, utils.py.\n- Likely improvements in code structure, handling, or bug fixes across key data processing and pipeline orchestration scripts.\n- No user-facing command or workflow changes documented in SKILL.md.\n\nv2.0.2 | 2026-06-10T14:18:46.238Z | user\n\nVersion 2.0.2\n\n- Updated scripting conventions: LLM now must check and override anomalous script results (e.g. implausible country, duplicate handling errors), making scripts tools but not final authorities.\n- No core logic or workflow changes—functionality remains focused on parsing parcel coordinates, generating CSVs, and managing per-country archives.\n\nv2.0.1 | 2026-06-10T02:42:50.068Z | auto\n\n**Country detection now handled by the LLM, not by script.**\n\n- `country_locator.py` now only normalizes and validates coordinates; it no longer determines country codes.\n- The LLM is responsible for country determination based on coordinate ranges, document text, and conversation context.\n- All methodology and workflow steps updated to reflect this LLM-led country identification process.\n- Documented script interface/contract adjustments and clarified input/output expectations.\n\nv2.0.0 | 2026-06-10T01:48:46.443Z | user\n\n**Major update: introduces modular Python scripting for all data processing and key workflow changes.**\n\n- All data processing, QC, CSV generation, and archiving now run via dedicated Python scripts in the `scripts/` directory instead of LLM-only logic.\n- Country code format switched from ISO 3166-1 alpha-3 (e.g., CHN) to alpha-2 (e.g., CN) for compatibility with automated Nominatim geo lookups.\n- Code assignment, duplicate checks, and provider name matching are all managed via script workflows, centralizing archive logic and batch processing.\n- Updated system workflow: stepwise orchestration using `parcel_pipeline.py`, separating coordinate/provider resolution, duplicate detection, code assignment, CSV generation, and archiving.\n- Added/removed files: introduces 7 Python scripts for all operations; documentation file `skill-card.md` removed.\n- Skill description, procedures, and examples revised to reflect script-based operation and new conventions.\n\nv1.0.1 | 2026-06-09T14:48:33.628Z | user\n\nProvider confirmation moved to Step 1. No code assignment or file writing until both coordinates and provider are confirmed.\n\nProactive fuzzy deduplication added to provider workflow. Every user-supplied provider name is now matched against all existing records using four rules: exact match, whitespace/punctuation variation, Chinese-Pinyin overlap, and partial/suffix/prefix overlap. When a short/ambiguous name matches multiple existing providers, the system lists all candidates and asks the user to specify which one. If the user is unsure, the new name is kept with a \"Possible duplicate\" note in provider_notes.\n\nExample output updated to reflect the new flow.\n\nv1.0.0 | 2026-06-09T14:32:28.666Z | auto\n\nInitial skill release for Ovitalmap Parcel CSV Generator.\n\n- Parses parcel vertex coordinates from images or text in multiple formats (decimal degrees, DMS, UTM, etc.).\n- Auto-detects country from coordinates and generates unique `parcel_code` for each parcel, prioritizing official IDs.\n- Produces Ovitalmap-compatible Vertices CSV (顶点表) and Boundary CSV (边界表), using strict file/content conventions.\n- Archives processed parcels into per-country CSV databases with full categorization.\n- Includes robust quality checks, duplicate handling, collision reporting, and preserves full coordinate precision.\n\nArchive index:\n\nArchive v3.0.1: 16 files, 31290 bytes\n\nFiles: references/csv-contract.md (2036b), references/interaction-and-edge-cases.md (3400b), references/workflow-contract.md (1900b), scripts/archive_manager.py (11954b), scripts/archive_store.py (4506b), scripts/batch_rules.py (2204b), scripts/coordinate_converter.py (5379b), scripts/country_locator.py (2073b), scripts/csv_builder.py (9629b), scripts/parcel_pipeline.py (26617b), scripts/provider_matcher.py (1495b), scripts/response_protocol.py (5736b), scripts/utils.py (8667b), skill-card.md (2257b), SKILL.md (4685b), _meta.json (139b)\n\nFile v3.0.1:SKILL.md\n\n---\nname: ovitalmap-parcel-csv\ndescription: Convert parcel boundaries into OvitalMap-compatible CSV files, assign stable parcel codes, and maintain deduplicated country and master archives. Use for WGS84, DMS, or UTM coordinates supplied as text or images, including archive re-exports and coordinate corrections. Do not use it as cadastral or legal validation.\nlicense: MIT-0\nmetadata:\n  openclaw:\n    requires:\n      bins:\n        - python3\n    envVars:\n      - name: OVITALMAP_WORKSPACE\n        required: false\n        description: Directory for generated exports and archives; defaults to the current working directory.\n---\n\n# OvitalMap Parcel CSV\n\nUse the bundled Python scripts through JSON stdin/stdout. Do not recreate coordinate conversion, code allocation, CSV generation, or archive updates manually.\n\n## Input\n\nSet `OVITALMAP_WORKSPACE` to the directory where exports and archives should be stored. If it is unset, the scripts use the current working directory.\n\nEach parcel is a JSON object:\n\n```json\n{\"vertices\":[[114.13472,22.50422],[114.13564,22.50411],[114.135,22.503]],\"provider_name\":\"Survey Team\",\"official_id\":null,\"altitude\":[]}\n```\n\nUse WGS84 longitude, latitude order. For a batch, keep one country or region per pipeline run. The pipeline assigns stable `parcel_ref` values (`P01`, `P02`, and so on).\n\n## Workflow\n\n1. Extract and show the source coordinate text. When the source is an image, preserve the transcription for review.\n2. Convert decimal, DMS, or UTM coordinates with `scripts/coordinate_converter.py`. Supply the coordinate `format`; for decimal input also supply `order`, and for UTM supply `zone` and `hemisphere`.\n3. Show the resulting WGS84 vertices and obtain explicit confirmation of the coordinates and provider names. Do not write exports or archives before confirmation.\n4. Obtain the ISO 3166-1 alpha-2 country or region code from explicit context. Ask when it is uncertain.\n5. Run `python3 scripts/parcel_pipeline.py --step 1` with `parcels`, `country_code`, and optional `date` in `YYMMDD` form. Retain the returned `run_id`. On `needs_input`, request only the fields listed in `required_input`.\n6. Continue with the same `run_id`: run Step `2b` to classify archive hits and new parcels, then Step `2` to assign codes to new parcels.\n7. Show the proposed codes. After the user approves them, pass `confirmed_codes: true` to Step `3`.\n8. Deliver every path in `result.exports` in its returned order. Boundary files import into OvitalMap as tracks (`轨迹`); vertex files import as labels (`标签`).\n\nUse `--step all` only when the user has already confirmed the complete input and explicitly approved automatic code acceptance with `\"confirmed\": true` and `\"auto_accept_codes\": true`.\n\n## Parcel codes\n\nPrefer a confirmed official registration, cadastral, or permit identifier:\n\n```text\n{CC}-{OFFICIAL_ID}\n```\n\nWhen no official identifier is available, assign a stable archive code:\n\n```text\n{CC}-{YYMMDD}-{SEQ}\n```\n\nThe archive determines the next three-digit sequence. Do not use `unknown`, invent a descriptive parcel name, or silently replace a generated code later.\n\n## Export modes\n\n- `boundary` is the default and produces one track CSV per parcel.\n- `vertices` produces one label CSV per parcel only when explicitly requested.\n- `both` produces both formats only when explicitly requested.\n\nPreserve the chosen mode throughout a multi-step run.\n\n## Safety and consistency\n\n- Treat `error`, `blocked`, and `needs_input` as stopping conditions.\n- Never guess the country, provider, altitude, official identifier, UTM zone, or hemisphere.\n- Reuse an archive hit's parcel code and metadata; do not append it again.\n- Resolve batch conflicts by `parcel_ref`; identical coordinates do not prove two submissions are the same parcel.\n- Do not replace a non-empty cadastral identifier without explicit confirmation.\n- Preserve vertex order; the scripts close polygons when needed.\n- Export each parcel separately and preserve submitted order.\n- The scripts own filenames, CSV headers, encoding, archive schemas, and defaults.\n\n## Archive operations\n\nUse `scripts/archive_manager.py` with one of these actions: `scan`, `check_duplicate`, `extract_single`, `update_cadastre`, `backup`, or `correct`.\n\n## References\n\n- Read [references/csv-contract.md](references/csv-contract.md) when checking or changing OvitalMap CSV compatibility.\n- Read [references/workflow-contract.md](references/workflow-contract.md) when handling pipeline states, confirmations, or errors.\n- Read [references/interaction-and-edge-cases.md](references/interaction-and-edge-cases.md) for duplicate submissions, archive hits, corrections, or multi-parcel batches.\n\nFile v3.0.1:_meta.json\n\n{\n  \"ownerId\": \"kn76j7kby3cajgq933bwccdxbn82fw68\",\n  \"slug\": \"ovitalmap-parcel-csv\",\n  \"version\": \"3.0.1\",\n  \"publishedAt\": 1788527160108\n}\n\nFile v3.0.1:references/csv-contract.md\n\n# CSV Compatibility Contract\n\nDo not change this contract without an explicit migration request.\n\n## Encoding and filenames\n\n- Encoding: UTF-8, comma-separated, no BOM.\n- Directory: `ovitalmap_exports/{CC}/`.\n- Every generated file contains exactly one parcel.\n- Default boundary export: `{parcelCode}_{YYYYMMDD_HHMMSS}.csv`.\n- Explicit vertex export: `{parcelCode}_{YYYYMMDD_HHMMSS}_vertices.csv`.\n- Same-second collisions append `_02`, `_03`, and so on before `.csv` or `_vertices.csv`.\n\nFor multiple parcels, generate files in submitted `parcel_ref` order and do not combine them. Archive names remain `{CC}_parcels.csv` and `master.csv`.\n\nThe export modes are:\n\n- `boundary` (default): boundary file only.\n- `vertices`: vertex file only, and only after an explicit user request.\n- `both`: both files, only after an explicit user request for both.\n\n## Vertex CSV (顶点表)\n\nExact headers:\n\n```text\n文件夹,名称,经度,纬度,海拔,文本显示风格,图标样式,Comment\n```\n\n- 文件夹: parcel code.\n- 名称: `{parcel_code}_A01`, restarting at A01 for each parcel.\n- 经度/纬度: WGS84 longitude and latitude in original vertex order.\n- 海拔: input altitude or empty.\n- 文本显示风格: empty.\n- 图标样式: `1`.\n- Comment: `提供者:{provider} 归档日期:{YYYY-MM-DD}` and, when present, ` 地籍号:{cadastre_code}`.\n\n## Boundary CSV\n\nExact headers:\n\n```text\n文件夹,名称,经纬度[经度+纬度],线条宽度,线条颜色,线条不透明度,闭合,线型,轨迹风格,Comment\n```\n\n- 文件夹 and 名称: parcel code.\n- 经纬度: `lon,lat;lon,lat;...`; repeat the first point to close the polygon.\n- 线条宽度: `3`.\n- 线条颜色: `0X00FF0000`.\n- 线条不透明度: `50`.\n- 闭合: `1`.\n- 线型: `0`.\n- 轨迹风格: `1`.\n- Comment: same as the vertex CSV.\n\n## Archive schemas\n\nPer-country:\n\n```text\nparcel_code,provider_name,archive_date,boundary_coords,provider_notes,cadastre_code\n```\n\nMaster:\n\n```text\nCC,parcel_code,provider_name,archive_date,boundary_coords,provider_notes,cadastre_code\n```\n\nFile v3.0.1:references/interaction-and-edge-cases.md\n\n# Interaction and Edge Cases\n\n## Delivery\n\nSend or link the actual files in their returned order:\n\n```text\n1. {first_parcel_filename}\n2. {second_parcel_filename}\n```\n\nGive the import instruction once: open each boundary CSV in OvitalMap and choose `轨迹`. For vertex files, choose `标签`. If both modes were requested, distinguish them by the `_vertices` filename suffix.\n\n## Archive model\n\n- `{CC}_parcels.csv` is the country record.\n- `master.csv` is the all-in-one cross-country record.\n- New parcels update both in one locked commit.\n- Archive hits are re-exported without another append.\n- Corrections back up and update both records.\n\n## Parcel codes\n\nPrefer a confirmed official registration/cadastre/permit ID:\n\n```text\n{CC}-{OFFICIAL_ID}\n```\n\nOtherwise use:\n\n```text\n{CC}-{YYMMDD}-{SEQ}\n```\n\nThe archive allocates sequence continuity. An existing official code is blocking and requires user review; do not silently fall back to a sequential code.\n\n## Archive hits\n\n- Reuse the archived parcel code and provider metadata.\n- Export only that parcel as its own file in the requested export mode.\n- Do not append it again.\n- If a newly supplied official ID fills an empty cadastre field, update it during Step 3.\n- If the user insists identical coordinates represent a different parcel, require explicit confirmation and set `allow_duplicate_coordinates: true` with a note naming the matched code.\n\nFor a mixed batch, preserve the original `parcel_ref` order across archive hits and new parcels. Export each parcel separately; do not group the delivered files by archive status.\n\n## Multi-parcel batches\n\n- Keep `parcel_ref` stable from intake through replies, CSV generation, and archive results. Numeric positions remain accepted only for backward-compatible input.\n- Generate one file per parcel for the requested mode and return the files in `parcel_ref` order. If both modes were requested, keep each parcel's normal file immediately before its `_vertices` file.\n- Use one country/region per pipeline run. If parcel-level country codes differ, split the batch and preserve each parcel's ref.\n- Report all current parcel-specific problems together in the user's language.\n- If two submitted parcels have identical boundaries, request `duplicate_resolutions.{parcel_ref}`:\n  - `same`: skip the later duplicate.\n  - `different`: keep both, record explicit confirmation, and allow the duplicate boundary during archive commit.\n- Reject duplicate non-empty official IDs before code allocation. Use `official_id_resolutions.{parcel_ref}` to correct or clear the later value.\n- Never drop an unresolved parcel from run state. No CSV or archive write may occur while a batch conflict remains.\n\n## Provider matching\n\n- Exact normalized match: reuse automatically.\n- No match: keep the supplied provider.\n- Never merge providers based on similarity alone.\n\n## Corrections\n\nUse `archive_manager.py` action `correct` with `country_code`, `parcel_code`, and `new_vertices`. The operation must:\n\n1. Validate the corrected polygon.\n2. Require the parcel in both country and master archives.\n3. Reject coordinates already belonging to another parcel.\n4. Back up both archives.\n5. Update both rows atomically.\n6. Regenerate the corrected boundary file by default, or the explicitly requested vertex/both mode.\n\nReport the backup and generated file paths and ask the user to verify the corrected parcel.\n\nFile v3.0.1:references/workflow-contract.md\n\n# Workflow Contract\n\nEvery pipeline response contains:\n\n```text\nstatus: needs_input | ready | completed | blocked\nnext_action: machine-readable next step\nrequired_input: exact missing confirmations or values\nmessage: concise user-facing summary\nresult: structured evidence and file paths\n```\n\n## Agent behavior\n\n- `needs_input`: show the message and relevant coordinate or code preview, ask only for `required_input`, and stop.\n- `ready`: report the result and perform `next_action` when it requires no new user decision.\n- `completed`: deliver every item in `result.exports` in order and give the appropriate OvitalMap import instruction.\n- `blocked`: explain the message, make no success claim, and wait for corrected input or retry safely.\n\nRespond in the user's language. Do not expose run state or raw JSON unless the user asks for technical details.\n\n## Confirmation gates\n\nThe pipeline must not pass these gates implicitly:\n\n- `confirmed_coordinates`: the user verified the displayed WGS84 vertices.\n- `country_code`: the country or region is known rather than guessed.\n- `provider_resolutions.{parcel_ref}`: a missing or ambiguous provider is resolved per parcel.\n- `duplicate_resolutions.{parcel_ref}`: identical submitted boundaries are confirmed as `same` or `different`.\n- `official_id_resolutions.{parcel_ref}`: duplicate official identifiers are corrected or cleared.\n- `confirmed_codes`: the user approved generated parcel codes before Step 3.\n- `auto_accept_codes`: explicit permission for non-interactive `--step all`.\n\n`export_mode` is not a confirmation gate. It defaults to `boundary` and must remain unchanged throughout a run unless the user explicitly requests another mode.\n\nUse stable parcel references in decisions:\n\n```json\n{\"provider_resolutions\":{\"P01\":\"Survey Team\"},\"duplicate_resolutions\":{\"P02\":\"different\"}}\n```\n\nUse `parcel_ref` keys for every per-parcel decision.\n\nFile v3.0.1:skill-card.md\n\n## Description:\n\nConverts parcel boundaries into OvitalMap-compatible CSV files, assigns stable parcel codes, and maintains deduplicated country and master archives.\n\nThis skill is ready for commercial/non-commercial use.\n\n## Publisher:\n\n[jeromeex](https://clawhub.ai/user/jeromeex)\n\n### License/Terms of Use:\n\nMIT-0\n\n## Use Case:\n\nDevelopers, survey operations teams, and land-record workflows use this skill to convert confirmed WGS84, DMS, or UTM parcel coordinates into OvitalMap boundary or vertex CSV exports while preserving parcel codes and local archives. It is not cadastral or legal validation.\n\n### Deployment Geography for Use:\n\nGlobal\n\n## Known Risks and Mitigations:\n\nRisk: Untrusted provider names or notes can be persisted into generated CSV archives in a form spreadsheet software may interpret as formulas.\n\nMitigation: Review and sanitize provider-supplied text before opening generated CSVs in spreadsheet software; keep generated exports in a dedicated workspace.\n\nRisk: The skill creates and updates local CSV exports, country archives, master archives, and backups.\n\nMitigation: Set OVITALMAP_WORKSPACE to a dedicated folder and review coordinates, country codes, provider names, and parcel codes before approving writes.\n\n## Reference(s):\n\n- [OvitalMap Parcel CSV on ClawHub](https://clawhub.ai/jeromeex/skills/ovitalmap-parcel-csv)\n- [CSV Compatibility Contract](references/csv-contract.md)\n- [Workflow Contract](references/workflow-contract.md)\n- [Interaction and Edge Cases](references/interaction-and-edge-cases.md)\n\n## Skill Output:\n\n**Output Type(s):** [text, markdown, shell commands, configuration, guidance, CSV files]\n\n**Output Format:** [Markdown guidance with JSON stdin examples and generated UTF-8 CSV files]\n\n**Output Parameters:** [1D]\n\n**Other Properties Related to Output:** [Requires python3; OVITALMAP_WORKSPACE can be set to a dedicated folder for generated exports and archives.]\n\n## Skill Version(s):\n\n3.0.1 (source: server release metadata)\n\n## Ethical Considerations:\n\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment.\n\nArchive v3.0.0: 17 files, 32372 bytes\n\nFiles: references/csv-contract.md (1781b), references/interaction-and-edge-cases.md (3538b), references/reply-contract.md (1895b), scripts/__init__.py (39b), scripts/archive_manager.py (11781b), scripts/archive_store.py (4506b), scripts/batch_rules.py (2343b), scripts/coordinate_converter.py (5379b), scripts/country_locator.py (2073b), scripts/csv_builder.py (8354b), scripts/parcel_pipeline.py (27044b), scripts/provider_matcher.py (3584b), scripts/response_protocol.py (7084b), scripts/utils.py (8667b), skill-card.md (2637b), SKILL.md (3161b), _meta.json (139b)\n\nFile v3.0.0:SKILL.md\n\n---\nname: ovitalmap-parcel-csv\ndescription: Generate and archive Ovitalmap parcel vertex/boundary CSVs. Use when users provide parcel coordinates or images and request 奥维地图 CSV export, archive re-export, or coordinate correction.\n---\n\n# Ovitalmap Parcel CSV\n\nUse scripts via JSON stdin/stdout; never reproduce processing manually. Reply with `reply_zh` in Chinese unless another language is requested.\n\n## Setup\n\nSet `OVITALMAP_WORKSPACE` to the user's working directory; otherwise scripts use the current directory.\n\nParcel input:\n\n```json\n{\"vertices\":[[114.13472,22.50422],[114.13564,22.50411],[114.135,22.503]],\"provider_name\":\"张三\",\"official_id\":null,\"altitude\":[]}\n```\n\nUse WGS84 longitude, latitude order. For batches, keep one country per run and providers per parcel unless shared. The pipeline assigns stable `parcel_ref` values (`P01`, `P02`, ...).\n\n## Workflow\n\n1. Extract and display the raw coordinate text.\n2. Convert decimal, DMS, or UTM input with `scripts/coordinate_converter.py`. Pass `format` and `coordinates`; also pass decimal `order`, or UTM `zone` and `hemisphere`.\n3. Display converted vertices and obtain explicit confirmation of coordinates and providers. Do not write files before confirmation.\n4. Obtain the ISO alpha-2 country code from explicit context; ask if uncertain.\n5. Run pipeline `--step 1` with `parcels`, `country_code`, and optional `date` (`YYMMDD`). Retain `run_id`; on `needs_input`, ask only for `required_input`.\n6. Resolve provider candidates: reuse exact matches; ask before every non-exact or ambiguous match.\n7. With the same `run_id`, run:\n   - `--step 2b` to classify archive hits and new parcels.\n   - `--step 2` to propose codes for new parcels.\n   - After the user approves codes, pass `confirmed_codes: true` to `--step 3`.\n8. Attach or link every generated file. Label vertex files 顶点表 and boundary files 边界表.\n\nUse `--step all` only with explicit `\"confirmed\": true` and `\"auto_accept_codes\": true`.\n\n## Hard Rules\n\n- Treat `error` and `needs_input` as blocking. Do not translate `reply_zh` or expose internal JSON unless asked.\n- Never edit archive CSVs manually or guess country, provider, altitude, official ID, UTM zone, or hemisphere.\n- Reuse an archive hit's parcel code; never append it again.\n- Resolve batch conflicts by `parcel_ref`; never infer whether identical coordinates mean the same parcel.\n- Do not replace a non-empty cadastre code without confirmation.\n- Preserve vertex order; scripts close polygons.\n- Deliver both CSV types. Scripts own the CSV headers and defaults.\n\n## Targeted Archive Actions\n\nCall `scripts/archive_manager.py` with `action`: `scan`, `check_duplicate`, `extract_single`, `update_cadastre`, `backup`, or `correct`.\n\n## References\n\n- Read [references/csv-contract.md](references/csv-contract.md) only when checking or changing CSV compatibility.\n- Read [references/reply-contract.md](references/reply-contract.md) when changing interaction gates or user-facing replies.\n- Read [references/interaction-and-edge-cases.md](references/interaction-and-edge-cases.md) for delivery, mixed hits, provider ambiguity, official IDs, or corrections.\n\nFile v3.0.0:_meta.json\n\n{\n  \"ownerId\": \"kn76j7kby3cajgq933bwccdxbn82fw68\",\n  \"slug\": \"ovitalmap-parcel-csv\",\n  \"version\": \"3.0.0\",\n  \"publishedAt\": 1784804275353\n}\n\nFile v3.0.0:references/csv-contract.md\n\n# CSV Compatibility Contract\n\nDo not change this contract without an explicit migration request.\n\n## Encoding and filenames\n\n- Encoding: UTF-8, comma-separated, no BOM.\n- Directory: `ovitalmap_exports/{CC}/`.\n- Single parcel: `{parcelCode}_{YYYYMMDD_HHMMSS}_{vertices|boundary}.csv`.\n- Multi-parcel batch: `{CC}_batch_N{count}_{YYYYMMDD_HHMMSS}_{vertices|boundary}.csv`.\n- Same-second collisions append `_02`, `_03`, and so on before the type suffix.\n\nFilenames describe the export; CSV rows retain each parcel's actual code. Archive names remain `{CC}_parcels.csv` and `master.csv`.\n\n## Vertex CSV (顶点表)\n\nExact headers:\n\n```text\n文件夹,名称,经度,纬度,海拔,文本显示风格,图标样式,Comment\n```\n\n- 文件夹: parcel code.\n- 名称: `{parcel_code}_A01`, restarting at A01 for each parcel.\n- 经度/纬度: WGS84 longitude and latitude in original vertex order.\n- 海拔: input altitude or empty.\n- 文本显示风格: empty.\n- 图标样式: `1`.\n- Comment: `提供者:{provider} 归档日期:{YYYY-MM-DD}` and, when present, ` 地籍号:{cadastre_code}`.\n\n## Boundary CSV (边界表)\n\nExact headers:\n\n```text\n文件夹,名称,经纬度[经度+纬度],线条宽度,线条颜色,线条不透明度,闭合,线型,轨迹风格,Comment\n```\n\n- 文件夹 and 名称: parcel code.\n- 经纬度: `lon,lat;lon,lat;...`; repeat the first point to close the polygon.\n- 线条宽度: `3`.\n- 线条颜色: `0X00FF0000`.\n- 线条不透明度: `50`.\n- 闭合: `1`.\n- 线型: `0`.\n- 轨迹风格: `1`.\n- Comment: same as the vertex CSV.\n\n## Archive schemas\n\nPer-country:\n\n```text\nparcel_code,provider_name,archive_date,boundary_coords,provider_notes,cadastre_code\n```\n\nMaster:\n\n```text\nCC,parcel_code,provider_name,archive_date,boundary_coords,provider_notes,cadastre_code\n```\n\nFile v3.0.0:references/interaction-and-edge-cases.md\n\n# Interaction and Edge Cases\n\n## Delivery\n\nSend or link the actual files and label them explicitly:\n\n```text\n顶点表（导入为“标签”）：{vertices_filename}\n边界表（导入为“轨迹”）：{boundary_filename}\n```\n\nTell the user to open each CSV in 奥维地图, choose the stated import type, confirm the import page, select 导入, and confirm the import options.\n\n## Archive model\n\n- `{CC}_parcels.csv` is the country record.\n- `master.csv` is the all-in-one cross-country record.\n- New parcels update both in one locked commit.\n- Archive hits are re-exported without another append.\n- Corrections back up and update both records.\n\n## Sharing the master archive\n\nSharing is entirely user-directed. Do not prompt automatically or prescribe email, timing, sender, recipient, or delivery service. If the user asks to share `master.csv`, follow their requested method with the available tools and never store delivery details in the archive.\n\n## Parcel codes\n\nPrefer a confirmed official registration/cadastre/permit ID:\n\n```text\n{CC}-{OFFICIAL_ID}\n```\n\nOtherwise use:\n\n```text\n{CC}-{YYMMDD}-{SEQ}\n```\n\nThe archive allocates sequence continuity. An existing official code is blocking and requires user review; do not silently fall back to a sequential code.\n\n## Archive hits\n\n- Reuse the archived parcel code and provider metadata.\n- Export only that parcel as its own CSV pair.\n- Do not append it again.\n- If a newly supplied official ID fills an empty cadastre field, update it during Step 3.\n- If the user insists identical coordinates represent a different parcel, require explicit confirmation and set `allow_duplicate_coordinates: true` with a note naming the matched code.\n\nFor a mixed batch, export archive hits individually and new parcels as one batch. Present the groups separately.\n\n## Multi-parcel batches\n\n- Keep `parcel_ref` stable from intake through replies, CSV generation, and archive results. Numeric positions remain accepted only for backward-compatible input.\n- Use one country/region per pipeline run. If parcel-level country codes differ, split the batch and preserve each parcel's ref.\n- Report all current parcel-specific problems in one Chinese reply.\n- If two submitted parcels have identical boundaries, request `duplicate_resolutions.{parcel_ref}`:\n  - `same`: skip the later duplicate.\n  - `different`: keep both, record explicit confirmation, and allow the duplicate boundary during archive commit.\n- Reject duplicate non-empty official IDs before code allocation. Use `official_id_resolutions.{parcel_ref}` to correct or clear the later value.\n- Never drop an unresolved parcel from run state. No CSV or archive write may occur while a batch conflict remains.\n\n## Provider matching\n\n- Exact normalized match: reuse automatically.\n- One non-exact candidate: ask whether it is the same provider.\n- Multiple top candidates: list all and ask the user to choose or create a new provider.\n- No match: keep the supplied provider.\n- Never merge providers based only on substring or pinyin similarity.\n\n## Corrections\n\nUse `archive_manager.py` action `correct` with `country_code`, `parcel_code`, and `new_vertices`. The operation must:\n\n1. Validate the corrected polygon.\n2. Require the parcel in both country and master archives.\n3. Reject coordinates already belonging to another parcel.\n4. Back up both archives.\n5. Update both rows atomically.\n6. Regenerate the corrected vertex and boundary CSV files.\n\nReport the backup and generated file paths and ask the user to verify the new boundary.\n\nFile v3.0.0:references/reply-contract.md\n\n# OpenClaw Reply Contract\n\nEvery pipeline response contains:\n\n```text\nstatus: needs_input | ready | completed | blocked\nnext_action: machine-readable next step\nrequired_input: exact missing confirmations or values\nreply_zh: concise Chinese user-facing response\nresult: structured evidence and file paths\n```\n\n## Agent behavior\n\n- `needs_input`: send `reply_zh`, include relevant coordinate/code preview from `result`, and stop. Ask only for `required_input`.\n- `ready`: report the concise result and perform `next_action` when it requires no new user decision.\n- `completed`: send `reply_zh`, attach/link all paths in `result`, and identify 顶点表 versus 边界表.\n- `blocked`: explain `reply_zh`, make no success claim, and wait for corrected input or retry safely.\n\nUse Chinese by default. Do not expose status keys, run state, or raw JSON unless the user asks for technical details.\n\n## Critical gates\n\nThe pipeline must not pass these gates implicitly:\n\n- `confirmed_coordinates`: user verified the displayed WGS84 vertices.\n- `country_code`: country/region is known rather than guessed.\n- `provider_resolutions.{parcel_ref}`: missing or non-exact provider match is resolved per parcel.\n- `duplicate_resolutions.{parcel_ref}`: identical submitted boundaries are confirmed as `same` or `different`.\n- `official_id_resolutions.{parcel_ref}`: duplicate official IDs are corrected or cleared.\n- `confirmed_codes`: user approved generated codes before Step 3.\n- `auto_accept_codes`: explicit permission required only for non-interactive `--step all`.\n\nUse stable parcel refs in decisions:\n\n```json\n{\"provider_resolutions\":{\"P01\":\"中非李总\"},\"duplicate_resolutions\":{\"P02\":\"different\"}}\n```\n\nLegacy zero-based keys remain accepted as input.\n\nDo not combine multiple unrelated questions. Present all currently missing critical fields once, as a short list, then wait for the user's answer.\n\nFile v3.0.0:skill-card.md\n\n## Description: <br>\nGenerate and archive Ovitalmap parcel vertex/boundary CSVs for users who provide parcel coordinates or images and request 奥维地图 CSV export, archive re-export, or coordinate correction. <br>\n\nThis skill is ready for commercial/non-commercial use. <br>\n\n## Publisher: <br>\n[jeromeex](https://clawhub.ai/user/jeromeex) <br>\n\n### License/Terms of Use: <br>\nMIT-0 <br>\n\n\n## Use Case: <br>\nExternal users and developers use this skill to turn confirmed parcel coordinates into Ovitalmap-compatible vertex and boundary CSV files, then maintain local per-country and master parcel archives. It is intended for workflows that need provider matching, code assignment, archive re-export, or coordinate correction with explicit confirmation gates before writes. <br>\n\n### Deployment Geography for Use: <br>\nGlobal <br>\n\n## Known Risks and Mitigations: <br>\nRisk: The skill writes generated CSVs and can update local parcel archives. <br>\nMitigation: Set OVITALMAP_WORKSPACE to the intended project folder, review coordinate, provider, and code confirmations before allowing writes, and keep backups of important archives. <br>\nRisk: Incorrect country, provider, parcel code, or coordinate confirmation could create misleading Ovitalmap exports or archive records. <br>\nMitigation: Treat script-reported error and needs_input states as blocking, require explicit confirmation for non-exact matches and generated codes, and do not guess missing geographic or identity fields. <br>\n\n\n## Reference(s): <br>\n- [ClawHub Skill Page](https://clawhub.ai/jeromeex/skills/ovitalmap-parcel-csv) <br>\n- [CSV Compatibility Contract](references/csv-contract.md) <br>\n- [Interaction and Edge Cases](references/interaction-and-edge-cases.md) <br>\n- [OpenClaw Reply Contract](references/reply-contract.md) <br>\n\n\n## Skill Output: <br>\n**Output Type(s):** [Text, Markdown, Code, Shell commands, Configuration, Files, Guidance] <br>\n**Output Format:** [Chinese user-facing replies with generated CSV files, file paths, JSON-driven script calls, and concise Markdown guidance when needed] <br>\n**Output Parameters:** [1D] <br>\n**Other Properties Related to Output:** [Produces Ovitalmap vertex and boundary CSVs and can update local parcel archive CSVs after required user confirmations.] <br>\n\n## Skill Version(s): <br>\n3.0.0 (source: server release evidence) <br>\n\n## Ethical Considerations: <br>\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment. <br>\n\nArchive v2.1.1: 10 files, 30624 bytes\n\nFiles: scripts/__init__.py (39b), scripts/archive_manager.py (17303b), scripts/country_locator.py (2539b), scripts/csv_builder.py (7752b), scripts/parcel_pipeline.py (16240b), scripts/provider_matcher.py (6795b), scripts/utils.py (7478b), skill-card.md (2215b), SKILL.md (31921b), _meta.json (139b)\n\nFile v2.1.1:SKILL.md\n\n---\nname: \"ovitalmap-parcel-csv\"\ndescription: \"Parse parcel vertex coordinates from images/text, generate Ovitalmap-compatible CSVs (顶点表 + 边界表), categorize parcels by country-code/provider, and archive into a per-country database. Invoke when user provides parcel coordinates in any format and wants Ovitalmap CSV output.\"\n---\n\n# Ovitalmap Parcel CSV Generator\n\nThis skill processes parcel vertex coordinates — from images or text — and produces Ovitalmap-readable CSV files. It also archives every processed parcel into a structured per-country database with provider metadata.\n\n---\n\n## 0) Defaults: Language, Tone, I/O\n\n- **Reply language**: Chinese by default unless the user requests another language.\n- **Tone**: non-repetitive, concise, precise, professional.\n- **Ambiguity handling**: when inputs are unclear (e.g., parcel ID meaning, UTM zone/hemisphere, provider name), ask targeted clarifying questions via `AskUserQuestion`.\n- **CSV headers**: keep original Chinese headers exactly as listed below. Do not translate them.\n\n---\n\n## 0b) Scripting Conventions (MANDATORY)\n\n**Use Python scripts for all data processing, CSV generation, archive management, and QC checks.** Do not process data through LLM reasoning alone — it is unreliable and costly for structured operations.\n\n### Available Scripts\n\nAll scripts live in `scripts/` and accept JSON via stdin, returning JSON to stdout.\n\n| Script | Purpose | Key CLI examples |\n|--------|---------|------------------|\n| **`scripts/utils.py`** | Shared helpers (CSV I/O, boundary comparison, DMS conversion, coordinate validation). Imported by other scripts — not called directly. | `from utils import boundaries_equal, dms_to_decimal` |\n| **`scripts/country_locator.py`** | Normalize & validate WGS84 coordinates (lat/lon swap detection, range checks). ALWAYS returns `country_code: null` — the LLM determines the country from spatial knowledge and conversation context. | `echo '[[114.13,22.50],[114.14,22.51]]' \\| python3 scripts/country_locator.py` |\n| **`scripts/archive_manager.py`** | All archive operations: scan existing codes/max-SEQ/providers, append new parcels, check coordinate duplicates, backup, correct coordinates, extract single-parcel exports from batch files, update cadastre_code. | `echo '{\"action\":\"scan\",\"country_code\":\"CN\",\"date\":\"260610\"}' \\| python3 scripts/archive_manager.py` |\n| **`scripts/csv_builder.py`** | Build both Vertices CSV (顶点表) and Boundary CSV (边界表) from structured parcel data. Writes to `ovitalmap_exports/{CC}/`. Can also build single-parcel CSVs for archive hits. | `echo '{\"parcels\":[{...}],\"first_code\":\"CN-260610-001\",\"count\":2,\"country_code\":\"CN\"}' \\| python3 scripts/csv_builder.py` |\n| **`scripts/provider_matcher.py`** | Fuzzy-match a provider name against existing names (exact, whitespace, honorific, substring, pinyin). Returns `ambiguous` flag when multiple candidates match equally. | `echo '{\"input_name\":\"李总\",\"existing_names\":[\"中非李总\",\"张三\"]}' \\| python3 scripts/provider_matcher.py` |\n| **`scripts/parcel_pipeline.py`** | **Main orchestrator.** Runs the full flow in steps. Step 1 = country+provider (read-only), Step 2b = duplicate check → reuse matched codes (read-only), Step 2 = code assignment for new parcels (read-only), Step 3 = CSV build for all + archive for new (writes files). | `echo '{\"parcels\":[{...}],\"date\":\"260610\",\"resolved_provider_name\":\"张三\"}' \\| python3 scripts/parcel_pipeline.py --step 2b` |\n\n### Script principles\n\n- Run scripts via `RunCommand` and read their stdout JSON for results.\n- All scripts produce machine-parseable JSON output for the LLM to consume and present to the user.\n- **Use `python3`** as the interpreter.\n- Do not inline large data transformations in the conversation — delegate to scripts.\n- **LLM has the final say.** Scripts are tools, not authorities. If a script's output looks wrong — implausible country, mismatched provider, duplicate not caught, garbled coordinates, unreasonable SEQ jump — the LLM **must** inspect the result, flag anomalies to the user, and override or re-run with corrections when appropriate. Do not silently trust script output.\n\n### Recommended workflow\n\nThe LLM should orchestrate the pipeline **step-by-step** using `parcel_pipeline.py`:\n\n1. **After the user confirms coordinates and provider:** run `--step 1` → get country code, country name, and provider match results.\n2. **Before code assignment — duplicate check:** run `--step 2b` → coordinate-based duplicate check against archive. Archive hits **reuse the existing `parcel_code`** (no new code assigned). Non-hits proceed to step 2.\n3. **Assign codes for new parcels:** run `--step 2` → sequential codes for genuinely new parcels only.\n4. **After the user confirms codes and any archive hits are resolved:** run `--step 3` → CSV generation for **ALL parcels** (batch for new, single-file for hits) + archive append (**new parcels only**).\n\nAlternatively, call individual scripts for targeted operations (e.g., `provider_matcher.py` alone when only checking a provider name).\n\n---\n\n## 1) Inputs and Core Assumptions\n\n- **Input**: one or more images or text blocks that contain parcel vertex coordinates.\n- **Coordinate parsing**: auto-detect format:\n  - Decimal degrees: `22.50422, 114.13472`\n  - DMS: `22°30'15.2\"N, 114°08'05.0\"E`\n  - UTM with zone and hemisphere\n  - Other formats on a best-effort basis\n- **WGS84 policy**:\n  1. Always display the raw recognized coordinates verbatim per parcel.\n  2. Always display WGS84 decimal-degree coordinates (convert if needed).\n- **Date token (YYMMDD)**:\n  - Use user-provided date if given.\n  - Else use today's local date.\n- **CSV format**: UTF-8, comma-separated, no BOM.\n\n---\n\n## 2) Country and Parcel Codes\n\n### 2.1) Country Code\n- **The LLM determines the country.** The `country_locator.py` script only normalizes coordinates; it does NOT perform geocoding. Use your spatial knowledge: match coordinate ranges against the world map, combine with any country names visible in documents, administrative regions mentioned, or the user's stated location.\n- **State it, don't ask.** Present your determination (e.g. \"根据坐标判断，该地块位于中国 (CN)\") and proceed. Do NOT ask \"which country?\" — the user will correct if wrong.\n- Default standard: **ISO 3166-1 alpha-2** (e.g., CN, HK, US, FR).\n- **Cross-border parcels**: assign to the country where the majority of the parcel falls. Do not split.\n\n### 2.2) Parcel Code — Always Generated\n\n**Every parcel MUST receive a `parcel_code`.** There is no \"no code\" fallback.\n\nThe code follows one of two formats, with priority given to official registration IDs:\n\n| Priority | Source | Format | Example |\n|----------|--------|--------|---------|\n| 1 (preferred) | Official registration ID found in **image text or explicitly provided by user** | `{CC}-{OFFICIAL_ID}` | `CN-PE12345`, `AU-EL9876` |\n| 2 (default) | Auto-generated sequential code | `{CC}-{YYMMDD}-{SEQ}` | `CN-260609-003`, `HK-260609-001` |\n\nWhere `{CC}` is the **ISO 3166-1 alpha-2** country code.\n\n**Official registration ID detection:**\n- Scan any user-provided text, image OCR output, chat context, attached documents, or any other input modality for candidate registration / permit / cadastre numbers.\n- If a clear mining cadastre / registration / permit number appears, present it to the user for confirmation before adopting it.\n- If multiple candidate IDs appear for the same parcel, pick the most specific one and ask the user to confirm.\n\n### 2.3) Uniqueness Check (Mandatory Before Code Assignment)\n\n**Before finalizing any `parcel_code`,** you MUST scan the existing archive to prevent duplicates. This is critical because:\n- Users may upload multiple parcels in one session or across separate sessions on the same day.\n- A new session must NOT restart SEQ from 001 — it must continue from the last used number.\n\n**Procedure:**\n\n1. Scan `ovitalmap_archive/{CC}_parcels.csv` (if it exists) — this is the single source of truth.\n2. Extract all existing `parcel_code` values from the archive.\n3. For **official registration IDs** (format 1): check that `{CC}-{OFFICIAL_ID}` does NOT already exist. If it does, warn the user and ask for clarification.\n4. For **sequential codes** (format 2): find the maximum SEQ already used for today (`{CC}-{YYMMDD}-*`). The new SEQ = max_existing + 1. If none exist for today, SEQ starts at `001`.\n5. If the archive file does not exist yet, SEQ starts at `001`.\n\n---\n\n## 3) Output Files Overview\n\nTwo CSVs are produced together for the batch:\n\n| # | File | Description |\n|---|------|-------------|\n| 1 | **Vertices CSV** (顶点表) | Every parcel vertex |\n| 2 | **Boundary CSV** (边界表) | Every parcel as a closed polygon |\n\n### 3.1) File Naming & Layout\n\nStore generated CSVs in **country subdirectories** under `ovitalmap_exports/`:\n\n```\novitalmap_exports/{CC}/\n```\n\nEvery export filename includes a `YYMMDD_HHMMSS` timestamp to prevent collisions even across re-exports or parallel sessions:\n\n| File | Pattern |\n|------|---------|\n| Vertices CSV | `{firstCode}_N{count}_{YYMMDD_HHMMSS}.csv` |\n| Boundary CSV | `{firstCode}_N{count}_{YYMMDD_HHMMSS}_boundary.csv` |\n\n- `firstCode` = the `parcel_code` of the first parcel in this batch.\n- `count` = total number of parcels in this batch.\n- `YYMMDD_HHMMSS` = export timestamp at file-write time.\n\nExamples:\n- `CN-260609-001_N2_260609_143021.csv` — batch of 2, first is 001.\n- `CN-PE12345_N1_260609_143522.csv` — single parcel with an official registration code.\n\n### 3.2) Mandatory User-Facing Delivery Wording\n\nWhenever sending generated CSV files to the user, explicitly identify which file is the **顶点表** and which file is the **边界表**. Do not rely on filenames alone.\n\n**Mandatory file delivery:** After generating CSVs, send/attach the actual CSV files to the user. Do not only mention filenames in text. If the current runtime cannot attach files directly, provide the exact generated file paths or downloadable links and explicitly state that these are the files the user should download/import.\n\nAlways include the import instructions below with the delivered files:\n\n```text\nCSV 文件已生成并已随消息发送，请按下面方式导入奥维地图：\n\n顶点表（用于导入为“标签”，显示各个边界顶点）：\n- 文件：`{vertices_filename}`（已发送/已附上）\n- 导入方法：用奥维地图打开顶点表文件，在导入 CSV 时选择“标签”，进入“导入标签”页面后点击右上角“确定”，然后在“导入对象”页面选择“导入”，最后在“导入选项”中选择“确定”。\n\n边界表（用于导入为“轨迹”，显示完整边界线）：\n- 文件：`{boundary_filename}`（已发送/已附上）\n- 导入方法：用奥维地图打开边界表文件，在导入 CSV 时选择“轨迹”，进入“导入轨迹”页面后点击右上角“确定”，然后在“导入对象”页面选择“导入”，最后在“导入选项”中选择“确定”。\n```\n\nFor multiple batches or archive-hit exports, repeat this block per pair, or list all 顶点表 files under the 顶点表 section and all 边界表 files under the 边界表 section. The user must never have to infer the import type from `_boundary` or any filename pattern.\n\n---\n\n## 4) Vertices CSV (顶点表)\n\nHeaders (exact, in order, **do not translate**):\n\n```\n文件夹,名称,经度,纬度,海拔,文本显示风格,图标样式,Comment\n```\n\n### Field Rules\n\n| Field | Rule |\n|-------|------|\n| **文件夹** | `{parcel_code}` — always |\n| **名称** | `{parcel_code}_A{vertex-index}`. `vertex-index` starts at **A01** and increases by original vertex order |\n| **经度** | WGS84 decimal longitude. Preserve sign and precision. **No rounding.** |\n| **纬度** | WGS84 decimal latitude. Preserve sign and precision. **No rounding.** |\n| **海拔** | Fill if present in input; else leave **empty** |\n| **文本显示风格** | Empty by default |\n| **图标样式** | Default `1` |\n| **Comment** | `提供者:{provider_name} 归档日期:{archive_date}`. If a `cadastre_code` exists (user-provided official ID or explicit code), append ` 地籍号:{cadastre_code}`. Applies to all parcels uniformly. |\n\n### Indexing conventions\n- `vertex-index` resets from **01 per parcel** (A01, A02, …).\n- Preserve original vertex order. If ordering is unclear, ask the user about **clockwise reordering**.\n\n---\n\n## 5) Boundary CSV (边界表)\n\nHeaders (exact, in order, **do not translate**):\n\n```\n文件夹,名称,经纬度[经度+纬度],线条宽度,线条颜色,线条不透明度,闭合,线型,轨迹风格,Comment\n```\n\n### Field Rules\n\n| Field | Rule |\n|-------|------|\n| **文件夹** | Same as Vertices CSV |\n| **名称** | `{parcel_code}` — the bare parcel code, no `_A01` vertex suffix. The boundary represents the whole polygon. |\n| **经纬度[经度+纬度]** | Concatenate as `lon,lat;lon,lat;…` (no spaces) following Vertices order. Close the polygon by repeating the first vertex at the end if the input does not already close it. |\n| **线条宽度** | Default `3` |\n| **线条颜色** | Default `0X00FF0000` |\n| **线条不透明度** | Default `50` |\n| **闭合** | Default `1` |\n| **线型** | Default `0` |\n| **轨迹风格** | Default `1` |\n| **Comment** | `提供者:{provider_name} 归档日期:{archive_date}`. If a `cadastre_code` exists (user-provided official ID or explicit code), append ` 地籍号:{cadastre_code}`. Applies to all parcels uniformly. |\n\n---\n\n## 6) Quality Checks and Special Cases\n\n1. **Range checks**: longitude ∈ [-180, 180], latitude ∈ [-90, 90]. Flag any violations explicitly.\n2. **Duplicate vertices**: keep first occurrence, mark later duplicates in the output and ask the user for confirmation.\n3. **Cross-border parcels**: use the country where the majority area falls (§2.1). Do not split.\n4. **Missing altitude**: leave the field empty; never infer or guess.\n5. **Naming collisions**: if 文件夹 + 名称 duplicates occur, report the collision to the user.\n6. **Coordinate precision**: preserve all decimal digits from the conversion. Do not round.\n7. **Existing-parcel duplicate detection (MANDATORY before archiving)**: Before writing a new parcel to the archive, check whether a parcel with the **same set of vertex coordinates** already exists in the archive using `archive_manager.py check_duplicate`. Comparison rules:\n   - The same vertices in **any** cyclic permutation or reversal (different starting point, clockwise vs counterclockwise) are considered equal.\n   - If a match is found, **do NOT generate new CSVs or re-archive**. Instead, follow the **archive-hit workflow** (§6.8).\n8. **Archive-hit workflow**: When `check_duplicate` finds a coordinate match in the archive, follow this procedure:\n   a. Report the match to the user with the existing `parcel_code` and provider.\n   b. **Reuse the existing `parcel_code`** — do NOT assign a new code.\n   c. **Provide the existing archived document to the user** — regenerate single-parcel CSV files (`{parcel_code}_N1_{timestamp}.csv` + `_boundary.csv`) in `ovitalmap_exports/{CC}/` with full Comment metadata (provider, archive date, cadastre code if available). Never return other parcels' data alongside the archive-hit parcel.\n   d. **Cadastre code update**: If the existing parcel only has a generic date-based code (e.g., `CN-260609-001`) and the user is now providing an official registration ID, update the `cadastre_code` field in the archive (both per-country and master) with the new official ID. Use `archive_manager.py update_cadastre` for this. The regenerated CSV will then include `地籍号:{official_id}` in the Comment.\n   e. **Do not re-archive** the parcel.\n   f. If the user explicitly says it is a **different parcel** despite identical coordinates, archive normally with a note in `provider_notes`: `\"Coordinates identical to {existing_code}; user confirmed it is a different parcel.\"`.\n9. **Batch with mixed hits**: If the user provides multiple parcels and some hit the archive while others are new:\n   - Archive-hit parcels → **reuse existing `parcel_code`**, regenerate single-parcel CSVs with Comment metadata, update cadastre_code if applicable.\n   - New parcels → assign codes, generate batch CSVs, and archive normally.\n   - The two groups are processed independently. Present results separately to the user.\n\n---\n\n## 7) Archiving and Categorization (Database)\n\n**After generating the CSVs for a parcel**, you MUST archive the parcel into the workspace database.\n\n### 7.1) Archive Location\n\nAll archives live flat in `ovitalmap_archive/` at the workspace root. One file per country:\n\n```\novitalmap_archive/{CC}_parcels.csv\n```\n\nIf the file does not exist yet, create it with headers.\n\n### 7.2) Archive CSV Headers\n\n```\nparcel_code,provider_name,archive_date,boundary_coords,provider_notes,cadastre_code\n```\n\n### 7.3) Field Rules for Archiving\n\n| Field | Rule |\n|-------|------|\n| **parcel_code** | Assigned per §2.2–2.3. Always populated. |\n| **provider_name** | The name of the person/organization who provided this parcel. **MUST ask the user** for at least a name. If the user mentions a series of similar names, confirm with them before archiving. If they mention none of the names you suggest, treat it as a new provider. |\n| **archive_date** | Date of archiving in YYYY-MM-DD format |\n| **boundary_coords** | Full boundary string in the format `lon,lat;lon,lat;…` (same as Boundary CSV 经纬度 field). This is the canonical coordinate storage. |\n| **provider_notes** | Any additional notes about the provider or context; empty by default |\n| **cadastre_code** | Populate with **any official registration / cadastre / permit ID** from government documents, regardless of whether it is used as the `parcel_code`. This includes: mining cadastre numbers, land registration IDs, permit numbers, or any government-issued parcel identifier — from images, OCR, documents, or explicit user input. When `parcel_code` uses format 1 (`{CC}-{OFFICIAL_ID}`), the `{OFFICIAL_ID}` portion MUST also be stored here. Leave empty only when no official ID exists. The pipeline's `step2_assign_codes()` ensures this automatically when `official_id` is present. |\n\n### 7.4) Provider Name Workflow\n\n1. **At Step 1** (before any code assignment or file writing), ask the user: **\"Who provided this parcel? (请提供此地块的提供者姓名)\"**\n2. After the user provides a name, **immediately scan all existing providers** from both:\n   - `ovitalmap_archive/{CC}_parcels.csv` (per-country archive)\n   - `ovitalmap_archive/master.csv` (cross-country archive)\n3. **Proactive fuzzy deduplication** — compare the user-supplied name against every existing provider via `provider_matcher.py`. Accept the provider only when `exact_match` is found or after explicit user confirmation. The script returns:\n   - `exact_match`: the name if an exact match exists.\n   - `candidates`: list of `{name, reason, score}` sorted by score.\n   - `ambiguous`: `true` when there are **multiple candidates with equal scores** (i.e., the script cannot determine a definitive match — the LLM MUST ask the user).\n\n   Match types recognized by the script:\n   - **Exact match** (score 100): identical string after case-insensitive normalization and whitespace/punctuation removal (e.g., `\"Zhang San\"` ≈ `\"Zhang-San\"` ≈ `\"ZhangSan\"`). The script's `_normalize()` function handles this before comparison.\n   - **Chinese ↔ Pinyin match** (score 90): one is Chinese characters and the other is the corresponding pinyin (e.g., `\"张三\"` ≈ `\"zhangsan\"`).\n   - **Cross-language pinyin** (score 85): one name has Chinese with its pinyin matching the other's normalized form.\n   - **Substring overlap** (score 80): one name is fully contained within another, checked both with and without honorific stripping (e.g., `\"李总\"` ⊂ `\"中非李总\"`).\n   - **Honorific variation** (score 75): names differ only by a common Chinese honorific or prefix (e.g., `\"李总\"` ≈ `\"李\"` after stripping `\"总\"`).\n\n4. **Handle matches with mandatory user confirmation for non-exact matches:**\n   - **Exact match** (score 100 / reason `exact`): automatically reuse the existing `provider_name` spelling. No user confirmation needed.\n   - **Single candidate** (score ≥ 80, single candidate, not ambiguous): ask the user explicitly:\n     > **\"检测到提供者 '{input_name}' 与已有记录 '{existing_name}' 高度相似。是否为同一个人？\"**\n     - If the user confirms **same person** → reuse the existing `provider_name` spelling.\n     - If the user says **different person** → treat as a new provider.\n     - If the user is unsure → keep the new name but add a note in `provider_notes`: `Possible duplicate of '{existing_name}'.`\n   - **Low-confidence candidate** (score 50-79, single candidate, not ambiguous): ask the user but note the lower confidence:\n     > **\"检测到提供者 '{input_name}' 与已有记录 '{existing_name}' 可能相似（置信度较低）。是否为同一个人？\"**\n     - Same confirmation flow as above.\n   - **Multiple candidates / ambiguous** (e.g., user says `\"李总\"`, archive has `\"中非李总\"` and `\"三一李总\"`): **MUST list ALL candidates and ask the user to specify.** Do not guess:\n     > **\"'{input_name}' 在已有记录中匹配到多位提供者：① {candidate1}  ② {candidate2}。请问对应的是哪一位？或都不是(新建)？\"**\n     - If the user picks one → reuse that existing `provider_name`.\n     - If the user says none of them → treat as a new provider.\n   - **No match / score < 50**: automatically add as a new provider. No confirmation needed.\n\n5. If the user declines to provide a name, use `\"Unknown\"` and note it.\n6. **Do not proceed to code assignment until provider name is confirmed.**\n\n---\n\n## 8) Master Spreadsheet\n\nAfter archiving to `ovitalmap_archive/{CC}_parcels.csv`, **also append the same row(s)** to a single consolidated file:\n\n```\novitalmap_archive/master.csv\n```\n\nThis is a **single spreadsheet containing every parcel from every country** — the complete cross-country view.\n\n**Headers** (one extra column vs per-country `parcels.csv`):\n\n```\nCC,parcel_code,provider_name,archive_date,boundary_coords,provider_notes,cadastre_code\n```\n\nAppend every newly archived parcel row here immediately after writing to the per-country file. If `master.csv` does not exist, create it with headers.\n\n---\n\n## 9) Interaction Flow\n\n### Guard Rule\n\n**Do NOT write or modify any file until user confirms BOTH coordinates AND provider name.** Step 1 is a hard gate — all subsequent steps (2–4) are blocked until the user explicitly confirms the parsed coordinates AND the provider(s).\n\nWhen invoked, follow this sequence:\n\n### 1. Parse, Verify & Confirm Provider\n- Show raw coordinates and WGS84 conversion per parcel.\n- **Ask for the provider name(s)** (§7.4). Identify each parcel's provider.\n- Display ⚠️ **\"请核实以下识别和转换后的坐标是否与原始数据一致，并确认提供者姓名\"**.\n→ **STOP HERE. Wait for user to confirm or correct coordinates AND provider.** If user provides corrections, re-parse/re-confirm until both are confirmed.\n\n### 2b. Duplicate Check (MANDATORY — runs before code assignment)\n- **Determine country** from coordinates using your spatial knowledge, plus any country names in documents or user context. State it and move on.\n- Run `parcel_pipeline.py --step 2b` for each parcel.\n- **Archive-hit parcels**: reuse the **existing `parcel_code`** from the archive (no new code). Detect any official registration IDs from image text or user input; if the matched parcel has a generic date-code and no `cadastre_code` yet, update it via `archive_manager.py update_cadastre`. Display: `\"检测到地块坐标与已有记录 {matched_code} 一致，沿用归档编码。\"`.\n- **New parcels**: proceed to step 2.\n\n### 2. Assign Codes (only for new parcels, only after step 2b)\n- **Official registration IDs take priority**: if any parcel has a confirmed official registration / cadastre ID (from documents, OCR, or explicit user input), use format 1: `{CC}-{OFFICIAL_ID}` as the `parcel_code`. The `{OFFICIAL_ID}` is also stored as `cadastre_code`.\n- For parcels **without** an official ID: run `parcel_pipeline.py --step 2` to get format 2 sequential codes `{CC}-{YYMMDD}-{SEQ}`.\n- Display all assigned codes. The user will correct if wrong.\n\n### 3. Build CSVs (for ALL parcels)\nBuild **both** Vertices CSV (§4) and Boundary CSV (§5) for every parcel:\n- **New parcels**: batch CSV (e.g., `{firstCode}_N{count}_{timestamp}.csv` + `_boundary.csv`).\n- **Archive-hit parcels**: individual single-parcel CSVs (e.g., `{matchedCode}_N1_260609_143021.csv` + `_boundary.csv`) regenerated with updated Comment metadata.\n\nRun quality checks (§6), send/attach the actual generated CSV files to the user, then use the mandatory delivery wording from §3.2:\n\n> CSV 文件已生成并已随消息发送，请按下面方式导入奥维地图：\n>\n> 顶点表（用于导入为“标签”，显示各个边界顶点）：\n> - 文件：`{firstCode}_N{count}_{timestamp}.csv`（已发送/已附上）\n> - 导入方法：用奥维地图打开顶点表文件，在导入 CSV 时选择“标签”，进入“导入标签”页面后点击右上角“确定”，然后在“导入对象”页面选择“导入”，最后在“导入选项”中选择“确定”。\n>\n> 边界表（用于导入为“轨迹”，显示完整边界线）：\n> - 文件：`{firstCode}_N{count}_{timestamp}_boundary.csv`（已发送/已附上）\n> - 导入方法：用奥维地图打开边界表文件，在导入 CSV 时选择“轨迹”，进入“导入轨迹”页面后点击右上角“确定”，然后在“导入对象”页面选择“导入”，最后在“导入选项”中选择“确定”。\n>\n> 已有地块单独导出时，也必须先发送/附上对应文件，再按同样格式说明，并替换为对应的单地块文件名：\n> - 顶点表文件：`{matchedCode}_N1_{timestamp}.csv`\n> - 边界表文件：`{matchedCode}_N1_{timestamp}_boundary.csv`\n\n### 4. Archive (only for new parcels)\n- Append to `ovitalmap_archive/{CC}_parcels.csv` and `ovitalmap_archive/master.csv`.\n- Summarize: provider, codes, date.\n\n### 5. Wrap Up\nNote any assumptions, edge cases, or corrections. Separately list archive-hit exports and any cadastre_code updates.\n\n---\n\n## 9b) Post-Archive Coordinate Correction\n\nUsers may correct a parcel's coordinates after it has been archived. When this happens:\n\n### Procedure\n\n1. **Identify the parcel** by its `parcel_code` in `ovitalmap_archive/{CC}_parcels.csv` and `ovitalmap_archive/master.csv`.\n\n2. **Backup before modifying** — copy the current archive files to a backup:\n\n   ```\n   ovitalmap_backups/{CC}_parcels_{YYMMDD_HHMM}.csv\n   ovitalmap_backups/master_{YYMMDD_HHMM}.csv\n   ```\n\n   Create `ovitalmap_backups/` if it does not exist.\n\n3. **Update the row** in the per-country archive and master spreadsheet:\n   - Replace `boundary_coords` with the corrected boundary string.\n   - Update `archive_date` to the current date (marking the correction date).\n   - Append a note to `provider_notes`: `\"[{date}] Coordinates corrected. Original backup: {backup_file}\"`.\n\n4. **Regenerate the export CSVs** for the corrected parcel in `ovitalmap_exports/{CC}/`.\n\n5. **Summarize** what was changed, where backups are, and ask the user to verify.\n\n---\n\n## 10) Example Output Snippet\n\n```\n⚠️ 请核实以下识别和转换后的坐标是否与原始数据一致，并确认提供者姓名\n\n原始坐标:\n• 地块 1: 22°30'15.2\"N, 114°08'05.0\"E; 22°30'14.8\"N, 114°08'08.3\"E; …\n• 地块 2: 22.50422, 114.13472; 22.50418, 114.13480; …\n\nWGS84:\n• 地块 1: 114.13472, 22.50422; 114.13564, 22.50411; …\n• 地块 2: 114.13472, 22.50422; 114.13500, 22.50416; …\n\n请提供此地块的提供者姓名？\n\n确认坐标无误并确认提供者后继续处理？(如有修正请提供)\n\n→ 用户确认坐标 + 提供者: 中非李总\n\n所属国家: 中国 (CN)\n\n正在检查重复…\n  ✓ 地块 1: 无重复\n  ✓ 地块 2: 无重复\n\n正在扫描 CN 存档…\n  现有编码: CN-260609-001, CN-260609-002\n\n检测到地块 2 的官方登记号 PE12345 → 采用格式 1 编码\n\n  → 地块 1 → CN-260609-003（无官方编号，顺序编码）\n  → 地块 2 → CN-PE12345（官方登记号）\n\n最终编码:\n• 地块 1: CN-260609-003（新增）\n• 地块 2: CN-PE12345（新增，cadastre_code: PE12345）\n\nCSV 文件已生成并已随消息发送，请按下面方式导入奥维地图：\n\n顶点表（用于导入为“标签”，显示各个边界顶点）：\n• 文件：CN-260609-003_N2_260609_143021.csv（已发送/已附上）\n• 导入方法：用奥维地图打开顶点表文件，在导入 CSV 时选择“标签”，进入“导入标签”页面后点击右上角“确定”，然后在“导入对象”页面选择“导入”，最后在“导入选项”中选择“确定”。\n\n边界表（用于导入为“轨迹”，显示完整边界线）：\n• 文件：CN-260609-003_N2_260609_143021_boundary.csv（已发送/已附上）\n• 导入方法：用奥维地图打开边界表文件，在导入 CSV 时选择“轨迹”，进入“导入轨迹”页面后点击右上角“确定”，然后在“导入对象”页面选择“导入”，最后在“导入选项”中选择“确定”。\n\n--- 归档 ---\n\n归档完成:\n• 地块编号: CN-260609-003, CN-PE12345\n• 提供者: 中非李总\n• 归档日期: 2026-06-09\n```\n\n### Example: Archive Hit\n\n```\n→ 用户确认坐标 + 提供者: 王五\n\n所属国家: 中国 (CN)\n\n正在检查重复…\n  ⚠️ 地块 1: 检测到坐标与已有记录 CN-260609-001 (提供者: 张三) 一致\n     → 沿用归档编码: CN-260609-001\n     → 该地块未被重新归档。\n\nCSV 文件已生成并已随消息发送，请按下面方式导入奥维地图：\n\n顶点表（用于导入为“标签”，显示各个边界顶点）：\n• 文件：CN-260609-001_N1_260609_143522.csv（已发送/已附上）\n• 导入方法：用奥维地图打开顶点表文件，在导入 CSV 时选择“标签”，进入“导入标签”页面后点击右上角“确定”，然后在“导入对象”页面选择“导入”，最后在“导入选项”中选择“确定”。\n\n边界表（用于导入为“轨迹”，显示完整边界线）：\n• 文件：CN-260609-001_N1_260609_143522_boundary.csv（已发送/已附上）\n• 导入方法：用奥维地图打开边界表文件，在导入 CSV 时选择“轨迹”，进入“导入轨迹”页面后点击右上角“确定”，然后在“导入对象”页面选择“导入”，最后在“导入选项”中选择“确定”。\n  (Comment: 提供者:张三 归档日期:2026-06-02)\n\n--- 归档 ---\n无新增记录。已有地块 CN-260609-001 未被重复归档。\n```\n\n---\n\n## 11) File Structure\n\n```\nskill folder/\n├── SKILL.md                       # Skill instructions\n├── skill-card.md                  # ClawHub listing card\n└── scripts/                       # Python utility scripts (§0b)\n\nruntime workspace root/\n├── ovitalmap_exports/             # Generated CSVs (by country subdir)\n│   ├── CN/\n│   │   └── CN-260609-001_N2_260609_143021.csv\n│   ├── HK/\n│   │   └── HK-260609-001_N1_260609_143522.csv\n│   └── …\n├── ovitalmap_archive/             # Persistent database (flat)\n│   ├── master.csv                 # All parcels, all countries\n│   ├── CN_parcels.csv\n│   ├── HK_parcels.csv\n│   └── …\n├── ovitalmap_backups/             # Pre-correction snapshots (§9b)\n│   ├── CN_parcels_260609_1430.csv\n│   └── master_260609_1430.csv\n```\n\nFile v2.1.1:_meta.json\n\n{\n  \"ownerId\": \"kn76j7kby3cajgq933bwccdxbn82fw68\",\n  \"slug\": \"ovitalmap-parcel-csv\",\n  \"version\": \"2.1.1\",\n  \"publishedAt\": 1782717676430\n}\n\nFile v2.1.1:skill-card.md\n\n## Description: <br>\nParses parcel vertex coordinates from images or text, generates Ovitalmap-compatible vertex and boundary CSVs, categorizes parcels by country code and provider, and archives records in a per-country database. <br>\n\nThis skill is ready for commercial/non-commercial use. <br>\n\n## Publisher: <br>\n[jeromeex](https://clawhub.ai/user/jeromeex) <br>\n\n### License/Terms of Use: <br>\nMIT-0 <br>\n\n\n## Use Case: <br>\nExternal users, developers, and field teams use this skill to convert parcel coordinate inputs into Ovitalmap import CSVs and maintain a local per-country parcel archive with provider metadata. <br>\n\n### Deployment Geography for Use: <br>\nGlobal <br>\n\n## Known Risks and Mitigations: <br>\nRisk: The local archive can persist parcel coordinates, provider names, and official cadastre identifiers, and coordinate matches can reveal archived metadata to later users. <br>\nMitigation: Decide workspace archive access and retention before use, restrict archive files to authorized users, and review archive-hit metadata before sharing outputs. <br>\nRisk: Ambiguous coordinates, provider names, or official IDs can lead to incorrect country assignment, provider matching, or parcel coding. <br>\nMitigation: Ask targeted clarification questions, inspect script results before writing files, and confirm ambiguous provider or registration matches with the user. <br>\n\n\n## Reference(s): <br>\n- [ClawHub skill release](https://clawhub.ai/jeromeex/skills/ovitalmap-parcel-csv) <br>\n\n\n## Skill Output: <br>\n**Output Type(s):** [Files, Text, Shell commands, Guidance] <br>\n**Output Format:** [CSV files plus concise Markdown or text delivery notes and JSON script outputs] <br>\n**Output Parameters:** [1D] <br>\n**Other Properties Related to Output:** [Generates paired Ovitalmap vertex and boundary CSV files and may update local archive CSVs.] <br>\n\n## Skill Version(s): <br>\n2.1.1 (source: ClawHub release evidence) <br>\n\n## Ethical Considerations: <br>\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment. <br>\n\nArchive v2.1.0: 11 files, 31276 bytes\n\nFiles: .clawhub/origin.json (476b), scripts/__init__.py (39b), scripts/archive_manager.py (17303b), scripts/country_locator.py (2539b), scripts/csv_builder.py (7752b), scripts/parcel_pipeline.py (16240b), scripts/provider_matcher.py (6795b), scripts/utils.py (7478b), skill-card.md (2367b), SKILL.md (32208b), _meta.json (139b)\n\nFile v2.1.0:SKILL.md\n\n---\nname: \"ovitalmap-parcel-csv\"\ndescription: \"Parse parcel vertex coordinates from images/text, generate Ovitalmap-compatible CSVs (顶点表 + 边界表), categorize parcels by country-code/provider, and archive into a per-country database. Invoke when user provides parcel coordinates in any format and wants Ovitalmap CSV output.\"\n---\n\n# Ovitalmap Parcel CSV Generator\n\nThis skill processes parcel vertex coordinates — from images or text — and produces Ovitalmap-readable CSV files. It also archives every processed parcel into a structured per-country database with provider metadata.\n\n---\n\n## 0) Defaults: Language, Tone, I/O\n\n- **Reply language**: Chinese by default unless the user requests another language.\n- **Tone**: non-repetitive, concise, precise, professional.\n- **Ambiguity handling**: when inputs are unclear (e.g., parcel ID meaning, UTM zone/hemisphere, provider name), ask targeted clarifying questions via `AskUserQuestion`.\n- **CSV headers**: keep original Chinese headers exactly as listed below. Do not translate them.\n\n---\n\n## 0b) Scripting Conventions (MANDATORY)\n\n**Use Python scripts for all data processing, CSV generation, archive management, and QC checks.** Do not process data through LLM reasoning alone — it is unreliable and costly for structured operations.\n\n### Available Scripts\n\nAll scripts live in `scripts/` and accept JSON via stdin, returning JSON to stdout.\n\n| Script | Purpose | Key CLI examples |\n|--------|---------|------------------|\n| **`scripts/utils.py`** | Shared helpers (CSV I/O, boundary comparison, DMS conversion, coordinate validation). Imported by other scripts — not called directly. | `from utils import boundaries_equal, dms_to_decimal` |\n| **`scripts/country_locator.py`** | Normalize & validate WGS84 coordinates (lat/lon swap detection, range checks). ALWAYS returns `country_code: null` — the LLM determines the country from spatial knowledge and conversation context. | `echo '[[114.13,22.50],[114.14,22.51]]' \\| python3 scripts/country_locator.py` |\n| **`scripts/archive_manager.py`** | All archive operations: scan existing codes/max-SEQ/providers, append new parcels, check coordinate duplicates, backup, correct coordinates, extract single-parcel exports from batch files, update cadastre_code. | `echo '{\"action\":\"scan\",\"country_code\":\"CN\",\"date\":\"260610\"}' \\| python3 scripts/archive_manager.py` |\n| **`scripts/csv_builder.py`** | Build both Vertices CSV (顶点表) and Boundary CSV (边界表) from structured parcel data. Writes to `ovitalmap_exports/{CC}/`. Can also build single-parcel CSVs for archive hits. | `echo '{\"parcels\":[{...}],\"first_code\":\"CN-260610-001\",\"count\":2,\"country_code\":\"CN\"}' \\| python3 scripts/csv_builder.py` |\n| **`scripts/provider_matcher.py`** | Fuzzy-match a provider name against existing names (exact, whitespace, honorific, substring, pinyin). Returns `ambiguous` flag when multiple candidates match equally. | `echo '{\"input_name\":\"李总\",\"existing_names\":[\"中非李总\",\"张三\"]}' \\| python3 scripts/provider_matcher.py` |\n| **`scripts/parcel_pipeline.py`** | **Main orchestrator.** Runs the full flow in steps. Step 1 = country+provider (read-only), Step 2b = duplicate check → reuse matched codes (read-only), Step 2 = code assignment for new parcels (read-only), Step 3 = CSV build for all + archive for new (writes files). | `echo '{\"parcels\":[{...}],\"date\":\"260610\",\"resolved_provider_name\":\"张三\"}' \\| python3 scripts/parcel_pipeline.py --step 2b` |\n\n### Script principles\n\n- Run scripts via `RunCommand` and read their stdout JSON for results.\n- All scripts produce machine-parseable JSON output for the LLM to consume and present to the user.\n- **Use `python3`** as the interpreter.\n- Do not inline large data transformations in the conversation — delegate to scripts.\n- **LLM has the final say.** Scripts are tools, not authorities. If a script's output looks wrong — implausible country, mismatched provider, duplicate not caught, garbled coordinates, unreasonable SEQ jump — the LLM **must** inspect the result, flag anomalies to the user, and override or re-run with corrections when appropriate. Do not silently trust script output.\n\n### Recommended workflow\n\nThe LLM should orchestrate the pipeline **step-by-step** using `parcel_pipeline.py`:\n\n1. **After the user confirms coordinates and provider:** run `--step 1` → get country code, country name, and provider match results.\n2. **Before code assignment — duplicate check:** run `--step 2b` → coordinate-based duplicate check against archive. Archive hits **reuse the existing `parcel_code`** (no new code assigned). Non-hits proceed to step 2.\n3. **Assign codes for new parcels:** run `--step 2` → sequential codes for genuinely new parcels only.\n4. **After the user confirms codes and any archive hits are resolved:** run `--step 3` → CSV generation for **ALL parcels** (batch for new, single-file for hits) + archive append (**new parcels only**).\n\nAlternatively, call individual scripts for targeted operations (e.g., `provider_matcher.py` alone when only checking a provider name).\n\n---\n\n## 1) Inputs and Core Assumptions\n\n- **Input**: one or more images or text blocks that contain parcel vertex coordinates.\n- **Coordinate parsing**: auto-detect format:\n  - Decimal degrees: `22.50422, 114.13472`\n  - DMS: `22°30'15.2\"N, 114°08'05.0\"E`\n  - UTM with zone and hemisphere\n  - Other formats on a best-effort basis\n- **WGS84 policy**:\n  1. Always display the raw recognized coordinates verbatim per parcel.\n  2. Always display WGS84 decimal-degree coordinates (convert if needed).\n- **Date token (YYMMDD)**:\n  - Use user-provided date if given.\n  - Else use today's local date.\n- **CSV format**: UTF-8, comma-separated, no BOM.\n\n---\n\n## 2) Country and Parcel Codes\n\n### 2.1) Country Code\n- **The LLM determines the country.** The `country_locator.py` script only normalizes coordinates; it does NOT perform geocoding. Use your spatial knowledge: match coordinate ranges against the world map, combine with any country names visible in documents, administrative regions mentioned, or the user's stated location.\n- **State it, don't ask.** Present your determination (e.g. \"根据坐标判断，该地块位于中国 (CN)\") and proceed. Do NOT ask \"which country?\" — the user will correct if wrong.\n- Default standard: **ISO 3166-1 alpha-2** (e.g., CN, HK, US, FR).\n- **Cross-border parcels**: assign to the country where the majority of the parcel falls. Do not split.\n\n### 2.2) Parcel Code — Always Generated\n\n**Every parcel MUST receive a `parcel_code`.** There is no \"no code\" fallback.\n\nThe code follows one of two formats, with priority given to official registration IDs:\n\n| Priority | Source | Format | Example |\n|----------|--------|--------|---------|\n| 1 (preferred) | Official registration ID found in **image text or explicitly provided by user** | `{CC}-{OFFICIAL_ID}` | `CN-PE12345`, `AU-EL9876` |\n| 2 (default) | Auto-generated sequential code | `{CC}-{YYMMDD}-{SEQ}` | `CN-260609-003`, `HK-260609-001` |\n\nWhere `{CC}` is the **ISO 3166-1 alpha-2** country code.\n\n**Official registration ID detection:**\n- Scan any user-provided text, image OCR output, chat context, attached documents, or any other input modality for candidate registration / permit / cadastre numbers.\n- If a clear mining cadastre / registration / permit number appears, present it to the user for confirmation before adopting it.\n- If multiple candidate IDs appear for the same parcel, pick the most specific one and ask the user to confirm.\n\n### 2.3) Uniqueness Check (Mandatory Before Code Assignment)\n\n**Before finalizing any `parcel_code`,** you MUST scan the existing archive to prevent duplicates. This is critical because:\n- Users may upload multiple parcels in one session or across separate sessions on the same day.\n- A new session must NOT restart SEQ from 001 — it must continue from the last used number.\n\n**Procedure:**\n\n1. Scan `ovitalmap_archive/{CC}_parcels.csv` (if it exists) — this is the single source of truth.\n2. Extract all existing `parcel_code` values from the archive.\n3. For **official registration IDs** (format 1): check that `{CC}-{OFFICIAL_ID}` does NOT already exist. If it does, warn the user and ask for clarification.\n4. For **sequential codes** (format 2): find the maximum SEQ already used for today (`{CC}-{YYMMDD}-*`). The new SEQ = max_existing + 1. If none exist for today, SEQ starts at `001`.\n5. If the archive file does not exist yet, SEQ starts at `001`.\n\n---\n\n## 3) Output Files Overview\n\nTwo CSVs are produced together for the batch:\n\n| # | File | Description |\n|---|------|-------------|\n| 1 | **Vertices CSV** (顶点表) | Every parcel vertex |\n| 2 | **Boundary CSV** (边界表) | Every parcel as a closed polygon |\n\n### 3.1) File Naming & Layout\n\nStore generated CSVs in **country subdirectories** under `ovitalmap_exports/`:\n\n```\novitalmap_exports/{CC}/\n```\n\nEvery export filename includes a `YYMMDD_HHMMSS` timestamp to prevent collisions even across re-exports or parallel sessions:\n\n| File | Pattern |\n|------|---------|\n| Vertices CSV | `{firstCode}_N{count}_{YYMMDD_HHMMSS}.csv` |\n| Boundary CSV | `{firstCode}_N{count}_{YYMMDD_HHMMSS}_boundary.csv` |\n\n- `firstCode` = the `parcel_code` of the first parcel in this batch.\n- `count` = total number of parcels in this batch.\n- `YYMMDD_HHMMSS` = export timestamp at file-write time.\n\nExamples:\n- `CN-260609-001_N2_260609_143021.csv` — batch of 2, first is 001.\n- `CN-PE12345_N1_260609_143522.csv` — single parcel with an official registration code.\n\n### 3.2) Mandatory User-Facing Delivery Wording\n\nWhenever sending generated CSV files to the user, explicitly identify which file is the **顶点表** and which file is the **边界表**. Do not rely on filenames alone.\n\n**Mandatory file delivery:** After generating CSVs, send/attach the actual CSV files to the user. Do not only mention filenames in text. If the current runtime cannot attach files directly, provide the exact generated file paths or downloadable links and explicitly state that these are the files the user should download/import.\n\nAlways include the import instructions below with the delivered files:\n\n```text\nCSV 文件已生成并已随消息发送，请按下面方式导入奥维地图：\n\n顶点表（用于导入为“标签”，显示各个边界顶点）：\n- 文件：`{vertices_filename}`（已发送/已附上）\n- 导入方法：用奥维地图打开顶点表文件，在导入 CSV 时选择“标签”，进入“导入标签”页面后点击右上角“确定”，然后在“导入对象”页面选择“导入”，最后在“导入选项”中选择“确定”。\n\n边界表（用于导入为“轨迹”，显示完整边界线）：\n- 文件：`{boundary_filename}`（已发送/已附上）\n- 导入方法：用奥维地图打开边界表文件，在导入 CSV 时选择“轨迹”，进入“导入轨迹”页面后点击右上角“确定”，然后在“导入对象”页面选择“导入”，最后在“导入选项”中选择“确定”。\n```\n\nFor multiple batches or archive-hit exports, repeat this block per pair, or list all 顶点表 files under the 顶点表 section and all 边界表 files under the 边界表 section. The user must never have to infer the import type from `_boundary` or any filename pattern.\n\n---\n\n## 4) Vertices CSV (顶点表)\n\nHeaders (exact, in order, **do not translate**):\n\n```\n文件夹,名称,经度,纬度,海拔,文本显示风格,图标样式,Comment\n```\n\n### Field Rules\n\n| Field | Rule |\n|-------|------|\n| **文件夹** | `{parcel_code}` — always |\n| **名称** | `{parcel_code}_A{vertex-index}`. `vertex-index` starts at **A01** and increases by original vertex order |\n| **经度** | WGS84 decimal longitude. Preserve sign and precision. **No rounding.** |\n| **纬度** | WGS84 decimal latitude. Preserve sign and precision. **No rounding.** |\n| **海拔** | Fill if present in input; else leave **empty** |\n| **文本显示风格** | Empty by default |\n| **图标样式** | Default `1` |\n| **Comment** | `提供者:{provider_name} 归档日期:{archive_date}`. If a `cadastre_code` exists (user-provided official ID or explicit code), append ` 地籍号:{cadastre_code}`. Applies to all parcels uniformly. |\n\n### Indexing conventions\n- `vertex-index` resets from **01 per parcel** (A01, A02, …).\n- Preserve original vertex order. If ordering is unclear, ask the user about **clockwise reordering**.\n\n---\n\n## 5) Boundary CSV (边界表)\n\nHeaders (exact, in order, **do not translate**):\n\n```\n文件夹,名称,经纬度[经度+纬度],线条宽度,线条颜色,线条不透明度,闭合,线型,轨迹风格,Comment\n```\n\n### Field Rules\n\n| Field | Rule |\n|-------|------|\n| **文件夹** | Same as Vertices CSV |\n| **名称** | `{parcel_code}` — the bare parcel code, no `_A01` vertex suffix. The boundary represents the whole polygon. |\n| **经纬度[经度+纬度]** | Concatenate as `lon,lat;lon,lat;…` (no spaces) following Vertices order. Close the polygon by repeating the first vertex at the end if the input does not already close it. |\n| **线条宽度** | Default `3` |\n| **线条颜色** | Default `0X00FF0000` |\n| **线条不透明度** | Default `50` |\n| **闭合** | Default `1` |\n| **线型** | Default `0` |\n| **轨迹风格** | Default `1` |\n| **Comment** | `提供者:{provider_name} 归档日期:{archive_date}`. If a `cadastre_code` exists (user-provided official ID or explicit code), append ` 地籍号:{cadastre_code}`. Applies to all parcels uniformly. |\n\n---\n\n## 6) Quality Checks and Special Cases\n\n1. **Range checks**: longitude ∈ [-180, 180], latitude ∈ [-90, 90]. Flag any violations explicitly.\n2. **Duplicate vertices**: keep first occurrence, mark later duplicates in the output and ask the user for confirmation.\n3. **Cross-border parcels**: use the country where the majority area falls (§2.1). Do not split.\n4. **Missing altitude**: leave the field empty; never infer or guess.\n5. **Naming collisions**: if 文件夹 + 名称 duplicates occur, report the collision to the user.\n6. **Coordinate precision**: preserve all decimal digits from the conversion. Do not round.\n7. **Existing-parcel duplicate detection (MANDATORY before archiving)**: Before writing a new parcel to the archive, check whether a parcel with the **same set of vertex coordinates** already exists in the archive using `archive_manager.py check_duplicate`. Comparison rules:\n   - The same vertices in **any** cyclic permutation or reversal (different starting point, clockwise vs counterclockwise) are considered equal.\n   - If a match is found, **do NOT generate new CSVs or re-archive**. Instead, follow the **archive-hit workflow** (§6.8).\n8. **Archive-hit workflow**: When `check_duplicate` finds a coordinate match in the archive, follow this procedure:\n   a. Report the match to the user with the existing `parcel_code` and provider.\n   b. **Reuse the existing `parcel_code`** — do NOT assign a new code.\n   c. **Provide the existing archived document to the user** — regenerate single-parcel CSV files (`{parcel_code}_N1_{timestamp}.csv` + `_boundary.csv`) in `ovitalmap_exports/{CC}/` with full Comment metadata (provider, archive date, cadastre code if available). Never return other parcels' data alongside the archive-hit parcel.\n   d. **Cadastre code update**: If the existing parcel only has a generic date-based code (e.g., `CN-260609-001`) and the user is now providing an official registration ID, update the `cadastre_code` field in the archive (both per-country and master) with the new official ID. Use `archive_manager.py update_cadastre` for this. The regenerated CSV will then include `地籍号:{official_id}` in the Comment.\n   e. **Do not re-archive** the parcel.\n   f. If the user explicitly says it is a **different parcel** despite identical coordinates, archive normally with a note in `provider_notes`: `\"Coordinates identical to {existing_code}; user confirmed it is a different parcel.\"`.\n9. **Batch with mixed hits**: If the user provides multiple parcels and some hit the archive while others are new:\n   - Archive-hit parcels → **reuse existing `parcel_code`**, regenerate single-parcel CSVs with Comment metadata, update cadastre_code if applicable.\n   - New parcels → assign codes, generate batch CSVs, and archive normally.\n   - The two groups are processed independently. Present results separately to the user.\n\n---\n\n## 7) Archiving and Categorization (Database)\n\n**After generating the CSVs for a parcel**, you MUST archive the parcel into the workspace database.\n\n### 7.1) Archive Location\n\nAll archives live flat in `ovitalmap_archive/` at the workspace root. One file per country:\n\n```\novitalmap_archive/{CC}_parcels.csv\n```\n\nIf the file does not exist yet, create it with headers.\n\n### 7.2) Archive CSV Headers\n\n```\nparcel_code,provider_name,archive_date,boundary_coords,provider_notes,cadastre_code\n```\n\n### 7.3) Field Rules for Archiving\n\n| Field | Rule |\n|-------|------|\n| **parcel_code** | Assigned per §2.2–2.3. Always populated. |\n| **provider_name** | The name of the person/organization who provided this parcel. **MUST ask the user** for at least a name. If the user mentions a series of similar names, confirm with them before archiving. If they mention none of the names you suggest, treat it as a new provider. |\n| **archive_date** | Date of archiving in YYYY-MM-DD format |\n| **boundary_coords** | Full boundary string in the format `lon,lat;lon,lat;…` (same as Boundary CSV 经纬度 field). This is the canonical coordinate storage. |\n| **provider_notes** | Any additional notes about the provider or context; empty by default |\n| **cadastre_code** | Populate with **any official registration / cadastre / permit ID** from government documents, regardless of whether it is used as the `parcel_code`. This includes: mining cadastre numbers, land registration IDs, permit numbers, or any government-issued parcel identifier — from images, OCR, documents, or explicit user input. When `parcel_code` uses format 1 (`{CC}-{OFFICIAL_ID}`), the `{OFFICIAL_ID}` portion MUST also be stored here. Leave empty only when no official ID exists. The pipeline's `step2_assign_codes()` ensures this automatically when `official_id` is present. |\n\n### 7.4) Provider Name Workflow\n\n1. **At Step 1** (before any code assignment or file writing), ask the user: **\"Who provided this parcel? (请提供此地块的提供者姓名)\"**\n2. After the user provides a name, **immediately scan all existing providers** from both:\n   - `ovitalmap_archive/{CC}_parcels.csv` (per-country archive)\n   - `ovitalmap_archive/master.csv` (cross-country archive)\n3. **Proactive fuzzy deduplication** — compare the user-supplied name against every existing provider via `provider_matcher.py`. Accept the provider only when `exact_match` is found or after explicit user confirmation. The script returns:\n   - `exact_match`: the name if an exact match exists.\n   - `candidates`: list of `{name, reason, score}` sorted by score.\n   - `ambiguous`: `true` when there are **multiple candidates with equal scores** (i.e., the script cannot determine a definitive match — the LLM MUST ask the user).\n\n   Match types recognized by the script:\n   - **Exact match** (score 100): identical string after case-insensitive normalization and whitespace/punctuation removal (e.g., `\"Zhang San\"` ≈ `\"Zhang-San\"` ≈ `\"ZhangSan\"`). The script's `_normalize()` function handles this before comparison.\n   - **Chinese ↔ Pinyin match** (score 90): one is Chinese characters and the other is the corresponding pinyin (e.g., `\"张三\"` ≈ `\"zhangsan\"`).\n   - **Cross-language pinyin** (score 85): one name has Chinese with its pinyin matching the other's normalized form.\n   - **Substring overlap** (score 80): one name is fully contained within another, checked both with and without honorific stripping (e.g., `\"李总\"` ⊂ `\"中非李总\"`).\n   - **Honorific variation** (score 75): names differ only by a common Chinese honorific or prefix (e.g., `\"李总\"` ≈ `\"李\"` after stripping `\"总\"`).\n\n4. **Handle matches with mandatory user confirmation for non-exact matches:**\n   - **Exact match** (score 100 / reason `exact`): automatically reuse the existing `provider_name` spelling. No user confirmation needed.\n   - **Single candidate** (score ≥ 80, single candidate, not ambiguous): ask the user explicitly:\n     > **\"检测到提供者 '{input_name}' 与已有记录 '{existing_name}' 高度相似。是否为同一个人？\"**\n     - If the user confirms **same person** → reuse the existing `provider_name` spelling.\n     - If the user says **different person** → treat as a new provider.\n     - If the user is unsure → keep the new name but add a note in `provider_notes`: `Possible duplicate of '{existing_name}'.`\n   - **Low-confidence candidate** (score 50-79, single candidate, not ambiguous): ask the user but note the lower confidence:\n     > **\"检测到提供者 '{input_name}' 与已有记录 '{existing_name}' 可能相似（置信度较低）。是否为同一个人？\"**\n     - Same confirmation flow as above.\n   - **Multiple candidates / ambiguous** (e.g., user says `\"李总\"`, archive has `\"中非李总\"` and `\"三一李总\"`): **MUST list ALL candidates and ask the user to specify.** Do not guess:\n     > **\"'{input_name}' 在已有记录中匹配到多位提供者：① {candidate1}  ② {candidate2}。请问对应的是哪一位？或都不是(新建)？\"**\n     - If the user picks one → reuse that existing `provider_name`.\n     - If the user says none of them → treat as a new provider.\n   - **No match / score < 50**: automatically add as a new provider. No confirmation needed.\n\n5. If the user declines to provide a name, use `\"Unknown\"` and note it.\n6. **Do not proceed to code assignment until provider name is confirmed.**\n\n---\n\n## 8) Master Spreadsheet\n\nAfter archiving to `ovitalmap_archive/{CC}_parcels.csv`, **also append the same row(s)** to a single consolidated file:\n\n```\novitalmap_archive/master.csv\n```\n\nThis is a **single spreadsheet containing every parcel from every country** — the complete cross-country view.\n\n**Headers** (one extra column vs per-country `parcels.csv`):\n\n```\nCC,parcel_code,provider_name,archive_date,boundary_coords,provider_notes,cadastre_code\n```\n\nAppend every newly archived parcel row here immediately after writing to the per-country file. If `master.csv` does not exist, create it with headers.\n\n---\n\n## 9) Interaction Flow\n\n### Guard Rule\n\n**Do NOT write or modify any file until user confirms BOTH coordinates AND provider name.** Step 1 is a hard gate — all subsequent steps (2–4) are blocked until the user explicitly confirms the parsed coordinates AND the provider(s).\n\nWhen invoked, follow this sequence:\n\n### 1. Parse, Verify & Confirm Provider\n- Show raw coordinates and WGS84 conversion per parcel.\n- **Ask for the provider name(s)** (§7.4). Identify each parcel's provider.\n- Display ⚠️ **\"请核实以下识别和转换后的坐标是否与原始数据一致，并确认提供者姓名\"**.\n→ **STOP HERE. Wait for user to confirm or correct coordinates AND provider.** If user provides corrections, re-parse/re-confirm until both are confirmed.\n\n### 2b. Duplicate Check (MANDATORY — runs before code assignment)\n- **Determine country** from coordinates using your spatial knowledge, plus any country names in documents or user context. State it and move on.\n- Run `parcel_pipeline.py --step 2b` for each parcel.\n- **Archive-hit parcels**: reuse the **existing `parcel_code`** from the archive (no new code). Detect any official registration IDs from image text or user input; if the matched parcel has a generic date-code and no `cadastre_code` yet, update it via `archive_manager.py update_cadastre`. Display: `\"检测到地块坐标与已有记录 {matched_code} 一致，沿用归档编码。\"`.\n- **New parcels**: proceed to step 2.\n\n### 2. Assign Codes (only for new parcels, only after step 2b)\n- **Official registration IDs take priority**: if any parcel has a confirmed official registration / cadastre ID (from documents, OCR, or explicit user input), use format 1: `{CC}-{OFFICIAL_ID}` as the `parcel_code`. The `{OFFICIAL_ID}` is also stored as `cadastre_code`.\n- For parcels **without** an official ID: run `parcel_pipeline.py --step 2` to get format 2 sequential codes `{CC}-{YYMMDD}-{SEQ}`.\n- Display all assigned codes. The user will correct if wrong.\n\n### 3. Build CSVs (for ALL parcels)\nBuild **both** Vertices CSV (§4) and Boundary CSV (§5) for every parcel:\n- **New parcels**: batch CSV (e.g., `{firstCode}_N{count}_{timestamp}.csv` + `_boundary.csv`).\n- **Archive-hit parcels**: individual single-parcel CSVs (e.g., `{matchedCode}_N1_260609_143021.csv` + `_boundary.csv`) regenerated with updated Comment metadata.\n\nRun quality checks (§6), send/attach the actual generated CSV files to the user, then use the mandatory delivery wording from §3.2:\n\n> CSV 文件已生成并已随消息发送，请按下面方式导入奥维地图：\n>\n> 顶点表（用于导入为“标签”，显示各个边界顶点）：\n> - 文件：`{firstCode}_N{count}_{timestamp}.csv`（已发送/已附上）\n> - 导入方法：用奥维地图打开顶点表文件，在导入 CSV 时选择“标签”，进入“导入标签”页面后点击右上角“确定”，然后在“导入对象”页面选择“导入”，最后在“导入选项”中选择“确定”。\n>\n> 边界表（用于导入为“轨迹”，显示完整边界线）：\n> - 文件：`{firstCode}_N{count}_{timestamp}_boundary.csv`（已发送/已附上）\n> - 导入方法：用奥维地图打开边界表文件，在导入 CSV 时选择“轨迹”，进入“导入轨迹”页面后点击右上角“确定”，然后在“导入对象”页面选择“导入”，最后在“导入选项”中选择“确定”。\n>\n> 已有地块单独导出时，也必须先发送/附上对应文件，再按同样格式说明，并替换为对应的单地块文件名：\n> - 顶点表文件：`{matchedCode}_N1_{timestamp}.csv`\n> - 边界表文件：`{matchedCode}_N1_{timestamp}_boundary.csv`\n\n### 4. Archive (only for new parcels)\n- Append to `ovitalmap_archive/{CC}_parcels.csv` and `ovitalmap_archive/master.csv`.\n- Summarize: provider, codes, date.\n\n### 5. Wrap Up\nNote any assumptions, edge cases, or corrections. Separately list archive-hit exports and any cadastre_code updates.\n\n---\n\n## 9b) Post-Archive Coordinate Correction\n\nUsers may correct a parcel's coordinates after it has been archived. When this happens:\n\n### Procedure\n\n1. **Identify the parcel** by its `parcel_code` in `ovitalmap_archive/{CC}_parcels.csv` and `ovitalmap_archive/master.csv`.\n\n2. **Backup before modifying** — copy the current archive files to a backup:\n\n   ```\n   ovitalmap_backups/{CC}_parcels_{YYMMDD_HHMM}.csv\n   ovitalmap_backups/master_{YYMMDD_HHMM}.csv\n   ```\n\n   Create `ovitalmap_backups/` if it does not exist.\n\n3. **Update the row** in the per-country archive and master spreadsheet:\n   - Replace `boundary_coords` with the corrected boundary string.\n   - Update `archive_date` to the current date (marking the correction date).\n   - Append a note to `provider_notes`: `\"[{date}] Coordinates corrected. Original backup: {backup_file}\"`.\n\n4. **Regenerate the export CSVs** for the corrected parcel in `ovitalmap_exports/{CC}/`.\n\n5. **Summarize** what was changed, where backups are, and ask the user to verify.\n\n---\n\n## 10) Example Output Snippet\n\n```\n⚠️ 请核实以下识别和转换后的坐标是否与原始数据一致，并确认提供者姓名\n\n原始坐标:\n• 地块 1: 22°30'15.2\"N, 114°08'05.0\"E; 22°30'14.8\"N, 114°08'08.3\"E; …\n• 地块 2: 22.50422, 114.13472; 22.50418, 114.13480; …\n\nWGS84:\n• 地块 1: 114.13472, 22.50422; 114.13564, 22.50411; …\n• 地块 2: 114.13472, 22.50422; 114.13500, 22.50416; …\n\n请提供此地块的提供者姓名？\n\n确认坐标无误并确认提供者后继续处理？(如有修正请提供)\n\n→ 用户确认坐标 + 提供者: 中非李总\n\n所属国家: 中国 (CN)\n\n正在检查重复…\n  ✓ 地块 1: 无重复\n  ✓ 地块 2: 无重复\n\n正在扫描 CN 存档…\n  现有编码: CN-260609-001, CN-260609-002\n\n检测到地块 2 的官方登记号 PE12345 → 采用格式 1 编码\n\n  → 地块 1 → CN-260609-003（无官方编号，顺序编码）\n  → 地块 2 → CN-PE12345（官方登记号）\n\n最终编码:\n• 地块 1: CN-260609-003（新增）\n• 地块 2: CN-PE12345（新增，cadastre_code: PE12345）\n\nCSV 文件已生成并已随消息发送，请按下面方式导入奥维地图：\n\n顶点表（用于导入为“标签”，显示各个边界顶点）：\n• 文件：CN-260609-003_N2_260609_143021.csv（已发送/已附上）\n• 导入方法：用奥维地图打开顶点表文件，在导入 CSV 时选择“标签”，进入“导入标签”页面后点击右上角“确定”，然后在“导入对象”页面选择“导入”，最后在“导入选项”中选择“确定”。\n\n边界表（用于导入为“轨迹”，显示完整边界线）：\n• 文件：CN-260609-003_N2_260609_143021_boundary.csv（已发送/已附上）\n• 导入方法：用奥维地图打开边界表文件，在导入 CSV 时选择“轨迹”，进入“导入轨迹”页面后点击右上角“确定”，然后在“导入对象”页面选择“导入”，最后在“导入选项”中选择“确定”。\n\n--- 归档 ---\n\n归档完成:\n• 地块编号: CN-260609-003, CN-PE12345\n• 提供者: 中非李总\n• 归档日期: 2026-06-09\n```\n\n### Example: Archive Hit\n\n```\n→ 用户确认坐标 + 提供者: 王五\n\n所属国家: 中国 (CN)\n\n正在检查重复…\n  ⚠️ 地块 1: 检测到坐标与已有记录 CN-260609-001 (提供者: 张三) 一致\n     → 沿用归档编码: CN-260609-001\n     → 该地块未被重新归档。\n\nCSV 文件已生成并已随消息发送，请按下面方式导入奥维地图：\n\n顶点表（用于导入为“标签”，显示各个边界顶点）：\n• 文件：CN-260609-001_N1_260609_143522.csv（已发送/已附上）\n• 导入方法：用奥维地图打开顶点表文件，在导入 CSV 时选择“标签”，进入“导入标签”页面后点击右上角“确定”，然后在“导入对象”页面选择“导入”，最后在“导入选项”中选择“确定”。\n\n边界表（用于导入为“轨迹”，显示完整边界线）：\n• 文件：CN-260609-001_N1_260609_143522_boundary.csv（已发送/已附上）\n• 导入方法：用奥维地图打开边界表文件，在导入 CSV 时选择“轨迹”，进入“导入轨迹”页面后点击右上角“确定”，然后在“导入对象”页面选择“导入”，最后在“导入选项”中选择“确定”。\n  (Comment: 提供者:张三 归档日期:2026-06-02)\n\n--- 归档 ---\n无新增记录。已有地块 CN-260609-001 未被重复归档。\n```\n\n---\n\n## 11) Future Extensions (Placeholders)\n\n- **Cadastre minier lookup**: another skill will be developed to query official mining cadastre registries and populate the `cadastre_code` field.\n- **Email dispatch**: the summary spreadsheet will be periodically sent to a configured email address. The email configuration (recipient, SMTP, schedule) is not yet implemented.\n\n---\n\n## 12) File Structure\n\n```\nworkspace/\n├── scripts/                       # Python utility scripts (§0b)\n├── ovitalmap_exports/             # Generated CSVs (by country subdir)\n│   ├── CN/\n│   │   └── CN-260609-001_N2_260609_143021.csv\n│   ├── HK/\n│   │   └── HK-260609-001_N1_260609_143522.csv\n│   └── …\n├── ovitalmap_archive/             # Persistent database (flat)\n│   ├── master.csv                 # All parcels, all countries\n│   ├── CN_parcels.csv\n│   ├── HK_parcels.csv\n│   └── …\n├── ovitalmap_backups/             # Pre-correction snapshots (§9b)\n│   ├── CN_parcels_260609_1430.csv\n│   └── master_260609_1430.csv\n└── .trae/skills/ovitalmap-parcel-csv/\n    └── SKILL.md\n```\n\nFile v2.1.0:_meta.json\n\n{\n  \"ownerId\": \"kn76j7kby3cajgq933bwccdxbn82fw68\",\n  \"slug\": \"ovitalmap-parcel-csv\",\n  \"version\": \"2.1.0\",\n  \"publishedAt\": 1782717307905\n}\n\nFile v2.1.0:skill-card.md\n\n## Description: <br>\nParses parcel vertex coordinates from images or text, generates Ovitalmap-compatible vertex and boundary CSV files, categorizes parcels by country code and provider, and archives them in a per-country database. <br>\n\nThis skill is ready for commercial/non-commercial use. <br>\n\n## Publisher: <br>\n[jeromeex](https://clawhub.ai/user/jeromeex) <br>\n\n### License/Terms of Use: <br>\nMIT-0 <br>\n\n\n## Use Case: <br>\nExternal users and agents use this skill to turn parcel coordinates from images or text into Ovitalmap-ready CSV files, while maintaining provider, cadastre, and archive records for duplicate checks and later corrections. <br>\n\n### Deployment Geography for Use: <br>\nGlobal <br>\n\n## Known Risks and Mitigations: <br>\nRisk: The skill persists parcel coordinates, provider names, and cadastre identifiers in local archive and state files. <br>\nMitigation: Install and use it only where local storage of this parcel data is acceptable; manage or delete archive and pipeline state files when persistence is not desired. <br>\nRisk: Correction and cadastre-update flows can modify existing archive records. <br>\nMitigation: Confirm the exact parcel code before applying updates and keep the generated backups for review or rollback. <br>\nRisk: Server security evidence flags the release for review because archive-modifying behavior may conflict with read-only expectations. <br>\nMitigation: Review generated CSV and archive changes before relying on, importing, or sharing the outputs. <br>\n\n\n## Reference(s): <br>\n- [ClawHub skill page](https://clawhub.ai/jeromeex/skills/ovitalmap-parcel-csv) <br>\n\n\n## Skill Output: <br>\n**Output Type(s):** [Files, Markdown, Shell commands, Guidance] <br>\n**Output Format:** [Markdown guidance with generated UTF-8 CSV files and JSON script results] <br>\n**Output Parameters:** [1D] <br>\n**Other Properties Related to Output:** [Generates paired Ovitalmap vertex and boundary CSV files and may update local archive, backup, and pipeline state files.] <br>\n\n## Skill Version(s): <br>\n2.1.0 (source: server release metadata) <br>\n\n## Ethical Considerations: <br>\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment. <br>\n\nFile v2.1.0:.clawhub/origin.json\n\n{\n  \"version\": 1,\n  \"registry\": \"https://clawhub.ai\",\n  \"slug\": \"ovitalmap-parcel-csv\",\n  \"installedVersion\": \"2.0.3\",\n  \"installedAt\": 1782549216604,\n  \"artifact\": {\n    \"kind\": \"archive\",\n    \"sha256\": \"3b6af6bdc377bc54f345a92ac5677bf67ebc43a6f4684840e64a0aa0da7fb476\",\n    \"integrity\": \"sha256-O2r2vcN3vFTzRakqxWd79n68Q6b0aEhA5koKoNp/tHY=\"\n  },\n  \"skillFile\": {\n    \"path\": \"SKILL.md\",\n    \"sha256\": \"c9a3a01881206123b43b1e94f558ff9ac1cdba2e6ac34ad456091677a446b572\"\n  }\n}\n\nArchive v2.0.3: 10 files, 29937 bytes\n\nFiles: scripts/__init__.py (39b), scripts/archive_manager.py (17303b), scripts/country_locator.py (2539b), scripts/csv_builder.py (7752b), scripts/parcel_pipeline.py (16240b), scripts/provider_matcher.py (6795b), scripts/utils.py (7478b), skill-card.md (2149b), SKILL.md (27855b), _meta.json (139b)\n\nFile v2.0.3:SKILL.md\n\n---\nname: \"ovitalmap-parcel-csv\"\ndescription: \"Parse parcel vertex coordinates from images/text, generate Ovitalmap-compatible CSVs (顶点表 + 边界表), categorize parcels by country-code/provider, and archive into a per-country database. Invoke when user provides parcel coordinates in any format and wants Ovitalmap CSV output.\"\n---\n\n# Ovitalmap Parcel CSV Generator\n\nThis skill processes parcel vertex coordinates — from images or text — and produces Ovitalmap-readable CSV files. It also archives every processed parcel into a structured per-country database with provider metadata.\n\n---\n\n## 0) Defaults: Language, Tone, I/O\n\n- **Reply language**: Chinese by default unless the user requests another language.\n- **Tone**: non-repetitive, concise, precise, professional.\n- **Ambiguity handling**: when inputs are unclear (e.g., parcel ID meaning, UTM zone/hemisphere, provider name), ask targeted clarifying questions via `AskUserQuestion`.\n- **CSV headers**: keep original Chinese headers exactly as listed below. Do not translate them.\n\n---\n\n## 0b) Scripting Conventions (MANDATORY)\n\n**Use Python scripts for all data processing, CSV generation, archive management, and QC checks.** Do not process data through LLM reasoning alone — it is unreliable and costly for structured operations.\n\n### Available Scripts\n\nAll scripts live in `scripts/` and accept JSON via stdin, returning JSON to stdout.\n\n| Script | Purpose | Key CLI examples |\n|--------|---------|------------------|\n| **`scripts/utils.py`** | Shared helpers (CSV I/O, boundary comparison, DMS conversion, coordinate validation). Imported by other scripts — not called directly. | `from utils import boundaries_equal, dms_to_decimal` |\n| **`scripts/country_locator.py`** | Normalize & validate WGS84 coordinates (lat/lon swap detection, range checks). ALWAYS returns `country_code: null` — the LLM determines the country from spatial knowledge and conversation context. | `echo '[[114.13,22.50],[114.14,22.51]]' \\| python3 scripts/country_locator.py` |\n| **`scripts/archive_manager.py`** | All archive operations: scan existing codes/max-SEQ/providers, append new parcels, check coordinate duplicates, backup, correct coordinates, extract single-parcel exports from batch files, update cadastre_code. | `echo '{\"action\":\"scan\",\"country_code\":\"CN\",\"date\":\"260610\"}' \\| python3 scripts/archive_manager.py` |\n| **`scripts/csv_builder.py`** | Build both Vertices CSV (顶点表) and Boundary CSV (边界表) from structured parcel data. Writes to `ovitalmap_exports/{CC}/`. Can also build single-parcel CSVs for archive hits. | `echo '{\"parcels\":[{...}],\"first_code\":\"CN-260610-001\",\"count\":2,\"country_code\":\"CN\"}' \\| python3 scripts/csv_builder.py` |\n| **`scripts/provider_matcher.py`** | Fuzzy-match a provider name against existing names (exact, whitespace, honorific, substring, pinyin). Returns `ambiguous` flag when multiple candidates match equally. | `echo '{\"input_name\":\"李总\",\"existing_names\":[\"中非李总\",\"张三\"]}' \\| python3 scripts/provider_matcher.py` |\n| **`scripts/parcel_pipeline.py`** | **Main orchestrator.** Runs the full flow in steps. Step 1 = country+provider (read-only), Step 2b = duplicate check → reuse matched codes (read-only), Step 2 = code assignment for new parcels (read-only), Step 3 = CSV build for all + archive for new (writes files). | `echo '{\"parcels\":[{...}],\"date\":\"260610\",\"resolved_provider_name\":\"张三\"}' \\| python3 scripts/parcel_pipeline.py --step 2b` |\n\n### Script principles\n\n- Run scripts via `RunCommand` and read their stdout JSON for results.\n- All scripts produce machine-parseable JSON output for the LLM to consume and present to the user.\n- **Use `python3`** as the interpreter.\n- Do not inline large data transformations in the conversation — delegate to scripts.\n- **LLM has the final say.** Scripts are tools, not authorities. If a script's output looks wrong — implausible country, mismatched provider, duplicate not caught, garbled coordinates, unreasonable SEQ jump — the LLM **must** inspect the result, flag anomalies to the user, and override or re-run with corrections when appropriate. Do not silently trust script output.\n\n### Recommended workflow\n\nThe LLM should orchestrate the pipeline **step-by-step** using `parcel_pipeline.py`:\n\n1. **After the user confirms coordinates and provider:** run `--step 1` → get country code, country name, and provider match results.\n2. **Before code assignment — duplicate check:** run `--step 2b` → coordinate-based duplicate check against archive. Archive hits **reuse the existing `parcel_code`** (no new code assigned). Non-hits proceed to step 2.\n3. **Assign codes for new parcels:** run `--step 2` → sequential codes for genuinely new parcels only.\n4. **After the user confirms codes and any archive hits are resolved:** run `--step 3` → CSV generation for **ALL parcels** (batch for new, single-file for hits) + archive append (**new parcels only**).\n\nAlternatively, call individual scripts for targeted operations (e.g., `provider_matcher.py` alone when only checking a provider name).\n\n---\n\n## 1) Inputs and Core Assumptions\n\n- **Input**: one or more images or text blocks that contain parcel vertex coordinates.\n- **Coordinate parsing**: auto-detect format:\n  - Decimal degrees: `22.50422, 114.13472`\n  - DMS: `22°30'15.2\"N, 114°08'05.0\"E`\n  - UTM with zone and hemisphere\n  - Other formats on a best-effort basis\n- **WGS84 policy**:\n  1. Always display the raw recognized coordinates verbatim per parcel.\n  2. Always display WGS84 decimal-degree coordinates (convert if needed).\n- **Date token (YYMMDD)**:\n  - Use user-provided date if given.\n  - Else use today's local date.\n- **CSV format**: UTF-8, comma-separated, no BOM.\n\n---\n\n## 2) Country and Parcel Codes\n\n### 2.1) Country Code\n- **The LLM determines the country.** The `country_locator.py` script only normalizes coordinates; it does NOT perform geocoding. Use your spatial knowledge: match coordinate ranges against the world map, combine with any country names visible in documents, administrative regions mentioned, or the user's stated location.\n- **State it, don't ask.** Present your determination (e.g. \"根据坐标判断，该地块位于中国 (CN)\") and proceed. Do NOT ask \"which country?\" — the user will correct if wrong.\n- Default standard: **ISO 3166-1 alpha-2** (e.g., CN, HK, US, FR).\n- **Cross-border parcels**: assign to the country where the majority of the parcel falls. Do not split.\n\n### 2.2) Parcel Code — Always Generated\n\n**Every parcel MUST receive a `parcel_code`.** There is no \"no code\" fallback.\n\nThe code follows one of two formats, with priority given to official registration IDs:\n\n| Priority | Source | Format | Example |\n|----------|--------|--------|---------|\n| 1 (preferred) | Official registration ID found in **image text or explicitly provided by user** | `{CC}-{OFFICIAL_ID}` | `CN-PE12345`, `AU-EL9876` |\n| 2 (default) | Auto-generated sequential code | `{CC}-{YYMMDD}-{SEQ}` | `CN-260609-003`, `HK-260609-001` |\n\nWhere `{CC}` is the **ISO 3166-1 alpha-2** country code.\n\n**Official registration ID detection:**\n- Scan any user-provided text, image OCR output, chat context, attached documents, or any other input modality for candidate registration / permit / cadastre numbers.\n- If a clear mining cadastre / registration / permit number appears, present it to the user for confirmation before adopting it.\n- If multiple candidate IDs appear for the same parcel, pick the most specific one and ask the user to confirm.\n\n### 2.3) Uniqueness Check (Mandatory Before Code Assignment)\n\n**Before finalizing any `parcel_code`,** you MUST scan the existing archive to prevent duplicates. This is critical because:\n- Users may upload multiple parcels in one session or across separate sessions on the same day.\n- A new session must NOT restart SEQ from 001 — it must continue from the last used number.\n\n**Procedure:**\n\n1. Scan `ovitalmap_archive/{CC}_parcels.csv` (if it exists) — this is the single source of truth.\n2. Extract all existing `parcel_code` values from the archive.\n3. For **official registration IDs** (format 1): check that `{CC}-{OFFICIAL_ID}` does NOT already exist. If it does, warn the user and ask for clarification.\n4. For **sequential codes** (format 2): find the maximum SEQ already used for today (`{CC}-{YYMMDD}-*`). The new SEQ = max_existing + 1. If none exist for today, SEQ starts at `001`.\n5. If the archive file does not exist yet, SEQ starts at `001`.\n\n---\n\n## 3) Output Files Overview\n\nTwo CSVs are produced together for the batch:\n\n| # | File | Description |\n|---|------|-------------|\n| 1 | **Vertices CSV** (顶点表) | Every parcel vertex |\n| 2 | **Boundary CSV** (边界表) | Every parcel as a closed polygon |\n\n### 3.1) File Naming & Layout\n\nStore generated CSVs in **country subdirectories** under `ovitalmap_exports/`:\n\n```\novitalmap_exports/{CC}/\n```\n\nEvery export filename includes a `YYMMDD_HHMMSS` timestamp to prevent collisions even across re-exports or parallel sessions:\n\n| File | Pattern |\n|------|---------|\n| Vertices CSV | `{firstCode}_N{count}_{YYMMDD_HHMMSS}.csv` |\n| Boundary CSV | `{firstCode}_N{count}_{YYMMDD_HHMMSS}_boundary.csv` |\n\n- `firstCode` = the `parcel_code` of the first parcel in this batch.\n- `count` = total number of parcels in this batch.\n- `YYMMDD_HHMMSS` = export timestamp at file-write time.\n\nExamples:\n- `CN-260609-001_N2_260609_143021.csv` — batch of 2, first is 001.\n- `CN-PE12345_N1_260609_143522.csv` — single parcel with an official registration code.\n\n---\n\n## 4) Vertices CSV (顶点表)\n\nHeaders (exact, in order, **do not translate**):\n\n```\n文件夹,名称,经度,纬度,海拔,文本显示风格,图标样式,Comment\n```\n\n### Field Rules\n\n| Field | Rule |\n|-------|------|\n| **文件夹** | `{parcel_code}` — always |\n| **名称** | `{parcel_code}_A{vertex-index}`. `vertex-index` starts at **A01** and increases by original vertex order |\n| **经度** | WGS84 decimal longitude. Preserve sign and precision. **No rounding.** |\n| **纬度** | WGS84 decimal latitude. Preserve sign and precision. **No rounding.** |\n| **海拔** | Fill if present in input; else leave **empty** |\n| **文本显示风格** | Empty by default |\n| **图标样式** | Default `1` |\n| **Comment** | `提供者:{provider_name} 归档日期:{archive_date}`. If a `cadastre_code` exists (user-provided official ID or explicit code), append ` 地籍号:{cadastre_code}`. Applies to all parcels uniformly. |\n\n### Indexing conventions\n- `vertex-index` resets from **01 per parcel** (A01, A02, …).\n- Preserve original vertex order. If ordering is unclear, ask the user about **clockwise reordering**.\n\n---\n\n## 5) Boundary CSV (边界表)\n\nHeaders (exact, in order, **do not translate**):\n\n```\n文件夹,名称,经纬度[经度+纬度],线条宽度,线条颜色,线条不透明度,闭合,线型,轨迹风格,Comment\n```\n\n### Field Rules\n\n| Field | Rule |\n|-------|------|\n| **文件夹** | Same as Vertices CSV |\n| **名称** | `{parcel_code}` — the bare parcel code, no `_A01` vertex suffix. The boundary represents the whole polygon. |\n| **经纬度[经度+纬度]** | Concatenate as `lon,lat;lon,lat;…` (no spaces) following Vertices order. Close the polygon by repeating the first vertex at the end if the input does not already close it. |\n| **线条宽度** | Default `3` |\n| **线条颜色** | Default `0X00FF0000` |\n| **线条不透明度** | Default `50` |\n| **闭合** | Default `1` |\n| **线型** | Default `0` |\n| **轨迹风格** | Default `1` |\n| **Comment** | `提供者:{provider_name} 归档日期:{archive_date}`. If a `cadastre_code` exists (user-provided official ID or explicit code), append ` 地籍号:{cadastre_code}`. Applies to all parcels uniformly. |\n\n---\n\n## 6) Quality Checks and Special Cases\n\n1. **Range checks**: longitude ∈ [-180, 180], latitude ∈ [-90, 90]. Flag any violations explicitly.\n2. **Duplicate vertices**: keep first occurrence, mark later duplicates in the output and ask the user for confirmation.\n3. **Cross-border parcels**: use the country where the majority area falls (§2.1). Do not split.\n4. **Missing altitude**: leave the field empty; never infer or guess.\n5. **Naming collisions**: if 文件夹 + 名称 duplicates occur, report the collision to the user.\n6. **Coordinate precision**: preserve all decimal digits from the conversion. Do not round.\n7. **Existing-parcel duplicate detection (MANDATORY before archiving)**: Before writing a new parcel to the archive, check whether a parcel with the **same set of vertex coordinates** already exists in the archive using `archive_manager.py check_duplicate`. Comparison rules:\n   - The same vertices in **any** cyclic permutation or reversal (different starting point, clockwise vs counterclockwise) are considered equal.\n   - If a match is found, **do NOT generate new CSVs or re-archive**. Instead, follow the **archive-hit workflow** (§6.8).\n8. **Archive-hit workflow**: When `check_duplicate` finds a coordinate match in the archive, follow this procedure:\n   a. Report the match to the user with the existing `parcel_code` and provider.\n   b. **Reuse the existing `parcel_code`** — do NOT assign a new code.\n   c. **Provide the existing archived document to the user** — regenerate single-parcel CSV files (`{parcel_code}_N1_{timestamp}.csv` + `_boundary.csv`) in `ovitalmap_exports/{CC}/` with full Comment metadata (provider, archive date, cadastre code if available). Never return other parcels' data alongside the archive-hit parcel.\n   d. **Cadastre code update**: If the existing parcel only has a generic date-based code (e.g., `CN-260609-001`) and the user is now providing an official registration ID, update the `cadastre_code` field in the archive (both per-country and master) with the new official ID. Use `archive_manager.py update_cadastre` for this. The regenerated CSV will then include `地籍号:{official_id}` in the Comment.\n   e. **Do not re-archive** the parcel.\n   f. If the user explicitly says it is a **different parcel** despite identical coordinates, archive normally with a note in `provider_notes`: `\"Coordinates identical to {existing_code}; user confirmed it is a different parcel.\"`.\n9. **Batch with mixed hits**: If the user provides multiple parcels and some hit the archive while others are new:\n   - Archive-hit parcels → **reuse existing `parcel_code`**, regenerate single-parcel CSVs with Comment metadata, update cadastre_code if applicable.\n   - New parcels → assign codes, generate batch CSVs, and archive normally.\n   - The two groups are processed independently. Present results separately to the user.\n\n---\n\n## 7) Archiving and Categorization (Database)\n\n**After generating the CSVs for a parcel**, you MUST archive the parcel into the workspace database.\n\n### 7.1) Archive Location\n\nAll archives live flat in `ovitalmap_archive/` at the workspace root. One file per country:\n\n```\novitalmap_archive/{CC}_parcels.csv\n```\n\nIf the file does not exist yet, create it with headers.\n\n### 7.2) Archive CSV Headers\n\n```\nparcel_code,provider_name,archive_date,boundary_coords,provider_notes,cadastre_code\n```\n\n### 7.3) Field Rules for Archiving\n\n| Field | Rule |\n|-------|------|\n| **parcel_code** | Assigned per §2.2–2.3. Always populated. |\n| **provider_name** | The name of the person/organization who provided this parcel. **MUST ask the user** for at least a name. If the user mentions a series of similar names, confirm with them before archiving. If they mention none of the names you suggest, treat it as a new provider. |\n| **archive_date** | Date of archiving in YYYY-MM-DD format |\n| **boundary_coords** | Full boundary string in the format `lon,lat;lon,lat;…` (same as Boundary CSV 经纬度 field). This is the canonical coordinate storage. |\n| **provider_notes** | Any additional notes about the provider or context; empty by default |\n| **cadastre_code** | Populate with **any official registration / cadastre / permit ID** from government documents, regardless of whether it is used as the `parcel_code`. This includes: mining cadastre numbers, land registration IDs, permit numbers, or any government-issued parcel identifier — from images, OCR, documents, or explicit user input. When `parcel_code` uses format 1 (`{CC}-{OFFICIAL_ID}`), the `{OFFICIAL_ID}` portion MUST also be stored here. Leave empty only when no official ID exists. The pipeline's `step2_assign_codes()` ensures this automatically when `official_id` is present. |\n\n### 7.4) Provider Name Workflow\n\n1. **At Step 1** (before any code assignment or file writing), ask the user: **\"Who provided this parcel? (请提供此地块的提供者姓名)\"**\n2. After the user provides a name, **immediately scan all existing providers** from both:\n   - `ovitalmap_archive/{CC}_parcels.csv` (per-country archive)\n   - `ovitalmap_archive/master.csv` (cross-country archive)\n3. **Proactive fuzzy deduplication** — compare the user-supplied name against every existing provider via `provider_matcher.py`. Accept the provider only when `exact_match` is found or after explicit user confirmation. The script returns:\n   - `exact_match`: the name if an exact match exists.\n   - `candidates`: list of `{name, reason, score}` sorted by score.\n   - `ambiguous`: `true` when there are **multiple candidates with equal scores** (i.e., the script cannot determine a definitive match — the LLM MUST ask the user).\n\n   Match types recognized by the script:\n   - **Exact match** (score 100): identical string after case-insensitive normalization and whitespace/punctuation removal (e.g., `\"Zhang San\"` ≈ `\"Zhang-San\"` ≈ `\"ZhangSan\"`). The script's `_normalize()` function handles this before comparison.\n   - **Chinese ↔ Pinyin match** (score 90): one is Chinese characters and the other is the corresponding pinyin (e.g., `\"张三\"` ≈ `\"zhangsan\"`).\n   - **Cross-language pinyin** (score 85): one name has Chinese with its pinyin matching the other's normalized form.\n   - **Substring overlap** (score 80): one name is fully contained within another, checked both with and without honorific stripping (e.g., `\"李总\"` ⊂ `\"中非李总\"`).\n   - **Honorific variation** (score 75): names differ only by a common Chinese honorific or prefix (e.g., `\"李总\"` ≈ `\"李\"` after stripping `\"总\"`).\n\n4. **Handle matches with mandatory user confirmation for non-exact matches:**\n   - **Exact match** (score 100 / reason `exact`): automatically reuse the existing `provider_name` spelling. No user confirmation needed.\n   - **Single candidate** (score ≥ 80, single candidate, not ambiguous): ask the user explicitly:\n     > **\"检测到提供者 '{input_name}' 与已有记录 '{existing_name}' 高度相似。是否为同一个人？\"**\n     - If the user confirms **same person** → reuse the existing `provider_name` spelling.\n     - If the user says **different person** → treat as a new provider.\n     - If the user is unsure → keep the new name but add a note in `provider_notes`: `Possible duplicate of '{existing_name}'.`\n   - **Low-confidence candidate** (score 50-79, single candidate, not ambiguous): ask the user but note the lower confidence:\n     > **\"检测到提供者 '{input_name}' 与已有记录 '{existing_name}' 可能相似（置信度较低）。是否为同一个人？\"**\n     - Same confirmation flow as above.\n   - **Multiple candidates / ambiguous** (e.g., user says `\"李总\"`, archive has `\"中非李总\"` and `\"三一李总\"`): **MUST list ALL candidates and ask the user to specify.** Do not guess:\n     > **\"'{input_name}' 在已有记录中匹配到多位提供者：① {candidate1}  ② {candidate2}。请问对应的是哪一位？或都不是(新建)？\"**\n     - If the user picks one → reuse that existing `provider_name`.\n     - If the user says none of them → treat as a new provider.\n   - **No match / score < 50**: automatically add as a new provider. No confirmation needed.\n\n5. If the user declines to provide a name, use `\"Unknown\"` and note it.\n6. **Do not proceed to code assignment until provider name is confirmed.**\n\n---\n\n## 8) Master Spreadsheet\n\nAfter archiving to `ovitalmap_archive/{CC}_parcels.csv`, **also append the same row(s)** to a single consolidated file:\n\n```\novitalmap_archive/master.csv\n```\n\nThis is a **single spreadsheet containing every parcel from every country** — the complete cross-country view.\n\n**Headers** (one extra column vs per-country `parcels.csv`):\n\n```\nCC,parcel_code,provider_name,archive_date,boundary_coords,provider_notes,cadastre_code\n```\n\nAppend every newly archived parcel row here immediately after writing to the per-country file. If `master.csv` does not exist, create it with headers.\n\n---\n\n## 9) Interaction Flow\n\n### Guard Rule\n\n**Do NOT write or modify any file until user confirms BOTH coordinates AND provider name.** Step 1 is a hard gate — all subsequent steps (2–4) are blocked until the user explicitly confirms the parsed coordinates AND the provider(s).\n\nWhen invoked, follow this sequence:\n\n### 1. Parse, Verify & Confirm Provider\n- Show raw coordinates and WGS84 conversion per parcel.\n- **Ask for the provider name(s)** (§7.4). Identify each parcel's provider.\n- Display ⚠️ **\"请核实以下识别和转换后的坐标是否与原始数据一致，并确认提供者姓名\"**.\n→ **STOP HERE. Wait for user to confirm or correct coordinates AND provider.** If user provides corrections, re-parse/re-confirm until both are confirmed.\n\n### 2b. Duplicate Check (MANDATORY — runs before code assignment)\n- **Determine country** from coordinates using your spatial knowledge, plus any country names in documents or user context. State it and move on.\n- Run `parcel_pipeline.py --step 2b` for each parcel.\n- **Archive-hit parcels**: reuse the **existing `parcel_code`** from the archive (no new code). Detect any official registration IDs from image text or user input; if the matched parcel has a generic date-code and no `cadastre_code` yet, update it via `archive_manager.py update_cadastre`. Display: `\"检测到地块坐标与已有记录 {matched_code} 一致，沿用归档编码。\"`.\n- **New parcels**: proceed to step 2.\n\n### 2. Assign Codes (only for new parcels, only after step 2b)\n- **Official registration IDs take priority**: if any parcel has a confirmed official registration / cadastre ID (from documents, OCR, or explicit user input), use format 1: `{CC}-{OFFICIAL_ID}` as the `parcel_code`. The `{OFFICIAL_ID}` is also stored as `cadastre_code`.\n- For parcels **without** an official ID: run `parcel_pipeline.py --step 2` to get format 2 sequential codes `{CC}-{YYMMDD}-{SEQ}`.\n- Display all assigned codes. The user will correct if wrong.\n\n### 3. Build CSVs (for ALL parcels)\nBuild **both** Vertices CSV (§4) and Boundary CSV (§5) for every parcel:\n- **New parcels**: batch CSV (e.g., `{firstCode}_N{count}_{timestamp}.csv` + `_boundary.csv`).\n- **Archive-hit parcels**: individual single-parcel CSVs (e.g., `{matchedCode}_N1_260609_143021.csv` + `_boundary.csv`) regenerated with updated Comment metadata.\n\nRun quality checks (§6). State the generated filenames:\n\n> CSV 文件已生成:\n> - 顶点表: `{firstCode}_N{count}_{timestamp}.csv`\n> - 边界表: `{firstCode}_N{count}_{timestamp}_boundary.csv`\n> \n> 已有地块:\n> - 顶点表: `{matchedCode}_N1_{timestamp}.csv`\n> - 边界表: `{matchedCode}_N1_{timestamp}_boundary.csv`\n\n### 4. Archive (only for new parcels)\n- Append to `ovitalmap_archive/{CC}_parcels.csv` and `ovitalmap_archive/master.csv`.\n- Summarize: provider, codes, date.\n\n### 5. Wrap Up\nNote any assumptions, edge cases, or corrections. Separately list archive-hit exports and any cadastre_code updates.\n\n---\n\n## 9b) Post-Archive Coordinate Correction\n\nUsers may correct a parcel's coordinates after it has been archived. When this happens:\n\n### Procedure\n\n1. **Identify the parcel** by its `parcel_code` in `ovitalmap_archive/{CC}_parcels.csv` and `ovitalmap_archive/master.csv`.\n\n2. **Backup before modifying** — copy the current archive files to a backup:\n\n   ```\n   ovitalmap_backups/{CC}_parcels_{YYMMDD_HHMM}.csv\n   ovitalmap_backups/master_{YYMMDD_HHMM}.csv\n   ```\n\n   Create `ovitalmap_backups/` if it does not exist.\n\n3. **Update the row** in the per-country archive and master spreadsheet:\n   - Replace `boundary_coords` with the corrected boundary string.\n   - Update `archive_date` to the current date (marking the correction date).\n   - Append a note to `provider_notes`: `\"[{date}] Coordinates corrected. Original backup: {backup_file}\"`.\n\n4. **Regenerate the export CSVs** for the corrected parcel in `ovitalmap_exports/{CC}/`.\n\n5. **Summarize** what was changed, where backups are, and ask the user to verify.\n\n---\n\n## 10) Example Output Snippet\n\n```\n⚠️ 请核实以下识别和转换后的坐标是否与原始数据一致，并确认提供者姓名\n\n原始坐标:\n• 地块 1: 22°30'15.2\"N, 114°08'05.0\"E; 22°30'14.8\"N, 114°08'08.3\"E; …\n• 地块 2: 22.50422, 114.13472; 22.50418, 114.13480; …\n\nWGS84:\n• 地块 1: 114.13472, 22.50422; 114.13564, 22.50411; …\n• 地块 2: 114.13472, 22.50422; 114.13500, 22.50416; …\n\n请提供此地块的提供者姓名？\n\n确认坐标无误并确认提供者后继续处理？(如有修正请提供)\n\n→ 用户确认坐标 + 提供者: 中非李总\n\n所属国家: 中国 (CN)\n\n正在检查重复…\n  ✓ 地块 1: 无重复\n  ✓ 地块 2: 无重复\n\n正在扫描 CN 存档…\n  现有编码: CN-260609-001, CN-260609-002\n\n检测到地块 2 的官方登记号 PE12345 → 采用格式 1 编码\n\n  → 地块 1 → CN-260609-003（无官方编号，顺序编码）\n  → 地块 2 → CN-PE12345（官方登记号）\n\n最终编码:\n• 地块 1: CN-260609-003（新增）\n• 地块 2: CN-PE12345（新增，cadastre_code: PE12345）\n\nCSV 文件已生成:\n• 顶点表: CN-260609-003_N2_260609_143021.csv\n• 边界表: CN-260609-003_N2_260609_143021_boundary.csv\n\n--- 归档 ---\n\n归档完成:\n• 地块编号: CN-260609-003, CN-PE12345\n• 提供者: 中非李总\n• 归档日期: 2026-06-09\n```\n\n### Example: Archive Hit\n\n```\n→ 用户确认坐标 + 提供者: 王五\n\n所属国家: 中国 (CN)\n\n正在检查重复…\n  ⚠️ 地块 1: 检测到坐标与已有记录 CN-260609-001 (提供者: 张三) 一致\n     → 沿用归档编码: CN-260609-001\n     → 该地块未被重新归档。\n\nCSV 文件已生成:\n• 顶点表: CN-260609-001_N1_260609_143522.csv\n• 边界表: CN-260609-001_N1_260609_143522_boundary.csv\n  (Comment: 提供者:张三 归档日期:2026-06-02)\n\n--- 归档 ---\n无新增记录。已有地块 CN-260609-001 未被重复归档。\n```\n\n---\n\n## 11) Future Extensions (Placeholders)\n\n- **Cadastre minier lookup**: another skill will be developed to query official mining cadastre registries and populate the `cadastre_code` field.\n- **Email dispatch**: the summary spreadsheet will be periodically sent to a configured email address. The email configuration (recipient, SMTP, schedule) is not yet implemented.\n\n---\n\n## 12) File Structure\n\n```\nworkspace/\n├── scripts/                       # Python utility scripts (§0b)\n├── ovitalmap_exports/             # Generated CSVs (by country subdir)\n│   ├── CN/\n│   │   └── CN-260609-001_N2_260609_143021.csv\n│   ├── HK/\n│   │   └── HK-260609-001_N1_260609_143522.csv\n│   └── …\n├── ovitalmap_archive/             # Persistent database (flat)\n│   ├── master.csv                 # All parcels, all countries\n│   ├── CN_parcels.csv\n│   ├── HK_parcels.csv\n│   └── …\n├── ovitalmap_backups/             # Pre-correction snapshots (§9b)\n│   ├── CN_parcels_260609_1430.csv\n│   └── master_260609_1430.csv\n└── .trae/skills/ovitalmap-parcel-csv/\n    └── SKILL.md\n```\n\nFile v2.0.3:_meta.json\n\n{\n  \"ownerId\": \"kn76j7kby3cajgq933bwccdxbn82fw68\",\n  \"slug\": \"ovitalmap-parcel-csv\",\n  \"version\": \"2.0.3\",\n  \"publishedAt\": 1781101789586\n}\n\nFile v2.0.3:skill-card.md\n\n## Description: <br>\nParses parcel vertex coordinates from images or text, creates Ovitalmap-compatible vertex and boundary CSV files, categorizes parcels by country and provider, and maintains a local parcel archive. <br>\n\nThis skill is ready for commercial/non-commercial use. <br>\n\n## Publisher: <br>\n[jeromeex](https://clawhub.ai/user/jeromeex) <br>\n\n### License/Terms of Use: <br>\nMIT-0 <br>\n\n\n## Use Case: <br>\nExternal users and GIS or data operators use this skill to convert parcel coordinates into Ovitalmap CSV exports while assigning parcel codes, checking duplicates, matching providers, and retaining archive records. <br>\n\n### Deployment Geography for Use: <br>\nGlobal <br>\n\n## Known Risks and Mitigations: <br>\nRisk: The skill persists parcel boundaries, provider names, and official registration IDs in local per-country and master archive CSV files. <br>\nMitigation: Use only when the user has agreed to local retention; avoid sensitive documents unless archival retention and cross-country provider matching are acceptable. <br>\nRisk: Security evidence notes that a step labeled read-only can write pipeline state. <br>\nMitigation: Treat pipeline execution as stateful, run it in a controlled workspace, and review generated state, archive, and export files before sharing or reusing them. <br>\n\n\n## Reference(s): <br>\n- [ClawHub skill page](https://clawhub.ai/jeromeex/ovitalmap-parcel-csv) <br>\n\n\n## Skill Output: <br>\n**Output Type(s):** [Files, Text, Shell commands, Configuration, Guidance] <br>\n**Output Format:** [Markdown guidance, JSON script output, and UTF-8 CSV files] <br>\n**Output Parameters:** [1D] <br>\n**Other Properties Related to Output:** [Creates country-scoped exports and persistent local archive CSVs; pipeline steps may read or write workspace state.] <br>\n\n## Skill Version(s): <br>\n2.0.3 (source: server release evidence) <br>\n\n## Ethical Considerations: <br>\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment. <br>\n\nArchive v2.0.2: 10 files, 29658 bytes\n\nFiles: scripts/__init__.py (39b), scripts/archive_manager.py (17297b), scripts/country_locator.py (2539b), scripts/csv_builder.py (7750b), scripts/parcel_pipeline.py (16215b), scripts/provider_matcher.py (6795b), scripts/utils.py (6556b), skill-card.md (2341b), SKILL.md (27855b), _meta.json (139b)\n\nFile v2.0.2:SKILL.md\n\n---\nname: \"ovitalmap-parcel-csv\"\ndescription: \"Parse parcel vertex coordinates from images/text, generate Ovitalmap-compatible CSVs (顶点表 + 边界表), categorize parcels by country-code/provider, and archive into a per-country database. Invoke when user provides parcel coordinates in any format and wants Ovitalmap CSV output.\"\n---\n\n# Ovitalmap Parcel CSV Generator\n\nThis skill processes parcel vertex coordinates — from images or text — and produces Ovitalmap-readable CSV files. It also archives every processed parcel into a structured per-country database with provider metadata.\n\n---\n\n## 0) Defaults: Language, Tone, I/O\n\n- **Reply language**: Chinese by default unless the user requests another language.\n- **Tone**: non-repetitive, concise, precise, professional.\n- **Ambiguity handling**: when inputs are unclear (e.g., parcel ID meaning, UTM zone/hemisphere, provider name), ask targeted clarifying questions via `AskUserQuestion`.\n- **CSV headers**: keep original Chinese headers exactly as listed below. Do not translate them.\n\n---\n\n## 0b) Scripting Conventions (MANDATORY)\n\n**Use Python scripts for all data processing, CSV generation, archive management, and QC checks.** Do not process data through LLM reasoning alone — it is unreliable and costly for structured operations.\n\n### Available Scripts\n\nAll scripts live in `scripts/` and accept JSON via stdin, returning JSON to stdout.\n\n| Script | Purpose | Key CLI examples |\n|--------|---------|------------------|\n| **`scripts/utils.py`** | Shared helpers (CSV I/O, boundary comparison, DMS conversion, coordinate validation). Imported by other scripts — not called directly. | `from utils import boundaries_equal, dms_to_decimal` |\n| **`scripts/country_locator.py`** | Normalize & validate WGS84 coordinates (lat/lon swap detection, range checks). ALWAYS returns `country_code: null` — the LLM determines the country from spatial knowledge and conversation context. | `echo '[[114.13,22.50],[114.14,22.51]]' \\| python3 scripts/country_locator.py` |\n| **`scripts/archive_manager.py`** | All archive operations: scan existing codes/max-SEQ/providers, append new parcels, check coordinate duplicates, backup, correct coordinates, extract single-parcel exports from batch files, update cadastre_code. | `echo '{\"action\":\"scan\",\"country_code\":\"CN\",\"date\":\"260610\"}' \\| python3 scripts/archive_manager.py` |\n| **`scripts/csv_builder.py`** | Build both Vertices CSV (顶点表) and Boundary CSV (边界表) from structured parcel data. Writes to `ovitalmap_exports/{CC}/`. Can also build single-parcel CSVs for archive hits. | `echo '{\"parcels\":[{...}],\"first_code\":\"CN-260610-001\",\"count\":2,\"country_code\":\"CN\"}' \\| python3 scripts/csv_builder.py` |\n| **`scripts/provider_matcher.py`** | Fuzzy-match a provider name against existing names (exact, whitespace, honorific, substring, pinyin). Returns `ambiguous` flag when multiple candidates match equally. | `echo '{\"input_name\":\"李总\",\"existing_names\":[\"中非李总\",\"张三\"]}' \\| python3 scripts/provider_matcher.py` |\n| **`scripts/parcel_pipeline.py`** | **Main orchestrator.** Runs the full flow in steps. Step 1 = country+provider (read-only), Step 2b = duplicate check → reuse matched codes (read-only), Step 2 = code assignment for new parcels (read-only), Step 3 = CSV build for all + archive for new (writes files). | `echo '{\"parcels\":[{...}],\"date\":\"260610\",\"resolved_provider_name\":\"张三\"}' \\| python3 scripts/parcel_pipeline.py --step 2b` |\n\n### Script principles\n\n- Run scripts via `RunCommand` and read their stdout JSON for results.\n- All scripts produce machine-parseable JSON output for the LLM to consume and present to the user.\n- **Use `python3`** as the interpreter.\n- Do not inline large data transformations in the conversation — delegate to scripts.\n- **LLM has the final say.** Scripts are tools, not authorities. If a script's output looks wrong — implausible country, mismatched provider, duplicate not caught, garbled coordinates, unreasonable SEQ jump — the LLM **must** inspect the result, flag anomalies to the user, and override or re-run with corrections when appropriate. Do not silently trust script output.\n\n### Recommended workflow\n\nThe LLM should orchestrate the pipeline **step-by-step** using `parcel_pipeline.py`:\n\n1. **After the user confirms coordinates and provider:** run `--step 1` → get country code, country name, and provider match results.\n2. **Before code assignment — duplicate check:** run `--step 2b` → coordinate-based duplicate check against archive. Archive hits **reuse the existing `parcel_code`** (no new code assigned). Non-hits proceed to step 2.\n3. **Assign codes for new parcels:** run `--step 2` → sequential codes for genuinely new parcels only.\n4. **After the user confirms codes and any archive hits are resolved:** run `--step 3` → CSV generation for **ALL parcels** (batch for new, single-file for hits) + archive append (**new parcels only**).\n\nAlternatively, call individual scripts for targeted operations (e.g., `provider_matcher.py` alone when only checking a provider name).\n\n---\n\n## 1) Inputs and Core Assumptions\n\n- **Input**: one or more images or text blocks that contain parcel vertex coordinates.\n- **Coordinate parsing**: auto-detect format:\n  - Decimal degrees: `22.50422, 114.13472`\n  - DMS: `22°30'15.2\"N, 114°08'05.0\"E`\n  - UTM with zone and hemisphere\n  - Other formats on a best-effort basis\n- **WGS84 policy**:\n  1. Always display the raw recognized coordinates verbatim per parcel.\n  2. Always display WGS84 decimal-degree coordinates (convert if needed).\n- **Date token (YYMMDD)**:\n  - Use user-provided date if given.\n  - Else use today's local date.\n- **CSV format**: UTF-8, comma-separated, no BOM.\n\n---\n\n## 2) Country and Parcel Codes\n\n### 2.1) Country Code\n- **The LLM determines the country.** The `country_locator.py` script only normalizes coordinates; it does NOT perform geocoding. Use your spatial knowledge: match coordinate ranges against the world map, combine with any country names visible in documents, administrative regions mentioned, or the user's stated location.\n- **State it, don't ask.** Present your determination (e.g. \"根据坐标判断，该地块位于中国 (CN)\") and proceed. Do NOT ask \"which country?\" — the user will correct if wrong.\n- Default standard: **ISO 3166-1 alpha-2** (e.g., CN, HK, US, FR).\n- **Cross-border parcels**: assign to the country where the majority of the parcel falls. Do not split.\n\n### 2.2) Parcel Code — Always Generated\n\n**Every parcel MUST receive a `parcel_code`.** There is no \"no code\" fallback.\n\nThe code follows one of two formats, with priority given to official registration IDs:\n\n| Priority | Source | Format | Example |\n|----------|--------|--------|---------|\n| 1 (preferred) | Official registration ID found in **image text or explicitly provided by user** | `{CC}-{OFFICIAL_ID}` | `CN-PE12345`, `AU-EL9876` |\n| 2 (default) | Auto-generated sequential code | `{CC}-{YYMMDD}-{SEQ}` | `CN-260609-003`, `HK-260609-001` |\n\nWhere `{CC}` is the **ISO 3166-1 alpha-2** country code.\n\n**Official registration ID detection:**\n- Scan any user-provided text, image OCR output, chat context, attached documents, or any other input modality for candidate registration / permit / cadastre numbers.\n- If a clear mining cadastre / registration / permit number appears, present it to the user for confirmation before adopting it.\n- If multiple candidate IDs appear for the same parcel, pick the most specific one and ask the user to confirm.\n\n### 2.3) Uniqueness Check (Mandatory Before Code Assignment)\n\n**Before finalizing any `parcel_code`,** you MUST scan the existing archive to prevent duplicates. This is critical because:\n- Users may upload multiple parcels in one session or across separate sessions on the same day.\n- A new session must NOT restart SEQ from 001 — it must continue from the last used number.\n\n**Procedure:**\n\n1. Scan `ovitalmap_archive/{CC}_parcels.csv` (if it exists) — this is the single source of truth.\n2. Extract all existing `parcel_code` values from the archive.\n3. For **official registration IDs** (format 1): check that `{CC}-{OFFICIAL_ID}` does NOT already exist. If it does, warn the user and ask for clarification.\n4. For **sequential codes** (format 2): find the maximum SEQ already used for today (`{CC}-{YYMMDD}-*`). The new SEQ = max_existing + 1. If none exist for today, SEQ starts at `001`.\n5. If the archive file does not exist yet, SEQ starts at `001`.\n\n---\n\n## 3) Output Files Overview\n\nTwo CSVs are produced together for the batch:\n\n| # | File | Description |\n|---|------|-------------|\n| 1 | **Vertices CSV** (顶点表) | Every parcel vertex |\n| 2 | **Boundary CSV** (边界表) | Every parcel as a closed polygon |\n\n### 3.1) File Naming & Layout\n\nStore generated CSVs in **country subdirectories** under `ovitalmap_exports/`:\n\n```\novitalmap_exports/{CC}/\n```\n\nEvery export filename includes a `YYMMDD_HHMMSS` timestamp to prevent collisions even across re-exports or parallel sessions:\n\n| File | Pattern |\n|------|---------|\n| Vertices CSV | `{firstCode}_N{count}_{YYMMDD_HHMMSS}.csv` |\n| Boundary CSV | `{firstCode}_N{count}_{YYMMDD_HHMMSS}_boundary.csv` |\n\n- `firstCode` = the `parcel_code` of the first parcel in this batch.\n- `count` = total number of parcels in this batch.\n- `YYMMDD_HHMMSS` = export timestamp at file-write time.\n\nExamples:\n- `CN-260609-001_N2_260609_143021.csv` — batch of 2, first is 001.\n- `CN-PE12345_N1_260609_143522.csv` — single parcel with an official registration code.\n\n---\n\n## 4) Vertices CSV (顶点表)\n\nHeaders (exact, in order, **do not translate**):\n\n```\n文件夹,名称,经度,纬度,海拔,文本显示风格,图标样式,Comment\n```\n\n### Field Rules\n\n| Field | Rule |\n|-------|------|\n| **文件夹** | `{parcel_code}` — always |\n| **名称** | `{parcel_code}_A{vertex-index}`. `vertex-index` starts at **A01** and increases by original vertex order |\n| **经度** | WGS84 decimal longitude. Preserve sign and precision. **No rounding.** |\n| **纬度** | WGS84 decimal latitude. Preserve sign and precision. **No rounding.** |\n| **海拔** | Fill if present in input; else leave **empty** |\n| **文本显示风格** | Empty by default |\n| **图标样式** | Default `1` |\n| **Comment** | `提供者:{provider_name} 归档日期:{archive_date}`. If a `cadastre_code` exists (user-provided official ID or explicit code), append ` 地籍号:{cadastre_code}`. Applies to all parcels uniformly. |\n\n### Indexing conventions\n- `vertex-index` resets from **01 per parcel** (A01, A02, …).\n- Preserve original vertex order. If ordering is unclear, ask the user about **clockwise reordering**.\n\n---\n\n## 5) Boundary CSV (边界表)\n\nHeaders (exact, in order, **do not translate**):\n\n```\n文件夹,名称,经纬度[经度+纬度],线条宽度,线条颜色,线条不透明度,闭合,线型,轨迹风格,Comment\n```\n\n### Field Rules\n\n| Field | Rule |\n|-------|------|\n| **文件夹** | Same as Vertices CSV |\n| **名称** | `{parcel_code}` — the bare parcel code, no `_A01` vertex suffix. The boundary represents the whole polygon. |\n| **经纬度[经度+纬度]** | Concatenate as `lon,lat;lon,lat;…` (no spaces) following Vertices order. Close the polygon by repeating the first vertex at the end if the input does not already close it. |\n| **线条宽度** | Default `3` |\n| **线条颜色** | Default `0X00FF0000` |\n| **线条不透明度** | Default `50` |\n| **闭合** | Default `1` |\n| **线型** | Default `0` |\n| **轨迹风格** | Default `1` |\n| **Comment** | `提供者:{provider_name} 归档日期:{archive_date}`. If a `cadastre_code` exists (user-provided official ID or explicit code), append ` 地籍号:{cadastre_code}`. Applies to all parcels uniformly. |\n\n---\n\n## 6) Quality Checks and Special Cases\n\n1. **Range checks**: longitude ∈ [-180, 180], latitude ∈ [-90, 90]. Flag any violations explicitly.\n2. **Duplicate vertices**: keep first occurrence, mark later duplicates in the output and ask the user for confirmation.\n3. **Cross-border parcels**: use the country where the majority area falls (§2.1). Do not split.\n4. **Missing altitude**: leave the field empty; never infer or guess.\n5. **Naming collisions**: if 文件夹 + 名称 duplicates occur, report the collision to the user.\n6. **Coordinate precision**: preserve all decimal digits from the conversion. Do not round.\n7. **Existing-parcel duplicate detection (MANDATORY before archiving)**: Before writing a new parcel to the archive, check whether a parcel with the **same set of vertex coordinates** already exists in the archive using `archive_manager.py check_duplicate`. Comparison rules:\n   - The same vertices in **any** cyclic permutation or reversal (different starting point, clockwise vs counterclockwise) are considered equal.\n   - If a match is found, **do NOT generate new CSVs or re-archive**. Instead, follow the **archive-hit workflow** (§6.8).\n8. **Archive-hit workflow**: When `check_duplicate` finds a coordinate match in the archive, follow this procedure:\n   a. Report the match to the user with the existing `parcel_code` and provider.\n   b. **Reuse the existing `parcel_code`** — do NOT assign a new code.\n   c. **Provide the existing archived document to the user** — regenerate single-parcel CSV files (`{parcel_code}_N1_{timestamp}.csv` + `_boundary.csv`) in `ovitalmap_exports/{CC}/` with full Comment metadata (provider, archive date, cadastre code if available). Never return other parcels' data alongside the archive-hit parcel.\n   d. **Cadastre code update**: If the existing parcel only has a generic date-based code (e.g., `CN-260609-001`) and the user is now providing an official registration ID, update the `cadastre_code` field in the archive (both per-country and master) with the new official ID. Use `archive_manager.py update_cadastre` for this. The regenerated CSV will then include `地籍号:{official_id}` in the Comment.\n   e. **Do not re-archive** the parcel.\n   f. If the user explicitly says it is a **different parcel** despite identical coordinates, archive normally with a note in `provider_notes`: `\"Coordinates identical to {existing_code}; user confirmed it is a different parcel.\"`.\n9. **Batch with mixed hits**: If the user provides multiple parcels and some hit the archive while others are new:\n   - Archive-hit parcels → **reuse existing `parcel_code`**, regenerate single-parcel CSVs with Comment metadata, update cadastre_code if applicable.\n   - New parcels → assign codes, generate batch CSVs, and archive normally.\n   - The two groups are processed independently. Present results separately to the user.\n\n---\n\n## 7) Archiving and Categorization (Database)\n\n**After generating the CSVs for a parcel**, you MUST archive the parcel into the workspace database.\n\n### 7.1) Archive Location\n\nAll archives live flat in `ovitalmap_archive/` at the workspace root. One file per country:\n\n```\novitalmap_archive/{CC}_parcels.csv\n```\n\nIf the file does not exist yet, create it with headers.\n\n### 7.2) Archive CSV Headers\n\n```\nparcel_code,provider_name,archive_date,boundary_coords,provider_notes,cadastre_code\n```\n\n### 7.3) Field Rules for Archiving\n\n| Field | Rule |\n|-------|------|\n| **parcel_code** | Assigned per §2.2–2.3. Always populated. |\n| **provider_name** | The name of the person/organization who provided this parcel. **MUST ask the user** for at least a name. If the user mentions a series of similar names, confirm with them before archiving. If they mention none of the names you suggest, treat it as a new provider. |\n| **archive_date** | Date of archiving in YYYY-MM-DD format |\n| **boundary_coords** | Full boundary string in the format `lon,lat;lon,lat;…` (same as Boundary CSV 经纬度 field). This is the canonical coordinate storage. |\n| **provider_notes** | Any additional notes about the provider or context; empty by default |\n| **cadastre_code** | Populate with **any official registration / cadastre / permit ID** from government documents, regardless of whether it is used as the `parcel_code`. This includes: mining cadastre numbers, land registration IDs, permit numbers, or any government-issued parcel identifier — from images, OCR, documents, or explicit user input. When `parcel_code` uses format 1 (`{CC}-{OFFICIAL_ID}`), the `{OFFICIAL_ID}` portion MUST also be stored here. Leave empty only when no official ID exists. The pipeline's `step2_assign_codes()` ensures this automatically when `official_id` is present. |\n\n### 7.4) Provider Name Workflow\n\n1. **At Step 1** (before any code assignment or file writing), ask the user: **\"Who provided this parcel? (请提供此地块的提供者姓名)\"**\n2. After the user provides a name, **immediately scan all existing providers** from both:\n   - `ovitalmap_archive/{CC}_parcels.csv` (per-country archive)\n   - `ovitalmap_archive/master.csv` (cross-country archive)\n3. **Proactive fuzzy deduplication** — compare the user-supplied name against every existing provider via `provider_matcher.py`. Accept the provider only when `exact_match` is found or after explicit user confirmation. The script returns:\n   - `exact_match`: the name if an exact match exists.\n   - `candidates`: list of `{name, reason, score}` sorted by score.\n   - `ambiguous`: `true` when there are **multiple candidates with equal scores** (i.e., the script cannot determine a definitive match — the LLM MUST ask the user).\n\n   Match types recognized by the script:\n   - **Exact match** (score 100): identical string after case-insensitive normalization and whitespace/punctuation removal (e.g., `\"Zhang San\"` ≈ `\"Zhang-San\"` ≈ `\"ZhangSan\"`). The script's `_normalize()` function handles this before comparison.\n   - **Chinese ↔ Pinyin match** (score 90): one is Chinese characters and the other is the corresponding pinyin (e.g., `\"张三\"` ≈ `\"zhangsan\"`).\n   - **Cross-language pinyin** (score 85): one name has Chinese with its pinyin matching the other's normalized form.\n   - **Substring overlap** (score 80): one name is fully contained within another, checked both with and without honorific stripping (e.g., `\"李总\"` ⊂ `\"中非李总\"`).\n   - **Honorific variation** (score 75): names differ only by a common Chinese honorific or prefix (e.g., `\"李总\"` ≈ `\"李\"` after stripping `\"总\"`).\n\n4. **Handle matches with mandatory user confirmation for non-exact matches:**\n   - **Exact match** (score 100 / reason `exact`): automatically reuse the existing `provider_name` spelling. No user confirmation needed.\n   - **Single candidate** (score ≥ 80, single candidate, not ambiguous): ask the user explicitly:\n     > **\"检测到提供者 '{input_name}' 与已有记录 '{existing_name}' 高度相似。是否为同一个人？\"**\n     - If the user confirms **same person** → reuse the existing `provider_name` spelling.\n     - If the user says **different person** → treat as a new provider.\n     - If the user is unsure → keep the new name but add a note in `provider_notes`: `Possible duplicate of '{existing_name}'.`\n   - **Low-confidence candidate** (score 50-79, single candidate, not ambiguous): ask the user but note the lower confidence:\n     > **\"检测到提供者 '{input_name}' 与已有记录 '{existing_name}' 可能相似（置信度较低）。是否为同一个人？\"**\n     - Same confirmation flow as above.\n   - **Multiple candidates / ambiguous** (e.g., user says `\"李总\"`, archive has `\"中非李总\"` and `\"三一李总\"`): **MUST list ALL candidates and ask the user to specify.** Do not guess:\n     > **\"'{input_name}' 在已有记录中匹配到多位提供者：① {candidate1}  ② {candidate2}。请问对应的是哪一位？或都不是(新建)？\"**\n     - If the user picks one → reuse that existing `provider_name`.\n     - If the user says none of them → treat as a new provider.\n   - **No match / score < 50**: automatically add as a new provider. No confirmation needed.\n\n5. If the user declines to provide a name, use `\"Unknown\"` and note it.\n6. **Do not proceed to code assignment until provider name is confirmed.**\n\n---\n\n## 8) Master Spreadsheet\n\nAfter archiving to `ovitalmap_archive/{CC}_parcels.csv`, **also append the same row(s)** to a single consolidated file:\n\n```\novitalmap_archive/master.csv\n```\n\nThis is a **single spreadsheet containing every parcel from every country** — the complete cross-country view.\n\n**Headers** (one extra column vs per-country `parcels.csv`):\n\n```\nCC,parcel_code,provider_name,archive_date,boundary_coords,provider_notes,cadastre_code\n```\n\nAppend every newly archived parcel row here immediately after writing to the per-country file. If `master.csv` does not exist, create it with headers.\n\n---\n\n## 9) Interaction Flow\n\n### Guard Rule\n\n**Do NOT write or modify any file until user confirms BOTH coordinates AND provider name.** Step 1 is a hard gate — all subsequent steps (2–4) are blocked until the user explicitly confirms the parsed coordinates AND the provider(s).\n\nWhen invoked, follow this sequence:\n\n### 1. Parse, Verify & Confirm Provider\n- Show raw coordinates and WGS84 conversion per parcel.\n- **Ask for the provider name(s)** (§7.4). Identify each parcel's provider.\n- Display ⚠️ **\"请核实以下识别和转换后的坐标是否与原始数据一致，并确认提供者姓名\"**.\n→ **STOP HERE. Wait for user to confirm or correct coordinates AND provider.** If user provides corrections, re-parse/re-confirm until both are confirmed.\n\n### 2b. Duplicate Check (MANDATORY — runs before code assignment)\n- **Determine country** from coordinates using your spatial knowledge, plus any country names in documents or user context. State it and move on.\n- Run `parcel_pipeline.py --step 2b` for each parcel.\n- **Archive-hit parcels**: reuse the **existing `parcel_code`** from the archive (no new code). Detect any official registration IDs from image text or user input; if the matched parcel has a generic date-code and no `cadastre_code` yet, update it via `archive_manager.py update_cadastre`. Display: `\"检测到地块坐标与已有记录 {matched_code} 一致，沿用归档编码。\"`.\n- **New parcels**: proceed to step 2.\n\n### 2. Assign Codes (only for new parcels, only after step 2b)\n- **Official registration IDs take priority**: if any parcel has a confirmed official registration / cadastre ID (from documents, OCR, or explicit user input), use format 1: `{CC}-{OFFICIAL_ID}` as the `parcel_code`. The `{OFFICIAL_ID}` is also stored as `cadastre_code`.\n- For parcels **without** an official ID: run `parcel_pipeline.py --step 2` to get format 2 sequential codes `{CC}-{YYMMDD}-{SEQ}`.\n- Display all assigned codes. The user will correct if wrong.\n\n### 3. Build CSVs (for ALL parcels)\nBuild **both** Vertices CSV (§4) and Boundary CSV (§5) for every parcel:\n- **New parcels**: batch CSV (e.g., `{firstCode}_N{count}_{timestamp}.csv` + `_boundary.csv`).\n- **Archive-hit parcels**: individual single-parcel CSVs (e.g., `{matchedCode}_N1_260609_143021.csv` + `_boundary.csv`) regenerated with updated Comment metadata.\n\nRun quality checks (§6). State the generated filenames:\n\n> CSV 文件已生成:\n> - 顶点表: `{firstCode}_N{count}_{timestamp}.csv`\n> - 边界表: `{firstCode}_N{count}_{timestamp}_boundary.csv`\n> \n> 已有地块:\n> - 顶点表: `{matchedCode}_N1_{timestamp}.csv`\n> - 边界表: `{matchedCode}_N1_{timestamp}_boundary.csv`\n\n### 4. Archive (only for new parcels)\n- Append to `ovitalmap_archive/{CC}_parcels.csv` and `ovitalmap_archive/master.csv`.\n- Summarize: provider, codes, date.\n\n### 5. Wrap Up\nNote any assumptions, edge cases, or corrections. Separately list archive-hit exports and any cadastre_code updates.\n\n---\n\n## 9b) Post-Archive Coordinate Correction\n\nUsers may correct a parcel's coordinates after it has been archived. When this happens:\n\n### Procedure\n\n1. **Identify the parcel** by its `parcel_code` in `ovi\n\nArchive v2.0.1: 10 files, 29157 bytes\n\nFiles: scripts/__init__.py (39b), scripts/archive_manager.py (17297b), scripts/country_locator.py (2539b), scripts/csv_builder.py (7750b), scripts/parcel_pipeline.py (15005b), scripts/provider_matcher.py (6795b), scripts/utils.py (6556b), skill-card.md (2150b), SKILL.md (27482b), _meta.json (139b)\n\nArchive v2.0.0: 10 files, 32419 bytes\n\nFiles: scripts/__init__.py (39b), scripts/archive_manager.py (17307b), scripts/country_locator.py (11889b), scripts/csv_builder.py (7589b), scripts/parcel_pipeline.py (14922b), scripts/provider_matcher.py (6795b), scripts/utils.py (7284b), skill-card.md (1994b), SKILL.md (26979b), _meta.json (139b)\n\nArchive v1.0.1: 3 files, 8886 bytes\n\nFiles: skill-card.md (2405b), SKILL.md (17644b), _meta.json (139b)\n\nArchive v1.0.0: 3 files, 8044 bytes\n\nFiles: skill-card.md (2143b), SKILL.md (15420b), _meta.json (139b)","readmeExcerpt":"Skill: OvitalMap Parcel CSV Owner: jeromeex Summary: Convert parcel boundaries into OvitalMap-compatible CSV files, assign stable parcel codes, and maintain deduplicated country and master archives. Use for WGS84, DMS, or UTM coordinates supplied as text or images, including archive re-exports and coordinate corrections. Do not use it as cadastral or legal validation. Tags: latest:3.0.1 Version history: v3.0.1 | 2026","codeSnippets":[],"executableExamples":[{"language":"json","snippet":"{\"vertices\":[[114.13472,22.50422],[114.13564,22.50411],[114.135,22.503]],\"provider_name\":\"Survey Team\",\"official_id\":null,\"altitude\":[]}"},{"language":"text","snippet":"{CC}-{OFFICIAL_ID}"},{"language":"text","snippet":"{CC}-{YYMMDD}-{SEQ}"},{"language":"text","snippet":"文件夹,名称,经度,纬度,海拔,文本显示风格,图标样式,Comment"},{"language":"text","snippet":"文件夹,名称,经纬度[经度+纬度],线条宽度,线条颜色,线条不透明度,闭合,线型,轨迹风格,Comment"},{"language":"text","snippet":"parcel_code,provider_name,archive_date,boundary_coords,provider_notes,cadastre_code"}],"parameters":null,"dependencies":[],"permissions":[],"extractedFiles":[{"path":"SKILL.md","content":"---\nname: ovitalmap-parcel-csv\ndescription: Convert parcel boundaries into OvitalMap-compatible CSV files, assign stable parcel codes, and maintain deduplicated country and master archives. Use for WGS84, DMS, or UTM coordinates supplied as text or images, including archive re-exports and coordinate corrections. Do not use it as cadastral or legal validation.\nlicense: MIT-0\nmetadata:\n  openclaw:\n    requires:\n      bins:\n        - python3\n    envVars:\n      - name: OVITALMAP_WORKSPACE\n        required: false\n        description: Directory for generated exports and archives; defaults to the current working directory.\n---\n\n# OvitalMap Parcel CSV\n\nUse the bundled Python scripts through JSON stdin/stdout. Do not recreate coordinate conversion, code allocation, CSV generation, or archive updates manually.\n\n## Input\n\nSet `OVITALMAP_WORKSPACE` to the directory where exports and archives should be stored. If it is unset, the scripts use the current working directory.\n\nEach parcel is a JSON object:\n\n```json\n{\"vertices\":[[114.13472,22.50422],[114.13564,22.50411],[114.135,22.503]],\"provider_name\":\"Survey Team\",\"official_id\":null,\"altitude\":[]}\n```\n\nUse WGS84 longitude, latitude order. For a batch, keep one country or region per pipeline run. The pipeline assigns stable `parcel_ref` values (`P01`, `P02`, and so on).\n\n## Workflow\n\n1. Extract and show the source coordinate text. When the source is an image, preserve the transcription for review.\n2. Convert decimal, DMS, or UTM coordinates with `scripts/coordinate_converter.py`. Supply the coordinate `format`; for decimal input also supply `order`, and for UTM supply `zone` and `hemisphere`.\n3. Show the resulting WGS84 vertices and obtain explicit confirmation of the coordinates and provider names. Do not write exports or archives before confirmation.\n4. Obtain the ISO 3166-1 alpha-2 country or region code from explicit context. Ask when it is uncertain.\n5. Run `python3 scripts/parcel_pipeline.py --step 1` with `parcels`, `country_code`, and optional `date` in `YYMMDD` form. Retain the returned `run_id`. On `needs_input`, request only the fields listed in `required_input`.\n6. Continue with the same `run_id`: run Step `2b` to classify archive hits and new parcels, then Step `2` to assign codes to new parcels.\n7. Show the proposed codes. After the user approves them, pass `confirmed_codes: true` to Step `3`.\n8. Deliver every path in `result.exports` in its returned order. Boundary files import into OvitalMap as tracks (`轨迹`); vertex files import as labels (`标签`).\n\nUse `--step all` only when the user has already confirmed the complete input and explicitly approved automatic code acceptance with `\"confirmed\": true` and `\"auto_accept_codes\": true`.\n\n## Parcel codes\n\nPrefer a confirmed official registration, cadastral, or permit identifier:\n\n```text\n{CC}-{OFFICIAL_ID}\n```\n\nWhen no official identifier is available, assign a stable archive code:\n\n```text\n{CC}-{YYMMDD}-{SEQ}\n```\n\nThe archive determines the next three-di"},{"path":"_meta.json","content":"{\n  \"ownerId\": \"kn76j7kby3cajgq933bwccdxbn82fw68\",\n  \"slug\": \"ovitalmap-parcel-csv\",\n  \"version\": \"3.0.1\",\n  \"publishedAt\": 1788527160108\n}"},{"path":"references/csv-contract.md","content":"# CSV Compatibility Contract\n\nDo not change this contract without an explicit migration request.\n\n## Encoding and filenames\n\n- Encoding: UTF-8, comma-separated, no BOM.\n- Directory: `ovitalmap_exports/{CC}/`.\n- Every generated file contains exactly one parcel.\n- Default boundary export: `{parcelCode}_{YYYYMMDD_HHMMSS}.csv`.\n- Explicit vertex export: `{parcelCode}_{YYYYMMDD_HHMMSS}_vertices.csv`.\n- Same-second collisions append `_02`, `_03`, and so on before `.csv` or `_vertices.csv`.\n\nFor multiple parcels, generate files in submitted `parcel_ref` order and do not combine them. Archive names remain `{CC}_parcels.csv` and `master.csv`.\n\nThe export modes are:\n\n- `boundary` (default): boundary file only.\n- `vertices`: vertex file only, and only after an explicit user request.\n- `both`: both files, only after an explicit user request for both.\n\n## Vertex CSV (顶点表)\n\nExact headers:\n\n```text\n文件夹,名称,经度,纬度,海拔,文本显示风格,图标样式,Comment\n```\n\n- 文件夹: parcel code.\n- 名称: `{parcel_code}_A01`, restarting at A01 for each parcel.\n- 经度/纬度: WGS84 longitude and latitude in original vertex order.\n- 海拔: input altitude or empty.\n- 文本显示风格: empty.\n- 图标样式: `1`.\n- Comment: `提供者:{provider} 归档日期:{YYYY-MM-DD}` and, when present, ` 地籍号:{cadastre_code}`.\n\n## Boundary CSV\n\nExact headers:\n\n```text\n文件夹,名称,经纬度[经度+纬度],线条宽度,线条颜色,线条不透明度,闭合,线型,轨迹风格,Comment\n```\n\n- 文件夹 and 名称: parcel code.\n- 经纬度: `lon,lat;lon,lat;...`; repeat the first point to close the polygon.\n- 线条宽度: `3`.\n- 线条颜色: `0X00FF0000`.\n- 线条不透明度: `50`.\n- 闭合: `1`.\n- 线型: `0`.\n- 轨迹风格: `1`.\n- Comment: same as the vertex CSV.\n\n## Archive schemas\n\nPer-country:\n\n```text\nparcel_code,provider_name,archive_date,boundary_coords,provider_notes,cadastre_code\n```\n\nMaster:\n\n```text\nCC,parcel_code,provider_name,archive_date,boundary_coords,provider_notes,cadastre_code\n```"},{"path":"references/interaction-and-edge-cases.md","content":"# Interaction and Edge Cases\n\n## Delivery\n\nSend or link the actual files in their returned order:\n\n```text\n1. {first_parcel_filename}\n2. {second_parcel_filename}\n```\n\nGive the import instruction once: open each boundary CSV in OvitalMap and choose `轨迹`. For vertex files, choose `标签`. If both modes were requested, distinguish them by the `_vertices` filename suffix.\n\n## Archive model\n\n- `{CC}_parcels.csv` is the country record.\n- `master.csv` is the all-in-one cross-country record.\n- New parcels update both in one locked commit.\n- Archive hits are re-exported without another append.\n- Corrections back up and update both records.\n\n## Parcel codes\n\nPrefer a confirmed official registration/cadastre/permit ID:\n\n```text\n{CC}-{OFFICIAL_ID}\n```\n\nOtherwise use:\n\n```text\n{CC}-{YYMMDD}-{SEQ}\n```\n\nThe archive allocates sequence continuity. An existing official code is blocking and requires user review; do not silently fall back to a sequential code.\n\n## Archive hits\n\n- Reuse the archived parcel code and provider metadata.\n- Export only that parcel as its own file in the requested export mode.\n- Do not append it again.\n- If a newly supplied official ID fills an empty cadastre field, update it during Step 3.\n- If the user insists identical coordinates represent a different parcel, require explicit confirmation and set `allow_duplicate_coordinates: true` with a note naming the matched code.\n\nFor a mixed batch, preserve the original `parcel_ref` order across archive hits and new parcels. Export each parcel separately; do not group the delivered files by archive status.\n\n## Multi-parcel batches\n\n- Keep `parcel_ref` stable from intake through replies, CSV generation, and archive results. Numeric positions remain accepted only for backward-compatible input.\n- Generate one file per parcel for the requested mode and return the files in `parcel_ref` order. If both modes were requested, keep each parcel's normal file immediately before its `_vertices` file.\n- Use one country/region per pipeline run. If parcel-level country codes differ, split the batch and preserve each parcel's ref.\n- Report all current parcel-specific problems together in the user's language.\n- If two submitted parcels have identical boundaries, request `duplicate_resolutions.{parcel_ref}`:\n  - `same`: skip the later duplicate.\n  - `different`: keep both, record explicit confirmation, and allow the duplicate boundary during archive commit.\n- Reject duplicate non-empty official IDs before code allocation. Use `official_id_resolutions.{parcel_ref}` to correct or clear the later value.\n- Never drop an unresolved parcel from run state. No CSV or archive write may occur while a batch conflict remains.\n\n## Provider matching\n\n- Exact normalized match: reuse automatically.\n- No match: keep the supplied provider.\n- Never merge providers based on similarity alone.\n\n## Corrections\n\nUse `archive_manager.py` action `correct` with `country_code`, `parcel_code`, and `new_vertices`. The operation must:\n\n1. Validate "},{"path":"references/workflow-contract.md","content":"# Workflow Contract\n\nEvery pipeline response contains:\n\n```text\nstatus: needs_input | ready | completed | blocked\nnext_action: machine-readable next step\nrequired_input: exact missing confirmations or values\nmessage: concise user-facing summary\nresult: structured evidence and file paths\n```\n\n## Agent behavior\n\n- `needs_input`: show the message and relevant coordinate or code preview, ask only for `required_input`, and stop.\n- `ready`: report the result and perform `next_action` when it requires no new user decision.\n- `completed`: deliver every item in `result.exports` in order and give the appropriate OvitalMap import instruction.\n- `blocked`: explain the message, make no success claim, and wait for corrected input or retry safely.\n\nRespond in the user's language. Do not expose run state or raw JSON unless the user asks for technical details.\n\n## Confirmation gates\n\nThe pipeline must not pass these gates implicitly:\n\n- `confirmed_coordinates`: the user verified the displayed WGS84 vertices.\n- `country_code`: the country or region is known rather than guessed.\n- `provider_resolutions.{parcel_ref}`: a missing or ambiguous provider is resolved per parcel.\n- `duplicate_resolutions.{parcel_ref}`: identical submitted boundaries are confirmed as `same` or `different`.\n- `official_id_resolutions.{parcel_ref}`: duplicate official identifiers are corrected or cleared.\n- `confirmed_codes`: the user approved generated parcel codes before Step 3.\n- `auto_accept_codes`: explicit permission for non-interactive `--step all`.\n\n`export_mode` is not a confirmation gate. It defaults to `boundary` and must remain unchanged throughout a run unless the user explicitly requests another mode.\n\nUse stable parcel references in decisions:\n\n```json\n{\"provider_resolutions\":{\"P01\":\"Survey Team\"},\"duplicate_resolutions\":{\"P02\":\"different\"}}\n```\n\nUse `parcel_ref` keys for every per-parcel decision."}],"languages":[],"docsSourceLabel":"CLAWHUB","editorialOverview":null,"editorialQuality":{"score":100,"threshold":65,"status":"thin","wordCount":2167,"uniquenessScore":39,"reasons":["uniqueness-below-45"]}},"media":{"evidence":{"source":"no-media","verified":false,"confidence":"low","updatedAt":"2026-10-11T06:50:12.624Z","emptyReason":"No screenshots, media assets, or demo links are available."},"primaryImageUrl":null,"mediaAssetCount":0,"assets":[],"demoUrl":null},"ownerResources":{"evidence":{"source":"unclaimed","verified":false,"confidence":"low","updatedAt":"2026-10-11T06:50:12.624Z","emptyReason":"This page has not been claimed by the agent owner."},"hasCustomPage":false,"customPageUpdatedAt":null,"customLinks":[],"structuredLinks":{"docsUrl":null,"demoUrl":null,"supportUrl":null,"pricingUrl":null,"statusUrl":null},"customPage":null},"relatedAgents":{"evidence":{"source":"protocol-neighbors","verified":false,"confidence":"medium","updatedAt":"2026-10-11T10:50:23.842Z","emptyReason":null},"items":[{"id":"8ebccd8e-3863-4187-8355-c3f14e1f9edf","entityType":"agent","canonicalPath":"/agent/iofficeai-aionui","slug":"iofficeai-aionui","name":"AionUi","description":"Free, local, open-source 24/7 Cowork app and OpenClaw for Gemini CLI, Claude Code, Codex, OpenCode, Qwen Code, Goose CLI, Auggie, and more | 🌟 Star if you like it!","url":"https://github.com/iOfficeAI/AionUi","homepage":"https://www.aionui.com","source":"GITHUB_REPOS","protocols":["MCP","OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-10-09T19:11:12.944Z","createdAt":"2026-02-25T03:38:16.584Z","downloads":null},{"id":"b917f68a-ebff-438e-84f8-3f4b2494c0bc","entityType":"agent","canonicalPath":"/agent/activepieces-activepieces","slug":"activepieces-activepieces","name":"activepieces","description":"AI Agents & MCPs & AI Workflow Automation • (~400 MCP servers for AI agents) • AI Automation / AI Agent with MCPs • AI Workflows & AI Agents • MCPs for AI Agents","url":"https://github.com/activepieces/activepieces","homepage":"https://www.activepieces.com","source":"GITHUB_REPOS","protocols":["OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-04-15T02:22:12.426Z","createdAt":"2026-02-25T03:38:12.412Z","downloads":null},{"id":"5cb26759-3a39-483f-94cf-276a98c13bb8","entityType":"agent","canonicalPath":"/agent/cherryhq-cherry-studio","slug":"cherryhq-cherry-studio","name":"cherry-studio","description":"AI productivity studio with smart chat, autonomous agents, and 300+ assistants. Unified access to frontier LLMs","url":"https://github.com/CherryHQ/cherry-studio","homepage":"https://cherry-ai.com","source":"GITHUB_REPOS","protocols":["MCP","OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-04-11T14:38:40.986Z","createdAt":"2026-02-25T03:38:19.379Z","downloads":null},{"id":"6f6582d0-5d76-4f0f-b81d-86520247950b","entityType":"agent","canonicalPath":"/agent/copilotkit-copilotkit","slug":"copilotkit-copilotkit","name":"CopilotKit","description":"The Frontend for Agents & Generative UI. React + Angular","url":"https://github.com/CopilotKit/CopilotKit","homepage":"https://docs.copilotkit.ai","source":"GITHUB_REPOS","protocols":["OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-03-25T09:50:57.846Z","createdAt":"2026-02-25T03:39:14.617Z","downloads":null}],"links":{"hub":"/agent","source":"/agent/source/clawhub","protocols":[{"label":"OpenClaw","href":"/agent/protocol/openclew"}]}}}