Before changing product behavior or public claims, read:
docs/PRODUCT-CONTEXT.md— product thesis, capability truth, priorities, and open questions.README.md— public description and runnable surface.docs/DESIGN.md— architecture and implementation boundaries.PROVENANCE.md— origin and source constraints.
This repository supports a public-sector permitting showcase. Trustworthy scope and evidence are product behavior, not editorial polish.
Permit Bearings is an auditable decision-support and verification layer for California housing permitting. Its primary wedge is Scenario A: help an applicant identify a candidate route and reach a complete, well-routed submission. Scenario C is the assurance layer underneath that experience: source currency, provenance, dependency tracking, and re-verification.
Scenario B is an expansion area, not a v1 commitment. Prefer depth for one real applicant workflow and one local jurisdiction over shallow coverage of many statutes, jurisdictions, or staff workflows.
Never position the system as legal advice, a compliance certification, an approval, or an authoritative source of law.
Use these labels consistently:
- Implemented — executable code/data exists, is testable, and is exposed by a documented interface.
- Prototype — executable in a bounded corpus, sample, simulation, or manual workflow; production breadth is not established.
- Planned — a design direction with no executable end-to-end path.
- Not targeted — intentionally outside the current scope.
A claim inherits the lowest status of its required parts. Link important
claims to a test, data artifact, or runnable path. Do not convert aspirations
in docs/DESIGN.md into present-tense README or demo claims.
Keep these distinctions explicit:
- A statewide baseline is not a locally encoded jurisdiction.
- A typical-document hint is not packet-level completeness validation.
- Structured intake-to-rule fixtures are not natural-language answer or citation evaluations.
- A source-change rehearsal is not a durable production review queue.
- Interface localization is not translated source-derived guidance.
- A plain-language explanation draft does not change rule matching and is not evidence of human, counsel, or jurisdiction review.
- A Spanish machine draft is not a semantically reviewed translation of the source record.
- A presence-based text screen is not a compliance determination and cannot prove that required language is present.
- A source-linked rule is not necessarily human-reviewed, jurisdiction-approved, or counsel-approved.
- A candidate transit or pathway result is not a final eligibility finding.
When a capability changes, update the matrix in
docs/PRODUCT-CONTEXT.md, the README, design, demo script, and accessibility
notes as applicable.
Prefer sources in this order:
- Official California statutory and regulatory text.
- Official HCD guidance and technical-assistance material.
- Official jurisdiction code, forms, GIS, and published procedures.
- HCD enforcement or technical-assistance letters as documented precedent, not controlling authority for every jurisdiction.
- Secondary sources only for discovery.
Search snippets, summaries, and model output are never verification evidence. If an official source cannot be retrieved, mark the item unverified and surface the gap.
Every published rule should have a stable ID, jurisdiction scope, criteria, canonical citation and URL, a short supporting excerpt or content digest, a source-check date, and explicit dependencies. Preserve effective dates and distinguish enactment, effective, and source-check dates.
Every published plain-language explanation should live outside the matching rule, link to a stable rule ID, source-check date, normalized citation fingerprint, and normalized full-rule fingerprint, carry its own version/authorship/review metadata, and preserve the citation as a separately visible evidence record. A completed review claim must record reviewer, method, review date, and the exact explanation version reviewed; translation review is independent and both statuses must remain visible. Missing, malformed, stale, or unverified explanation data must degrade to an evidence-only result, never suppress or create a rule match. Do not show action copy, interpretive notes, or generic document hints when the matched source is stale or unverified. If runtime fingerprint validation is unavailable or fails, fail closed on explanation display without disabling deterministic screening.
Plain language is a user-interface requirement, not a synonym for shorter legal prose. Start with the applicant consequence; use one condition or number per sentence; define unavoidable legal terms once; turn unresolved items into direct questions; and use a scannable list when a rule contains multiple deadlines or thresholds. Keep detailed exception lists and legal terminology in the evidence disclosure. Readability tests can flag regressions but do not replace review with applicants, staff, counsel, or translators.
The current verified_on field means that dated source evidence is recorded;
it does not encode who reviewed it or whether a jurisdiction accepted the
interpretation. New verification work should move toward explicit levels such
as machine_linked, human_reviewed, and jurisdiction_approved, with
reviewer/method metadata.
Treat a changed or unreachable source as a currency problem, but never as the same currency problem. A changed source — one that was fetched and whose content hash moved — must identify every affected rule, golden case, and user-facing output until a person re-verifies them. An unverifiable source — one the fetch could not reach — is evidence about the network, not about the law: report it as its own status with the last successful verification date, and do not mark anything stale on its account. Prefer explicit source IDs and dependency edges over substring matching.
- Use deterministic rules for objective, testable standards.
- Use AI for bounded extraction, retrieval, explanation, translation drafts, and staff-document drafts when its evidence can be shown.
- Never let model prose silently create or modify a published rule.
- Keep AI-assisted explanation and translation copy versioned, visibly labeled, and review-pending until named review metadata exists. Do not promote review status by editing interface prose alone.
- Require page/passage evidence for extracted facts and citations for generated remedies or explanations.
- Expose unknown, conflicting, stale, and unsupported states. Abstain and route to staff instead of filling gaps with inference.
- Keep model-independent regression fixtures for any AI-assisted workflow.
- Separate submission completeness (required material is present) from consistency/compliance review (the proposal satisfies applicable standards). Do not use one as a proxy for the other.
Runtime AI (ADR 0004) adds these rules for permit_pathways.ai:
- The model structures input and narrates output. It never evaluates a rule
criterion, never produces a match, and never sees an unmatched rule as
something to decide.
screening.pyand its browser port stay untouched by AI work. - An extracted fact is a draft until the applicant confirms it in the form.
Enforce the allowed-value list and require a verbatim supporting quote
from the applicant's text; downgrade anything else to
unknown. Absence is reported as "could not tell", never filled in. - Every substantive generated claim must cite corpus text, and the service must verify the quote against the extracted text of the named source before display. Drop what does not resolve and count it visibly. A verified citation is evidence that the passage exists, not that the sentence quoting it is correct.
- Label every runtime output AI-generated and keep the non-advice, non-eligibility, non-approval disclaimers beside it. Record the prompt version and model with the output.
- Store and log no applicant content in the service. Read the provider credential only from the environment; never write it to a file.
- Commit measured evaluation numbers only from a recorded live run that
names provider, model, date, and commit; otherwise mark the result
not_run. Never copy RAG or LLM code from another repository into this one; write against the public SDK. - The static site must keep working with the service absent.
Use public, synthetic, or properly redacted project material in the repository and demo. Do not commit applicant PII, credentials, private permit files, or model-provider payloads.
The current public demo persists no applicant data. Before adding storage,
accounts, telemetry, uploads, or external model calls, document (the optional
AI service's inventory is in docs/DATA-FLOW.md, "Optional runtime AI
service path"):
- collected fields and purpose;
- data flow and subprocessors;
- access controls and security boundary;
- retention and deletion behavior;
- jurisdiction ownership and full export;
- records-search/export behavior for CPRA workflows; and
- deployment-specific privacy and security review needs.
Do not claim CPRA, Information Practices Act, SAM, or SIMM compliance merely because the design anticipates it.
- Keep rules, sources, golden cases, and review artifacts in portable, human-readable formats owned by the jurisdiction.
- Keep
data/explanations/plain-language.jsonseparate from deterministic criteria. Validate exact rule coverage, duplicate/orphan IDs, review metadata and version binding, locale status, linked source-date drift, and same-date citation-content drift. Bind display copy to all rule fields that affect its meaning, including criteria, pathway, scope, notes, and document hints. - Preserve the dependency-light Python core and static-friendly demo unless a change has a clear product reason.
data/demo-data.jsis generated from canonical JSON byscripts/build_demo_bundle.py. Never hand-edit it; rebuild it whenever an input dataset changes.- The Python and browser demos currently duplicate matching and clock logic. Update both or establish a single generated source, and add parity coverage for behavior that appears in both.
- Never hard-code a favorable demo answer that bypasses the same data and logic under test.
- Keep stable identifiers for rules, sources, jurisdictions, and fixtures.
- Label samples, simulations, and manually curated data in the interface.
For rule or screening changes, add positive, negative, boundary, ambiguous, and wrong-jurisdiction cases as relevant. For source changes, test both the affected dependency set and unaffected controls. For the conformance scanner, use held-out positive and negative material before publishing accuracy or coverage metrics.
For explanation changes, test English and Spanish status independently, selected legal/semantic boundaries, high-priority jargon regressions, unavailable-copy fallback, source visibility, and the invariant that matching output is unchanged. Human readability, legal fidelity, and translation parity remain separate review activities; schema tests are not substitutes.
Before handing off a code or data change:
- Run
python -m pytest -qwith an interpreter that has pytest. - Run the verification harness when rules, sources, or golden cases changed.
- Run
python3 scripts/build_demo_bundle.py --check. - Check JSON and public-demo/Python parity where applicable.
- Run
git diff --check. - Update capability status and public claims.
Maintain the WCAG 2.2 AAA target while clearly separating automated/static checks from completed human assistive-technology testing. Translation of source-derived guidance requires semantic parity review; translating only UI controls is not enough.
Unless the task explicitly changes strategy, prefer:
- Claim integrity, source dependencies, and verification semantics.
- One pilot jurisdiction's parcel-aware ADU permit-readiness packet, including missing-item remedies and an evidence manifest.
- A human re-verification and local-rule authoring workflow.
- Held-out scanner evaluation and comparable-jurisdiction discovery.
- Bounded Scenario B extensions such as comment-resolution tracking.
Defer autonomous legal interpretation, full building-code plan review, rip-and-replace permitting infrastructure, and claims of comprehensive local coverage.