4.3. Mixed mode
A MIXED request asks for a change that has to satisfy a bound standard: “make the encoder emit one acknowledgement per requested type, as the standard requires”. It needs both sides — what the document requires and what the code does — and a change. SPEAR does not answer it with one loop doing two jobs. It runs three passes around the coding core and judges the result on evidence the model cannot supply.
Fig. 4.2 The MIXED pipeline. Advisory model findings are recorded beside it and decide nothing; a single bounded repair loops back only on a decisive violation.
4.3.1. When a request is MIXED
Three things must hold together:
a standard is bound and engaged for the session (Normative mode: authoritative standards);
the request asks for a change to the tree;
it asks in the standard’s terms — it names the document as its authority (“as the specification requires”), a provision, or compliance itself.
A write in a session that merely has a standard bound is not MIXED because of the binding: “rename this function” stays a change request, and a question about a provision stays a normative question. The class is read from the request’s own words, by its syntax — a file name, a function call, a causative “make X do Y” — not by a list of one project’s vocabulary.
4.3.2. The three passes
4.3.2.1. 1. The normative pre-pass
The established normative runtime (Normative mode: authoritative standards) runs first, read-only, with the standard’s own tools and nothing else. It is asked to identify the provisions that govern the change and to state each one exactly — its force, its condition, its counts, the identifiers and values it names — citing every one. It writes nothing and reads no code.
It investigates with those tools, then finalizes with none: when the tool window closes the model is told that no tool remains, and a tool call it then writes out as text is never run and never taken as the answer. It is asked once more; a pass that still gives no answer ends as not completed, and says so.
4.3.2.2. 2. The constraint packet
What the pre-pass cited becomes the starting point of a packet; nothing is taken from its prose. Three sets are kept apart, and every move between them is recorded with its reason:
Set |
What it holds |
|---|---|
Retrieved candidates |
every provision the pre-pass looked at |
Coverage set |
the provisions it cited — by printed label, by source id, or by section and a verbatim quotation of the provision’s own words — plus the provisions the document itself groups with them |
Active constraint set |
the coverage set minus what is established as not applicable |
4.3.2.2.1. Structural coverage
Selecting one requirement of a group can leave its siblings out — and a compliance picture with half a list in it is not a compliance picture. So each cited provision is closed over the relationships the document’s own structure records, and only those:
Relation |
Adds |
|---|---|
|
the other normative declarations of the same numbered list: same section, same kind (Rule, Permission, …), same heading |
|
the other normative rows of the same table |
|
a provision the cited one names outright — one step, never onward |
Every added provision records the relation, the provision it was reached from
and the structure it was reached through. Closure is bounded: a group larger
than its limit, or a closure that would add too many provisions, is not
absorbed — the coverage is marked INCOMPLETE, and an incomplete coverage
can never yield COMPLIANT. A pre-pass that cites nothing identifiable also
leaves coverage incomplete; the packet is never filled from whatever retrieval
happened to return. The coverage reason says which of three things happened:
the pass answered and cited no provision, its answer was withheld because the
evidence did not support it, or it did not complete.
4.3.2.2.2. Applicability
Being retrieved, cited or structurally adjacent does not make a provision apply to this change. Each provision in the coverage set is:
Applicability |
Established by |
|---|---|
|
the request naming the provision or its section; the project declaring it applicable; or a conformance check the project binds to it |
|
the project declaring it not applicable, with a reason |
|
nothing deterministic — the default |
The model’s view (possibly applicable because the pre-pass cited it, possibly not applicable from the post-check) is kept in the audit record as advice. It never discards a requirement and never adds one.
An UNRESOLVED requirement can be neither met nor failed: it holds the
verdict at COMPLIANCE NOT DEMONSTRATED, it is never reported as
VIOLATED, and it is never repaired.
4.3.2.2.3. The packet the coding core receives
The active set becomes a NormativeConstraintSet: one constraint per
provision, each with the provision’s identity (ProvisionKey and
ProvisionInstanceId), its modality (SHALL, SHOULD, MAY), the requirement in
the document’s words, its condition, any exact count, any stated values and
identifiers, and a one-line implication — “permitted, not required: the
implementation must still work when it is absent” for a MAY, “applies only when
…” for a conditional requirement. The set has a stable identity that the audit
trail and the verdict refer to.
The coding core receives the objective and this packet, compactly, and nothing else of the standard — no surrounding sections, no normative tools.
The workspace’s knowledge and its external capabilities reach this pass and no other. The pre-pass answers from the standard alone, and the post-check reads only the packet and the final source: what someone once noted about a project is not evidence of what a standard requires.
4.3.2.3. 3. Implementation, then the final source
The frozen coding core (Implementation mode) makes the change, with its six tools and SpearHost around it — exactly as for any implementation request. The constraints are guidance to it, not a policy it is held to. Then the final source state is fixed: its fingerprint is taken, and the implementation evidence of the turn is computed (Evidence and verdicts).
4.3.4. One bounded repair
If an applicable SHALL constraint is VIOLATED on decisive authoritative
evidence, the coding core gets exactly one repair: the constraint, its
provision, and the contradiction the evidence found — never a model’s
speculation. The source epoch moves, every earlier check becomes stale, the
bound checks run again, and the verdict is computed afresh from the new final
source. A model-only finding, an ambiguity, an unresolved applicability or a
MAY never triggers a repair. This is the only repair a MIXED turn gets: the
implementation pass is not also given the repair a standalone implementation
turn receives after a failed project validation
(Implementation mode).
4.3.5. The verdict
The turn ends with the composite verdict (Evidence and verdicts) and the coverage report behind it: how many provisions were cited, how many structure added, how many were excluded as not applicable, and for the required ones how many are satisfied, violated, not demonstrated, of unresolved applicability, or in conflict. Every compliance claim in the coding core’s own prose that the verdict does not support is marked (compliance not established) where it stands.
Everything above is recorded in the audit trail — the pre-pass, the packet and its coverage, each applicability decision, each binding loaded, each check run and its result, each constraint’s candidate and authoritative status, any conflict, the repair and the final verdict — and none of it is shown to the coding core.
4.3.6. Examples
A MIXED task. The synthetic standard states, in section 4.2.1, that the mode field shall be 2 when flag X is set (Rule 4.2.1-1), that the count field shall contain exactly four entries (Rule 4.2.1-2), and that the metadata field may be absent (Permission 4.2.1-3).
> /standard use SYNTH-STD 1
> Update the header implementation in record.py so it complies with the
Rule 4.2.1 provisions of the standard.
MIXED VERDICT: VERIFIED + COMPLIANT — SYNTH-STD 1, constraint set ncs-…
(3 constraint(s); compliance is judged against these only).
Coverage: COMPLETE — 3 cited, 0 added by the document's structure,
0 excluded as not applicable.
Required: 2 — applicable 2 (satisfied 2, violated 0, not demonstrated 0),
applicability unresolved 0, evidence conflicts 0.
- C1 Rule 4.2.1-1 (SHALL, when flag X is set; applicability APPLICABLE):
SATISFIED — CONDITIONAL_VALUE: the provision states 2, the final source
gives 2 (record.py:2 `mode = 2 if flag_x else 1`) [record.py:2]
- C2 Rule 4.2.1-2 (SHALL; applicability APPLICABLE): SATISFIED —
EXACT_COUNT: the provision states 4, the final source gives 4
(record.py:3 `count = [0, 0, 0, 0]`) [record.py:3]
- C3 Permission 4.2.1-3 (MAY; applicability APPLICABLE): NOT_DEMONSTRATED
Implementation evidence: VERIFIED. Normative: SATISFIED.
The request named “the Rule 4.2.1 provisions”, which is what makes all three applicable; the permission is reported and does not block.
A project-bound check. The same requirement, implemented as
count = [0] * 4 — a shape no predicate reads — with the project binding
its own check to Rule 4.2.1-2 (Normative checks and applicability):
- C2 Rule 4.2.1-2 (SHALL; applicability APPLICABLE): SATISFIED —
project check count-four (`python3 -B tests/check_count.py`) passed
Without the binding the same source, with the same passing tests, would report
C2 NOT_DEMONSTRATED.