package ingest // notes.go: the map "engine flag reason → contract note code → step". // // It lives here, with the other translations of the seam's vocabulary, because it has two consumers: // the read path that answers `GET /notes`, and the materializer that puts a note into a stream // frame. One copy in the HTTP layer left the frame carrying the engine's own word. // // ⚠ The codes are the companion's ◆ PROPOSAL (appendix A) and are not ratified — which is why // `Note.code` is not an enum in the schema. The one code outside it is the placeholder below: the // appendix leaves that cell empty while the field is required, so the server owes a value (PD-246). // NoteStep is the contract's NoteSeverity. Two values today; how many there ought to be is an open // product question (K-6). const ( StepAttention = "attention" StepGlance = "glance" ) // NoteCodeUnspecified is what a reason outside the map projects as. // // Not a hole and not an invention: the engine and the platform ship independently, so between two // releases the engine emits reasons this build has never heard of, and the wire needs a defined // answer for that window. The contract already says what a client does with a code it does not know. // Forwarding the engine's word is the leak this map prevents; dropping the note loses a remark. // // ⚠ Closing the window needs the ENGINE to publish its flag reasons as data — this module may not // import it (D39.85) — which is register row PD-246, not a change here. const NoteCodeUnspecified = "unspecified" // note is one row of appendix A. type note struct { code string step string } // notes mirrors appendix A of the companion. // // ⚠ The STEP is decided per row and NOT derived from the engine's severity rank. Deriving it tied // the wire to another zone's internal triage order — a rank the engine may re-order for its own // reasons — and put `empty_answer` (nothing usable was delivered) in the same quiet step as // `markup_cleaned` (the text shipped, tidied). The line drawn here is: did the reader lose text. // It is the platform's reading and awaits the owner's word with the phrases (column «Ступень» ⬜). var notes = map[string]note{ "hard_refusal": {"content_withheld", StepAttention}, "soft_refusal": {"content_withheld", StepAttention}, "content_filter": {"content_withheld", StepAttention}, "hard_block": {"content_withheld", StepAttention}, "cjk_artifact": {"source_residue", StepAttention}, "excision_suspect": {"text_possibly_dropped", StepAttention}, "coverage_fail": {"incomplete_coverage", StepAttention}, "sanitizer_defect": {"markup_defect", StepAttention}, "loop_degenerate": {"repetition", StepAttention}, "decode_error": {"unreadable_answer", StepAttention}, "empty": {"empty_answer", StepAttention}, "upstream_not_ok": {"unavailable", StepAttention}, "glossary_miss": {"term_not_applied", StepGlance}, "length": {"length_mismatch", StepGlance}, "sanitizer_stripped": {"markup_cleaned", StepGlance}, } // NoteCode maps one engine reason onto what the wire carries. func NoteCode(reason string) (code, step string) { if n, ok := notes[reason]; ok { return n.code, n.step } // A reason this build has never heard of gets the quiet step: the client draws a neutral phrase // for a code it does not know, and calling an unknown thing urgent is the one reading that is // certainly wrong. return NoteCodeUnspecified, StepGlance }