{
  "specVersion": "0.1",
  "status": "draft",
  "statusMeaning": "Published for public review and implementation. Field names and enumerations may change in 0.2; every 0.1 URL and artifact stays permanently available.",
  "datePublished": "2026-09-10",
  "dateModified": "2026-09-10",
  "license": "https://creativecommons.org/licenses/by/4.0/",
  "licenseName": "CC BY 4.0",
  "canonicalUrl": "https://www.bidbro.com/scopespec/v0-1",
  "schemaUrl": "https://www.bidbro.com/data/scopespec/scopespec-0.1.schema.json",
  "citationUrl": "https://www.bidbro.com/data/scopespec/CITATION.cff",
  "reviewer": {
    "name": "Ben Davis",
    "title": "Spokesperson, BidBro",
    "email": "ben.davis@bidbro.com"
  },
  "abstract": "ScopeSpec is an open, versioned field list for a comparable residential project brief. It defines what a homeowner must state about a job, and what a contractor's quote must return, so that two quotes for the same project can be compared line for line instead of by headline price alone.",
  "conformance": [
    {
      "id": "C1",
      "rule": "A conforming brief includes every field marked required in the core groups, and every field marked required by its declared trade profile.",
      "detail": "A brief that omits a required field is not a ScopeSpec brief. It may still be a useful brief — the standard makes no claim about briefs outside it."
    },
    {
      "id": "C2",
      "rule": "Every quantity carries a unit and a measurementMethod.",
      "detail": "A number without a stated unit and without how it was arrived at is the single most common cause of two quotes not being comparable. 'Roughly 1,800 square feet, paced off' and '1,812 square feet, from the plat' are both acceptable; a bare '1800' is not."
    },
    {
      "id": "C3",
      "rule": "Anything not stated as included is excluded, and the brief must say so explicitly in scope.exclusions.",
      "detail": "The default direction matters. A brief silent on debris haul-away is read by one bidder as included and another as extra; the standard forces the question to be answered once, by the person writing the brief."
    },
    {
      "id": "C4",
      "rule": "An allowance is a stated budget for an undecided selection, and must carry an amount, a currency and what it covers.",
      "detail": "An allowance without an amount is not an allowance, it is an unpriced hope. Bidders must be able to add identical allowances to identical base prices."
    },
    {
      "id": "C5",
      "rule": "A conforming quote states its priceBasis and repeats the brief's assumptions it accepts, listing separately any it restates.",
      "detail": "This is what makes comparison possible at all. Two fixed prices against different assumption sets are two different jobs, and the restated assumptions are where that difference becomes visible."
    },
    {
      "id": "C6",
      "rule": "A brief carries no street address, no homeowner name, no telephone number and no email address.",
      "detail": "Location is stated to postal-code granularity. A brief is a document that gets forwarded, so it is defined from the start to be safe to forward. Contact routing belongs to whatever platform carries the brief, not to the brief."
    }
  ],
  "fieldGroups": [
    {
      "id": "spec",
      "title": "Document identity",
      "purpose": "Says which version of the standard a reader is holding, so a brief written today is still interpretable when 0.2 exists.",
      "fields": [
        {
          "name": "specVersion",
          "type": "string",
          "required": true,
          "definition": "The ScopeSpec version this brief conforms to. `0.1` for this version.",
          "example": "0.1"
        },
        {
          "name": "briefId",
          "type": "string",
          "required": true,
          "definition": "An identifier unique within whoever issued the brief. Opaque; carries no personal information.",
          "example": "bb-2026-000412"
        },
        {
          "name": "created",
          "type": "date",
          "required": true,
          "definition": "ISO 8601 date the brief was first issued.",
          "example": "2026-09-10"
        },
        {
          "name": "revision",
          "type": "integer",
          "required": true,
          "definition": "Increments every time the brief changes after it has been sent to anyone. Bidders quote a revision, not a brief.",
          "example": "1"
        },
        {
          "name": "locale",
          "type": "string",
          "required": false,
          "definition": "BCP 47 language tag for the prose fields.",
          "example": "en-US"
        }
      ]
    },
    {
      "id": "project",
      "title": "The project",
      "purpose": "What is being asked for, in the words of the person asking, plus the timing constraints that change a price.",
      "fields": [
        {
          "name": "tradeProfile",
          "type": "enum:tradeProfile",
          "required": true,
          "definition": "The trade profile whose additional required fields apply. `other` is valid and imposes no extra fields.",
          "example": "roofing-replacement"
        },
        {
          "name": "summary",
          "type": "string",
          "required": true,
          "definition": "One to three sentences describing the work in plain language. Not a specification — the fields below are the specification.",
          "example": "Replace the asphalt shingle roof on a two-storey house, including new underlayment and all flashing."
        },
        {
          "name": "motivation",
          "type": "string",
          "required": false,
          "definition": "Why the work is being done. Changes what a good contractor proposes: an active leak and a planned sale lead to different recommendations.",
          "example": "Active leak over the back bedroom after the August storm."
        },
        {
          "name": "desiredStart",
          "type": "date",
          "required": false,
          "definition": "Earliest acceptable start date, if there is one.",
          "example": "2026-10-01"
        },
        {
          "name": "schedulingFlexibility",
          "type": "enum:schedulingFlexibility",
          "required": true,
          "definition": "How much the start date can move. A hard deadline is a price input and must not be discovered at contract stage.",
          "example": "flexible"
        },
        {
          "name": "budgetStated",
          "type": "boolean",
          "required": true,
          "definition": "Whether the brief states a budget at all. Stating `false` is a legitimate and common answer.",
          "example": "false"
        }
      ]
    },
    {
      "id": "property",
      "title": "The property",
      "purpose": "The physical facts that change the work, at a granularity that cannot identify the household.",
      "fields": [
        {
          "name": "propertyType",
          "type": "enum:propertyType",
          "required": true,
          "definition": "The kind of dwelling.",
          "example": "single-family-detached"
        },
        {
          "name": "postalCode",
          "type": "string",
          "required": true,
          "definition": "Postal code only. Never a street address — see conformance rule C6.",
          "example": "23451"
        },
        {
          "name": "locality",
          "type": "string",
          "required": true,
          "definition": "City or town name.",
          "example": "Virginia Beach"
        },
        {
          "name": "region",
          "type": "string",
          "required": true,
          "definition": "State or province code.",
          "example": "VA"
        },
        {
          "name": "yearBuilt",
          "type": "integer",
          "required": false,
          "definition": "Year of original construction, if known. Drives code, material and hazard assumptions.",
          "example": "1972"
        },
        {
          "name": "stories",
          "type": "integer",
          "required": false,
          "definition": "Number of storeys above grade. An access and labour input on every exterior trade.",
          "example": "2"
        },
        {
          "name": "occupiedDuringWork",
          "type": "boolean",
          "required": true,
          "definition": "Whether the household will be living in the property while the work runs. Changes sequencing, dust control and working hours.",
          "example": "true"
        },
        {
          "name": "petsOnSite",
          "type": "boolean",
          "required": false,
          "definition": "Whether animals will be present. A gate-and-containment question, not a courtesy field.",
          "example": "true"
        }
      ]
    },
    {
      "id": "scope",
      "title": "Scope — inclusions, exclusions, allowances",
      "purpose": "The heart of the standard. Comparability fails here more often than anywhere else, and it fails silently.",
      "fields": [
        {
          "name": "inclusions",
          "type": "string[]",
          "required": true,
          "definition": "Every item of work the homeowner intends to be part of the price. One item per entry, written as a deliverable rather than a task.",
          "example": "[\"Tear off existing shingles to deck\", \"Replace all step and valley flashing\"]"
        },
        {
          "name": "exclusions",
          "type": "string[]",
          "required": true,
          "definition": "Work explicitly NOT in the price. Required even when empty, because an empty exclusions list is itself a statement — see conformance rule C3.",
          "example": "[\"Gutter replacement\", \"Interior ceiling repair\"]"
        },
        {
          "name": "allowances",
          "type": "allowance[]",
          "required": true,
          "definition": "Budgets for selections not yet made. Required even when empty.",
          "example": "[{\"item\": \"Shingle upgrade to architectural\", \"amount\": 1200, \"currency\": \"USD\", \"covers\": \"material only\"}]"
        },
        {
          "name": "siteConditions",
          "type": "string[]",
          "required": true,
          "definition": "Known conditions a bidder would otherwise discover on site: soft decking, prior repairs, drainage, slope, known asbestos or lead, tight side yards.",
          "example": "[\"Two areas of soft decking noted over the garage\"]"
        },
        {
          "name": "accessConstraints",
          "type": "string[]",
          "required": true,
          "definition": "Anything limiting how crews, materials or a dumpster reach the work. Required even when empty.",
          "example": "[\"No driveway dumpster — HOA prohibits street placement\"]"
        },
        {
          "name": "debrisHandling",
          "type": "enum:responsibility",
          "required": true,
          "definition": "Who removes and disposes of debris. The most commonly assumed-both-ways line item in residential work.",
          "example": "contractor"
        },
        {
          "name": "cleanupStandard",
          "type": "enum:cleanupStandard",
          "required": false,
          "definition": "The condition the site is returned in.",
          "example": "broom-clean"
        }
      ]
    },
    {
      "id": "measurements",
      "title": "Measurements",
      "purpose": "Quantities with units and provenance. A quantity whose origin is unstated cannot be checked, and an unchecked quantity is the usual reason two prices differ by a third.",
      "fields": [
        {
          "name": "quantities",
          "type": "quantity[]",
          "required": true,
          "definition": "Each measurement the trade profile requires, plus any others that matter. Every entry carries name, value, unit, measurementMethod and confidence.",
          "example": "[{\"name\": \"roofArea\", \"value\": 2400, \"unit\": \"sqft\", \"measurementMethod\": \"aerial-report\", \"confidence\": \"measured\"}]"
        },
        {
          "name": "quantitiesVerifiedBy",
          "type": "enum:responsibility",
          "required": true,
          "definition": "Who is responsible for confirming the quantities before the price becomes binding.",
          "example": "contractor"
        }
      ]
    },
    {
      "id": "materials",
      "title": "Materials and selections",
      "purpose": "Whether the selections are made, who buys them, and what remains an allowance.",
      "fields": [
        {
          "name": "selectionsComplete",
          "type": "boolean",
          "required": true,
          "definition": "Whether every material selection has been made. `false` is normal and must be paired with allowances.",
          "example": "false"
        },
        {
          "name": "specifiedItems",
          "type": "specifiedItem[]",
          "required": true,
          "definition": "Items already chosen, named specifically enough to price. Required even when empty.",
          "example": "[{\"item\": \"Shingle\", \"specification\": \"CertainTeed Landmark, Weathered Wood\", \"suppliedBy\": \"contractor\"}]"
        },
        {
          "name": "ownerSuppliedItems",
          "type": "string[]",
          "required": true,
          "definition": "Anything the homeowner will supply. Required even when empty — an unstated owner-supplied item is a schedule risk nobody priced.",
          "example": "[]"
        }
      ]
    },
    {
      "id": "permits",
      "title": "Permits and approvals",
      "purpose": "Permit assumptions stated up front, because a permit assumption discovered late moves both price and schedule.",
      "fields": [
        {
          "name": "permitAssumedRequired",
          "type": "enum:tristate",
          "required": true,
          "definition": "Whether the brief assumes a permit is required. `unknown` is an honest and common answer, and is treated as a question for the bidder rather than a defect.",
          "example": "yes"
        },
        {
          "name": "permitPulledBy",
          "type": "enum:responsibility",
          "required": true,
          "definition": "Who applies for and pays for the permit under this brief's assumptions.",
          "example": "contractor"
        },
        {
          "name": "jurisdiction",
          "type": "string",
          "required": false,
          "definition": "The permitting authority, where the homeowner knows it.",
          "example": "City of Virginia Beach Planning Department"
        },
        {
          "name": "hoaApprovalRequired",
          "type": "enum:tristate",
          "required": true,
          "definition": "Whether an HOA or architectural review approval is needed.",
          "example": "no"
        },
        {
          "name": "inspectionsExpected",
          "type": "string[]",
          "required": false,
          "definition": "Inspections the homeowner expects, where known.",
          "example": "[\"Sheathing/nailing inspection\", \"Final\"]"
        }
      ]
    },
    {
      "id": "documents",
      "title": "Photos and documents",
      "purpose": "What evidence accompanies the brief. A brief with no photographs is quoted more cautiously, and the caution is priced.",
      "fields": [
        {
          "name": "photos",
          "type": "documentRef[]",
          "required": true,
          "definition": "Photographs supplied. Each entry states what the photo shows; a URL is optional and may be omitted for a brief that travels outside the issuing platform.",
          "example": "[{\"documentType\": \"photo\", \"describes\": \"Rear elevation, full roof plane\"}]"
        },
        {
          "name": "drawings",
          "type": "documentRef[]",
          "required": true,
          "definition": "Plans, sketches or measured drawings. Required even when empty.",
          "example": "[]"
        },
        {
          "name": "reports",
          "type": "documentRef[]",
          "required": true,
          "definition": "Inspection reports, engineer's letters, prior estimates being replaced. Required even when empty.",
          "example": "[{\"documentType\": \"report\", \"describes\": \"2026 home inspection, roof section\"}]"
        }
      ]
    },
    {
      "id": "assumptions",
      "title": "Stated assumptions",
      "purpose": "The list every bidder must accept or restate. This is the mechanism that converts a difference in reading into a visible difference on the page.",
      "fields": [
        {
          "name": "assumptions",
          "type": "string[]",
          "required": true,
          "definition": "One assumption per entry, written so it can be accepted or contradicted without ambiguity.",
          "example": "[\"Existing decking is sound except where noted in siteConditions\", \"Work proceeds in a single mobilisation\"]"
        }
      ]
    },
    {
      "id": "bidComparison",
      "title": "What a conforming quote returns",
      "purpose": "The response half of the standard. A brief that does not say what a comparable answer looks like has only solved half the problem.",
      "fields": [
        {
          "name": "priceBasis",
          "type": "enum:priceBasis",
          "required": true,
          "definition": "How the price is constructed. Two prices on different bases are not comparable and must not be presented as if they were.",
          "example": "fixed-price"
        },
        {
          "name": "priceTotal",
          "type": "number",
          "required": true,
          "definition": "The total for the scope as quoted, in the stated currency, exclusive of allowances listed separately.",
          "example": "18400"
        },
        {
          "name": "currency",
          "type": "string",
          "required": true,
          "definition": "ISO 4217 currency code.",
          "example": "USD"
        },
        {
          "name": "allowancesCarried",
          "type": "allowance[]",
          "required": true,
          "definition": "The brief's allowances as carried in this quote, so identical allowances sit on identical base prices.",
          "example": "[{\"item\": \"Shingle upgrade to architectural\", \"amount\": 1200, \"currency\": \"USD\", \"covers\": \"material only\"}]"
        },
        {
          "name": "assumptionsAccepted",
          "type": "string[]",
          "required": true,
          "definition": "The brief's assumptions this quote accepts, verbatim.",
          "example": "[\"Work proceeds in a single mobilisation\"]"
        },
        {
          "name": "assumptionsRestated",
          "type": "string[]",
          "required": true,
          "definition": "Assumptions the bidder replaced, with the replacement text. Required even when empty — this is where two apparently identical prices stop being identical.",
          "example": "[\"Decking replacement priced at $4.50/sqft beyond the two noted areas\"]"
        },
        {
          "name": "exclusionsAdded",
          "type": "string[]",
          "required": true,
          "definition": "Anything the bidder excludes beyond the brief's own exclusions. Required even when empty.",
          "example": "[]"
        },
        {
          "name": "validUntil",
          "type": "date",
          "required": true,
          "definition": "The date the price expires. A quote without an expiry cannot be compared against one with a short expiry on equal terms.",
          "example": "2026-10-10"
        },
        {
          "name": "startWindow",
          "type": "string",
          "required": true,
          "definition": "When work could begin, as a stated window rather than a promise of a date.",
          "example": "Between 2026-10-06 and 2026-10-20"
        },
        {
          "name": "durationEstimate",
          "type": "string",
          "required": true,
          "definition": "Expected working duration, with the unit stated.",
          "example": "3 working days, weather permitting"
        },
        {
          "name": "paymentSchedule",
          "type": "string[]",
          "required": true,
          "definition": "Each payment as a stated trigger and amount or percentage.",
          "example": "[\"25% at contract\", \"Balance on completion and final inspection\"]"
        },
        {
          "name": "warranty",
          "type": "string",
          "required": true,
          "definition": "Workmanship warranty in plain words, stated separately from any manufacturer warranty.",
          "example": "5 years on workmanship; manufacturer covers material separately."
        },
        {
          "name": "changeOrderPolicy",
          "type": "string",
          "required": true,
          "definition": "How a change is priced and authorised. Unstated at quote stage, it is negotiated at the worst possible moment.",
          "example": "Written change order priced before work proceeds; no verbal changes."
        },
        {
          "name": "licenseNumber",
          "type": "string",
          "required": false,
          "definition": "The contractor's licence number as issued by the relevant authority. Optional in the standard because licensing regimes differ; verification is the reader's responsibility, not the standard's.",
          "example": "2705-XXXXXX"
        },
        {
          "name": "insuranceOnFile",
          "type": "boolean",
          "required": false,
          "definition": "Whether the bidder asserts current liability and workers' compensation cover. An assertion, not a verification — the standard never implies BidBro or anyone else has checked it.",
          "example": "true"
        }
      ]
    }
  ],
  "enumerations": [
    {
      "id": "tradeProfile",
      "title": "Trade profile",
      "values": [
        "roofing-replacement",
        "bathroom-remodel",
        "kitchen-remodel",
        "hvac-replacement",
        "exterior-painting",
        "other"
      ]
    },
    {
      "id": "propertyType",
      "title": "Property type",
      "values": [
        "single-family-detached",
        "townhouse",
        "condominium",
        "duplex",
        "manufactured",
        "other"
      ]
    },
    {
      "id": "schedulingFlexibility",
      "title": "Scheduling flexibility",
      "values": [
        "urgent",
        "firm-date",
        "flexible",
        "seasonal"
      ]
    },
    {
      "id": "responsibility",
      "title": "Responsibility",
      "values": [
        "homeowner",
        "contractor",
        "shared",
        "undecided"
      ]
    },
    {
      "id": "priceBasis",
      "title": "Price basis",
      "values": [
        "fixed-price",
        "cost-plus",
        "time-and-materials",
        "not-to-exceed",
        "allowance-based"
      ]
    },
    {
      "id": "measurementMethod",
      "title": "Measurement method",
      "values": [
        "tape-measured",
        "laser-measured",
        "aerial-report",
        "from-drawings",
        "estimated",
        "unknown"
      ]
    },
    {
      "id": "confidence",
      "title": "Quantity confidence",
      "values": [
        "measured",
        "approximate",
        "rough"
      ]
    },
    {
      "id": "cleanupStandard",
      "title": "Cleanup standard",
      "values": [
        "broom-clean",
        "vacuumed",
        "as-found",
        "unstated"
      ]
    },
    {
      "id": "tristate",
      "title": "Yes / no / unknown",
      "values": [
        "yes",
        "no",
        "unknown"
      ]
    },
    {
      "id": "documentType",
      "title": "Document type",
      "values": [
        "photo",
        "drawing",
        "report",
        "prior-estimate",
        "other"
      ]
    }
  ],
  "tradeProfiles": [
    {
      "id": "roofing-replacement",
      "title": "Roofing replacement",
      "requiredQuantities": [
        "roofArea",
        "pitch",
        "layersExisting"
      ],
      "additionalRequired": [
        "property.stories"
      ],
      "minimumPhotos": 4,
      "photoGuidance": "One photograph of each elevation from ground level, plus a close view of any known problem area. Photograph flashing, valleys and penetrations where they can be reached safely — never climb to take a brief photograph.",
      "typicalExclusions": [
        "Gutter replacement",
        "Interior repair of water damage",
        "Decking replacement beyond a stated quantity",
        "Skylight replacement"
      ],
      "typicalAllowances": [
        "Decking replacement per sheet or per square foot",
        "Shingle upgrade",
        "Ventilation upgrade"
      ]
    },
    {
      "id": "bathroom-remodel",
      "title": "Bathroom remodel",
      "requiredQuantities": [
        "floorArea",
        "fixtureCount"
      ],
      "additionalRequired": [
        "property.yearBuilt",
        "materials.specifiedItems"
      ],
      "minimumPhotos": 4,
      "photoGuidance": "Each wall from the doorway, the floor, and the inside of the vanity cabinet showing the supply and waste connections. Photograph the ceiling if there is any staining.",
      "typicalExclusions": [
        "Moving load-bearing walls",
        "Window replacement",
        "Repairs to concealed damage discovered on demolition"
      ],
      "typicalAllowances": [
        "Tile",
        "Vanity and top",
        "Fixtures and trim",
        "Lighting"
      ]
    },
    {
      "id": "kitchen-remodel",
      "title": "Kitchen remodel",
      "requiredQuantities": [
        "floorArea",
        "linearFeetCabinetry"
      ],
      "additionalRequired": [
        "property.yearBuilt",
        "materials.specifiedItems",
        "materials.ownerSuppliedItems"
      ],
      "minimumPhotos": 5,
      "photoGuidance": "Each wall, the floor, the ceiling, and the panel or breaker serving the kitchen. Include a photograph taken from the adjoining room through the doorway — access for cabinetry is a real constraint.",
      "typicalExclusions": [
        "Appliance supply",
        "Structural alterations",
        "Asbestos or lead abatement",
        "Flooring beyond the kitchen footprint"
      ],
      "typicalAllowances": [
        "Countertop",
        "Cabinetry",
        "Appliances",
        "Backsplash tile",
        "Plumbing fixtures"
      ]
    },
    {
      "id": "hvac-replacement",
      "title": "HVAC replacement",
      "requiredQuantities": [
        "conditionedArea",
        "existingSystemAge"
      ],
      "additionalRequired": [
        "property.yearBuilt",
        "property.stories"
      ],
      "minimumPhotos": 3,
      "photoGuidance": "The outdoor unit including its data plate, the indoor air handler or furnace including its data plate, and the thermostat. A legible data plate answers more questions than any description.",
      "typicalExclusions": [
        "Duct replacement or resizing",
        "Electrical service upgrade",
        "Drywall repair after equipment access",
        "Permit fees where stated as homeowner-pulled"
      ],
      "typicalAllowances": [
        "Duct modification",
        "Line-set replacement",
        "Condensate pump or drain rework"
      ]
    },
    {
      "id": "exterior-painting",
      "title": "Exterior painting",
      "requiredQuantities": [
        "paintableArea",
        "stories"
      ],
      "additionalRequired": [
        "property.yearBuilt",
        "scope.siteConditions"
      ],
      "minimumPhotos": 4,
      "photoGuidance": "Each elevation, plus close views of any peeling, rot or previous repair. A pre-1978 property should include a photograph of a representative painted surface, because lead-safe practices are a price input.",
      "typicalExclusions": [
        "Carpentry repair beyond a stated quantity",
        "Window glazing",
        "Roof or gutter painting",
        "Pressure washing of hard surfaces"
      ],
      "typicalAllowances": [
        "Carpentry repair per linear or square foot",
        "Additional coat",
        "Trim colour change"
      ]
    },
    {
      "id": "other",
      "title": "Other work",
      "requiredQuantities": [],
      "additionalRequired": [],
      "minimumPhotos": 2,
      "photoGuidance": "At minimum, a wide view establishing where the work is and a close view of the specific condition being addressed.",
      "typicalExclusions": [],
      "typicalAllowances": []
    }
  ],
  "changelog": [
    {
      "version": "0.1",
      "date": "2026-09-10",
      "summary": "First public version. Nine core field groups, ten enumerations, six trade profiles and six conformance rules, with a JSON Schema, a machine-readable field registry, two worked examples and a CITATION.cff."
    }
  ],
  "limitations": [
    "ScopeSpec describes a project; it does not price one. Nothing in it produces, implies or validates a cost.",
    "The six trade profiles in 0.1 are the trades BidBro can describe carefully today. They are not a claim about which trades matter most, and the standard is explicitly incomplete outside them — use `other`, which imposes no extra fields, rather than forcing a job into a profile that does not fit.",
    "Field names and enumerations may change in 0.2. Every 0.1 URL and artifact remains available permanently so a brief written against 0.1 stays interpretable.",
    "The standard asserts nothing about licensing, insurance or competence. `licenseNumber` and `insuranceOnFile` record what a bidder states; verifying either is the reader's responsibility.",
    "No adoption is claimed. As of the published date, BidBro knows of no third-party implementation, and this page will name implementers only when they exist and agree to be named."
  ],
  "citation": "BidBro, Inc. (2026). ScopeSpec 0.1: a comparable residential project brief. https://www.bidbro.com/scopespec/v0-1 (CC BY 4.0)"
}
