# Native construction record v1

The independent schema is `vera.assetti_construction.v1`; assessment v1 stays
unchanged. The workflow ID remains `adeguati-assetti`. The local archive binds
client and engagement identity. There is no multi-tenant HTTP API or server role
assertion. All actor labels are declared local attribution, never authentication.

## Event envelope and persistence

The assistant writes an event envelope in the exact run output:

```json
{
  "request_id": "unique-stable-request-id",
  "expected_revision": 0,
  "actor": "the actual declared operator",
  "at": "2026-09-29T12:00:00+00:00",
  "event": {"kind": "cursor", "payload": {"summary": "Last reviewed topic", "next_step": "Next contextual question"}}
}
```

Run `python scripts/assetti_construction.py --client-engagement <context> apply
--event <output/event.json>`. Each accepted mutation atomically appends a SQLite
revision and audit event, then saves immutable content-addressed JSON and Markdown.
The full event payload preserves replaced answers and decisions. A retry with the
same request and body returns its original revision; a changed body or stale head
raises a conflict, leaving saved state intact. `status` regenerates the readable
outputs after an interrupted delivery. Do not edit the database directly.

Canonical digest: SHA-256 of JSON with sorted keys, UTF-8, no ASCII escaping,
compact separators and no nonfinite numbers. Revisions and content hashes do not
establish truth, a professional's identity or a legal timestamp.

## Payloads

Every collection item has an `id`; the writer assigns `revision`, `created_by`
and `created_at`. References use exact IDs in this case. Narrative comes from
the professional/model, not code-generated legal rules.

| Event | Required payload beyond ID |
| --- | --- |
| scope | description, proportionality, limitations |
| methodology | Complete versioned catalog, same criterion identities; approval actor/statement/source/date only when explicitly approved |
| visit | date, agenda, participants, observations, limitations |
| answer | question_id, question, original, speaker, date, mode text/html/reviewed_transcript, status answered/to_verify/unknown, criterion_ids, evidence_refs; separate summary |
| evidence | source_id, relative input path, actual sha256, locator, evidence_class document/statement/observation/execution/decision/transcript, limitations, criterion_ids; event_date/acquired_at/period/author as text or null |
| assessment | criterion ID, rationale, adequacy_judgment, applicability pending/applicable/not_applicable, evidence_stage, claimed_level, target_score, material_contradiction, evidence_refs; na_reason for N/A; contradiction and clarification_needed when material |
| qualification_review | criterion_id, exact assessment_basis hash as basis_sha256, statement, evidence_refs |
| score_decision | criterion_id, status proposed/recorded/revoked, basis_sha256, before_score, after_score, reason_code, rationale, alternative_considered, residual_risk, action_impact, review_trigger, evidence_refs; statement for recorded |
| baseline_review | exact digest of evaluate output as assessment_sha256, statement, evidence_refs |
| finding | criterion_ids, evidence_refs, observation, interpretation, consequence, alternatives, priority_reason |
| control | criterion_ids, finding_ids, title, risk, outcome, owner, decision_owner, substitute, role_status proposed/confirmed, inputs, steps[], outputs, frequency, timing_status proposed/confirmed, exceptions, response_time, archive, execution_evidence, register_fields[]; confirmation_evidence for confirmed roles/timing |
| action | control_id, finding_ids, proposal, owner, owner_status, timing, timing_status, priority_reason, completion_criterion, completion_kind document/investigation/operation, status proposed/agreed/in_progress/document_prepared/completed/rejected/deferred; confirmation_evidence for commitments; disposition, residual_risk, disposition_evidence for completed/rejected; execution_ids for operational completion |
| manual_compile | control_ids, introduction, limitations; immutable ID, frozen dependency snapshot and digest generated by helper |
| manual_review | manual_id, exact manual_sha256, statement, evidence_refs, finding_dispositions covering every included finding |
| adoption | manual_id, manual_sha256, competent_person, decision, effective_date, reservations, statement, evidence_refs |
| execution | control_id, exact control_sha256, manual_id, period, cycle, executor, exceptions, recipient, decision, closure, kind real/simulation, evidence_refs |
| operation_review | execution_ids, scope, sample, conclusion, limitations, next_review, outcome design_only/operating_supported/operating_not_supported/limited, action_dispositions covering every action, statement, evidence_refs |
| intake_import | source_id of original evidence item and exact UTF-8 content; schema, client/practice, questionnaire, revision and parent checked |
| legacy_review | record (unchanged assessment v1), evidence_refs pointing to that exact imported JSON; no implicit scoring/operation migration |

Score decisions, manuals, adoptions, executions, operation reviews, KPI observations
and strategy reviews use new IDs. Corrections append a new event or entity;
previous snapshots remain available. Other entity updates preserve their old
revision in the audit. New source versions should use new evidence IDs where
multiple versions are relevant together.

## Artifact and strategy contracts

`artifact`: workflow_id, module_version, run_id, artifact_id, source_id (evidence
ID), sha256, client_id, engagement_id, scope, periods, currency, review_status
draft/reviewed, limitations, adapter_status reviewed_external/native_contract_verified.
Reviewed adds reviewer/review_statement. Native Business Planning adds the exact
imported `document`, case_id, cycle, scenario_id. The CLI checks nested JSON against
the original imported bytes; the adapter checks v3 content/case/calculation digests.
Other workflow adapters currently require the reviewed_external route.

`budget_rows(plan, binding, mapping)` accepts a reviewed mapping with plan_sha256,
scenario Budget/Forecast, reviewer, decision, mapping_version, rows of
calculation_id/account_id/category/sign (+1 or -1), and control_totals keyed
`YYYY-MM/category`. It refuses unknown, duplicated or wrong-scenario IDs,
nondecimal/missing values and totals that do not reconcile exactly. Generated
rows retain calculation and plan lineage. This is a handoff to a reviewed
management-control recipe, not implicit cash events or an automatic source mapping.

Use `assetti_construction.py --client-engagement <context> budget
--artifact-id <registered-plan-id> --mapping <run-output/mapping.json>` to persist
the reviewed mapping and its rows as immutable JSON and CSV. Repeated exports
reuse the same content identity; revised Budget/Forecast exports keep prior files.

`objective`: description, perspective, owner, owner_status, scope, period,
evidence_refs. `strategy_link`: from_id, to_id, hypothesis, limitations, status
to_test/supported/contested and evidence_refs (required unless still to_test).

`kpi`: objective_id, definition, formula, formula_version, operation
value/ratio/percent, unit, population, data_owner, frequency, period, cutoff,
null_policy, direction, evidence_refs, target_status unknown/proposed/accepted.
Accepted targets need a value and explicit statement. `kpi_observation`: kpi_id,
exact contract_sha256, period, population, coverage, available_at, review_status,
evidence_refs, value or numerator/denominator; missing_reason when unknown.
The snapshot preserves its exact contract and target status. No automatic traffic
light or aggregate of unlike units is produced.

`strategy_review`: observation_ids, explanations, hypotheses, decision,
next_review, action_ids, statement, evidence_refs. A series discontinuity remains
visible in the stored contract/version; old observations are never recalculated.

## Intake Markdown

Schema `vera.assetti_intake.v1` includes practice_id (construction case), client_id,
engagement_id, session_id, revision, parent_sha256, date, declared_author, mode,
questionnaire_version, position and answers. Each answer carries question_id,
question, criterion_ids, original, status, notes and attachment_refs. The first
fenced JSON block is authoritative and the readable projection must match it.
Backticks are escaped in JSON; originals are indented in the projection. It cannot
contain score approval fields. The original file must have an archive receipt.
The first returned draft may reference an earlier draft that was never received;
that missing ancestor is recorded explicitly. Subsequent imports must descend
from the last imported revision or require a deliberate comparison of both drafts.
