adventure: stop dropping dispatches Pete has no words for
An event_type with no template was a 400 at ingest. That reads like caution and behaves like deletion: gogobee retries a 400 to its cap and then parks the row forever, so rejecting a type Pete hadn't learned to phrase didn't defer the event, it destroyed it. companion_hire went that way. It has been emitted from `!expedition hire` since the combat-engine work landed and has never once reached the site — the game logged a successful emit every time, and the queue row simply never sent. The mitigation on the books was "always deploy Pete first", which is a thing a person has to remember rather than a property of the system. So invert it. An unknown type now warns, gets counted, and publishes on a neutral fallback. 400 is kept for facts that are actually invalid: no guid, or a name that failed the fact-guard. gogobee can ship a new event type any day of the week now; the worst case is a thin card until Pete learns the words. It is thinner than it sounds in practice. gogobee authors dispatch prose from the fact's fields with no per-type switch, so an unrecognised type still arrives with a real headline and lede and is allowed to use them. The fallback only shows through when the model is off or the prose-guard refused the output. Untemplated types never post live to Matrix, whatever tier they claim. A thin card among cards is cheap and reversible; pinging everyone in the room with a dispatch Pete couldn't phrase is neither. The daily digest still carries it, one line among many, which is the right volume for something we don't understand yet. And give companion_hire its template. Pete is the one being hired, so it is first-person like his duels — third-person Pete filling in as a cleric reads as somebody else reporting on him. The admin status page grows a "dispatches with no template" panel, so the next one of these is a to-do list Pete can see rather than an archaeology dig. Claude-Session: https://claude.ai/code/session_012bxpQQJDjC1mTtLN3VVtBQ
This commit is contained in:
+29
-1
@@ -50,6 +50,16 @@ type statusPage struct {
|
||||
Sources []sourceStatus
|
||||
DegradedCnt int // sources currently failing
|
||||
Admin bool // viewer is an admin: show the full diagnostic columns
|
||||
// Untemplated adventure event types seen since boot, busiest first. Admin-only:
|
||||
// it names game internals, and it is a to-do list for Pete's vocabulary rather
|
||||
// than anything a reader wants. Empty in the healthy case.
|
||||
UnknownAdv []unknownAdvType
|
||||
}
|
||||
|
||||
// unknownAdvType is one event type gogobee sent that Pete had no template for.
|
||||
type unknownAdvType struct {
|
||||
EventType string
|
||||
Count int
|
||||
}
|
||||
|
||||
// handleStatus renders the source-health page. It's public: everyone sees a
|
||||
@@ -126,7 +136,25 @@ func (s *Server) handleStatus(w http.ResponseWriter, r *http.Request) {
|
||||
return rows[i].Name < rows[j].Name
|
||||
})
|
||||
|
||||
// Untemplated dispatch types, admin-only. These publish on the neutral
|
||||
// fallback rather than being rejected (see handleAdventureIngest), so nothing
|
||||
// is lost by not noticing — but a type sitting here with a rising count means
|
||||
// the section is carrying thin cards Pete could be writing properly.
|
||||
var unknownAdv []unknownAdvType
|
||||
if admin {
|
||||
for t, n := range AdvUnknownTypeCounts() {
|
||||
unknownAdv = append(unknownAdv, unknownAdvType{EventType: t, Count: n})
|
||||
}
|
||||
sort.SliceStable(unknownAdv, func(i, j int) bool {
|
||||
if unknownAdv[i].Count != unknownAdv[j].Count {
|
||||
return unknownAdv[i].Count > unknownAdv[j].Count
|
||||
}
|
||||
return unknownAdv[i].EventType < unknownAdv[j].EventType
|
||||
})
|
||||
}
|
||||
|
||||
base := s.base(r)
|
||||
base.Active = "status"
|
||||
s.render(w, "status", statusPage{pageData: base, Sources: rows, DegradedCnt: degraded, Admin: admin})
|
||||
s.render(w, "status", statusPage{pageData: base, Sources: rows, DegradedCnt: degraded, Admin: admin,
|
||||
UnknownAdv: unknownAdv})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user