Triage US residential real-property assessment review or appeal requests and prepare evidence packets when market value is a material ground. From an address and notice value, separates market, appraised, assessed, equalized, and taxable values; verifies jurisdiction-specific rules and valuation dates; analyzes comparable sales with APNs, stable transaction IDs, and contrary evidence; estimates a supportable requested value; and produces upload-ready English Markdown and PDF. Use for market-value informal reviews, decline-in-value or Proposition 8 requests, protests, grievances, abatements, comparable-sales packages, and defensible reduced-value estimates. Also use to identify the current authority, form, and deadline for unequal or non-uniform appraisal, exemption, classification, ownership, special valuation, or another non-market ground, but stop before comparable-sale valuation or packet generation for those grounds.
74
93%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
View guide
Passed
No findings from the security scan
Start real work from the fail-closed assets/case-template.json; its human-review, appeal-ground,
residential-use, and contrary-review gates intentionally fail until verified. Use
assets/case-example.json only as a fictional completed example and deterministic test fixture.
Never preserve its passing attestations in a real case. Version 2 deliberately replaces the
ambiguous v1 fields initial_assessed_value, requested_value, and likely_value_range.
Required:
schema_version: Exact string 2.0caseselection_policycomparablesrejected_comparablescontrary_evidence_reviewsourcescaseRequired core fields:
review_titleappeal_typeappeal_ground: Exact string market_value; the builder rejects unequal/non-uniform appraisal, exemption, classification, ownership, and other grounds that require a different evidence modeldocument_mode: informal_review_attachment, formal_board_evidence, protest_statement, grievance_support, abatement_support, or tribunal_exhibitproperty_address, apn, and assessment_yearvaluation_date and prepared_date: ISO YYYY-MM-DDvalue_basislikely_comparison_value_range.low and .highjurisdictionpropertyvaluation_rationalesubject_source_ids and assessment_source_idsverificationOptional narrative fields include owner_name, argument_points, special_factors, and suggested_attachments.
When present, owner_name must be a nonempty string or null; numeric and boolean stand-ins are
invalid. A provided name is rendered visibly in the shared subject table in both formats. PDF
Author metadata remains the generic Property owner so a name is never disclosed only through
hidden metadata.
case.propertyThe builder is limited to residential real property. In addition to the physical fields, every
case must include residential_use_verification with:
status: Exact string verified_residential; use another workflow and do not generate a packet
when the subject is non-residential or its use has not been verifiedclassification: The residential-use description reported by the cited parcel sourcesource_ids: Nonempty source list that collectively includes the parcel_record roleThis explicit, sourced verification avoids unreliable nationwide inference from free-form
property_type labels. parking and development_or_hoa, when present, must be nonempty strings
or null.
case.value_basisRequired:
comparison_basis_kind: Exact string sale_comparable_market_value; this explicit designation prevents a locally labeled appraised, assessed, or taxable amount from being compared with sales by inferencecomparison_value_type: fair_market_value, market_value, just_value, true_value, actual_value, estimated_market_value, or full_cash_valuecomparison_value_label: Exact human-readable jurisdiction termcurrent_comparison_value: Positive market-oriented value to compare with salesrequested_comparison_value: Positive requested amount, not above the current comparison valueprimary_notice_value_id: ID of the node corresponding to the value supplied by the ownernotice_values: Nonempty array of sourced notice-value nodessource_ids: Must collectively include assessment_notice and valuation_rule rolesEach notice-value node requires:
id: Unique 1-40 character identifiervalue_type: Any comparison category plus appraised_value, assessed_value, equalized_assessed_value, state_equalized_value, limited_property_value, or taxable_valuelabel and authority: Exact notice term and taxing/assessing authoritycurrent_value: Nonnegative amount, including zero when the official record supports itrequested_value: Nonnegative amount or null when the authority must recalculate itsource_ids: Must include assessment_noticederivation.kind: same_as_source, ratio, cap, equalization, exemption, classification, authority_specific, or reported_onlyderivation.source_value_id: comparison_value or another notice-node IDderivation.factor: Positive number only for ratio; otherwise nullderivation.description: Case-specific explanation of the transformationderivation.source_ids: Must include valuation_ruleThe builder rejects cycles and transformations outside its directed type matrix.
same_as_source requires the same value type and amount. ratio converts a market-value source
to an appraised, assessed, or limited-property target; it also supports sourced
appraised_value -> assessed_value and limited_property_value -> assessed_value chains such as
Arizona's statutory assessment percentage. A ratio uses a factor no greater than 1 and must
reconcile mechanically within normal rounding tolerance. cap runs from market value to an
appraised/assessed category, from appraised to assessed or limited value, or from assessed to
limited value; it cannot run backward. classification runs from market value to appraised or
assessed value. equalization runs from an assessed category to an equalized category, or from
equalized assessed value to state-equalized value. exemption and authority_specific can reduce
an assessed/equalized value to taxable value; authority-specific taxable-to-taxable links are also
allowed. Caps, classifications, exemptions, and authority-specific transformations cannot increase
either the current or requested amount. Use reported_only when the source reports both values but
no supported mechanical relationship is known. For every other derivation kind, a child
requested_value must remain null when its source requested_value is null.
Every non-null notice-node requested_value must also be no greater than that node's own
current_value; an appeal packet cannot silently request an increase in an assessed or taxable
notice value.
case.verificationEach boolean must be set to true only after the named human check is complete:
official_rules_recheckedsubject_facts_reconciledvalue_basis_reconciledcomparable_sales_verifiedcontrary_evidence_reviewedofficial_rules_current_as_of must be an ISO date equal to case.prepared_date. These are preparer attestations; the script cannot independently prove that a source is authentic or legally controlling.
case.jurisdictionRequired:
country: USstate and state_code, including DCcounty_or_localityroute_family: one documented in appeal-routes.mdappeal_stage, filing_authority, and valuation_standardfiling_deadline: fixed ISO date or nullfiling_deadline_ruleofficial_form_required, official_form_name, and official_form_urlsubmission_urlinformal_preserves_formal_deadline: true, false, or nullsource_ids: Must collectively include appeal_rule, submission_rule, and valuation_ruledeadline_source_ids: Must include deadline_ruleThe route must match the state registry. A verified local exception requires route_override.reason and sourced route_override.source_ids with appeal_rule role. A fixed deadline before prepared_date is rejected.
official_form_name and official_form_url must be null when absent. When present, the name
must be a nonempty string and the URL must satisfy the canonical public-HTTPS rules, even when an
official form is not required for the current stage.
declaration: null by default; otherwise exact owner-reviewed textdeclaration_owner_approved: Strict boolean, default falseinclude_signature_block: Strict boolean, default falseA declaration is rendered only when approval is exactly true. Signature lines require an approved declaration. Strings such as "false" are invalid.
selection_policystrict_bed_bath_matchstrict_property_type_matchexclude_above_current_comparison_value: Advocacy-table filter applied only after neutral candidate reviewallow_provisional_range_pricesminimum_comps and maximum_compslegal_sale_window.start_date and .end_datelegal_sale_window.basislegal_sale_window.source_ids: Must include sale_window_ruleThe v1 max_post_valuation_days shortcut is rejected because no universal nationwide post-valuation window exists.
comparablesRequired for every selected comparable:
address, apn, transaction_id, sale_date, and sale_price; sale_price must be stated in whole dollars, and transaction_id must be a stable recorder instrument, deed, MLS transaction, or equivalent source record identifierprice_source_kind: exact_closed_price or range_lower_boundproperty_type, bedrooms, bathrooms, and living_area_sqftarm_length_status: Must be verified or likelyrelevancesource_ids: Must collectively include parcel_record and transaction_recordRecommended:
same_development, distance_miles, and year_builtreported_price_range.low and .high when using range_lower_bound; both endpoints must be stated in whole dollars, and sale_price must equal .lowThe builder computes price per square foot. A provisional lower endpoint is labeled as such and is never described as exact consideration. Range evidence is treated as an interval; only exact prices enter a median, and at least two exact prices are required before a central point statistic is printed.
rejected_comparablesRecord every plausible candidate omitted after neutral review. Required:
address, apn, transaction_id, sale_date, sale_price, price_source_kind, property_type, bedrooms, bathrooms, living_area_sqft, relevance, and source_ids fields used for selected comparablesvaluation_status: valuation_eligible_omitted or research_only_inadmissiblereasons: Nonempty standardized-reason listrelevance_review: Specific comparison with the subject and selected setmaterially_contrary: Strict booleansource_ids: Valuation-eligible rows must collectively include parcel_record and
transaction_record; every research-only row requires parcel_record, with reason-specific
transaction-source rules described belowRecommended physical and transaction fields are also the same as selected comparables.
valuation_eligible_omitted rows must remain inside the sourced legal sale window, have verified
or likely arm's-length status, and participate in neutral-pool arithmetic. A
research_only_inadmissible row remains in the audit ledger but is excluded from every anchor,
interval count, span, and median. It must use at least one inadmissibility reason and set
materially_contrary to false. An inadmissibility label is not sufficient by itself: the row
facts must support the reason. non_arm_length and non_market_transfer require
arm_length_status: not_arm_length; outside_legal_sale_window requires a date actually outside
the sourced window; and unverified_transaction requires unknown arm's-length status, a
provisional range, a parcel_record source, and no source claiming the transaction_record role.
Non-arm's-length, non-market, out-of-window, and duplicate reasons require both parcel and
transaction-record sources. duplicate_record requires duplicate_of_transaction_id; it must
reference the same earlier transaction_id, and the address, APN, sale date, price kind,
whole-dollar price, and whole-dollar range must match exactly. A repeated APN with a different
transaction ID or transaction facts is a distinct sale, not a duplicate. Allowed reasons are:
above_current_comparison_valuebed_bath_mismatchliving_area_mismatchage_mismatchlocation_mismatchcondition_mismatchhoa_context_mismatchproperty_type_mismatchnon_arm_lengthnon_market_transferunverified_transactionoutside_legal_sale_windowduplicate_recordcontrary_evidence_reviewRequired:
completed: Must be trueall_plausible_candidates_recorded: Must be truesummary: Neutral description of higher and otherwise contrary evidence reviewedsource_ids: Must collectively include parcel_record and transaction_recorddisclosure: Required when any rejected comparable has materially_contrary: true; otherwise nullableThe builder applies one relevance score to selected and valuation-eligible omitted candidates. If
an eligible omitted candidate scores at least as highly as the best selected candidate,
materially_contrary must be true and disclosure is mandatory. Eligible omitted candidates
participate in neutral-pool interval arithmetic; research-only inadmissible rows never do.
All candidates tied for the highest score are rendered as co-best candidates in a deterministic
transaction-identity order independent of advocacy-table status.
sourcesEach source requires:
id: 1-40 letters, digits, dots, underscores, or hyphenssource_kind: public_url or owner_attachmenttitle and publisher: Safe descriptive text, never a file path or private locatorurl: A canonical public https URL for public_url; exactly null for owner_attachmentaccessed_date: ISO date no later than prepared_date; this is the review date for an owner attachmentsupports: Nonempty fact listroles: Nonempty typed-role listAn owner_attachment represents a notice, report, letter, MLS closed-sale sheet, closing
disclosure, or other evidence the owner supplied without copying its contents, local path, portal
URL, signed link, or another private locator into the case JSON. It may use only
assessment_notice, marketability_evidence, and transaction_record roles. A private
transaction_record may establish the closed-sale facts for a selected or valuation-eligible
omitted comparable, but that row must also cite a separate public parcel_record. The output uses
a fixed label stating that the attachment is not embedded and must be filed separately.
owner_attachment cannot establish parcel/residential classification, valuation transformations,
appeal rules, sale windows, deadlines, or submission requirements; those roles continue to require
public sources. Unknown fields are rejected throughout the case schema so a locator cannot be
hidden in an ad hoc local_path or similar property.
Allowed roles:
appeal_ruleassessment_noticedeadline_rulemarketability_evidenceparcel_recordsale_window_rulesubmission_ruletransaction_recordvaluation_rulePublic URLs with embedded credentials, query strings, fragments, control characters, backslashes,
percent-encoded authorities, malformed or lowercase percent escapes, encoded unreserved path
characters, noncanonical Unicode/IDNA authorities, raw non-ASCII paths, IANA special-use domains,
or non-public-unicast IP forms are rejected. This includes browser-compatible short and integer
IPv4 forms, Unicode dot separators, fullwidth digits, IANA special-purpose IPv4/IPv6 ranges,
multicast, transition addresses, and local NAT64 forms. The policy uses frozen address tables so
results do not change with the Python interpreter's ipaddress version. The builder never fetches
URLs. Separate research tooling must use an SSRF-protected connector or resolve once, pin the
connection to a validated numeric address while preserving SNI and Host, verify the peer, and
repeat that process for every redirect. A preflight lookup followed by an ordinary second DNS
resolution is not sufficient. For private owner documents, use owner_attachment with url: null,
a locator-free title and fact description, and attach the actual document separately through the
official filing channel.
The CLI reads at most 5 MiB of UTF-8 case JSON and rejects nesting deeper than 100 containers
before parsing. Duplicate object keys and Unicode surrogate code points are rejected instead of
being accepted into an output-bound structure. Selected comparables are capped at 20, rejected
candidates at 100, sources at 200, and selection_policy.maximum_comps at 20. Validation reports
at most 200 detailed errors plus one suppression summary. Malformed, oversized, ambiguous, and
recursively nested inputs return bounded errors without a traceback.