71 lines
3.5 KiB
Go
71 lines
3.5 KiB
Go
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
|
|
}
|