mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-15 15:02:04 +00:00
feat(coach): partial-malformed observability on sentinel parser
The W3-of-v1.4.22 sentinel parser silently dropped malformed rows and fired `coach.keyvalues.parse_failed` only when the entire block was unusable. Mixed-format drift (one row breaks, the other six parse) landed without any signal. Surface it. - `SentinelParseResult.malformedEntries[]` records each skipped row with a typed reason (`missing_colon` / `value_overflow` / `label_overflow` / `no_END_marker` / `byte_overflow` / `schema_invalid`). Block-level failures (truncation, missing close marker) land here as synthetic entries so the wide-event always carries a typed cause. - Per-row label and value caps moved out of the Zod schema into the parser so the row-level reason can be `label_overflow` / `value_overflow` rather than the catch-all `schema_invalid`. - Chat route splits the annotation: `coach.keyvalues.parse_partial` when at least one row parsed AND at least one row failed, the existing `coach.keyvalues.parse_failed` stays for full-block failures. Both annotations carry the per-line reason array. - Backwards-compatible `parseKeyValueLine` wrapper preserved. Tests +5: label_overflow, value_overflow, byte_overflow, mixed-malformed entry assertions, and a tryParseKeyValueLine direct-API surface check. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
921cb7d42f
commit
58ae9bca42
3 files changed
+205
-24
No files matched your search
@@ -300,11 +300,24 @@ Reply now as the assistant, in ${locale === "de" ? "German" : "English"}.`;
|
||||
if (sentinel.malformed) {
|
||||
// Graceful degrade: log so ops can spot a provider whose
|
||||
// sentinel format has drifted, but pass the prose through
|
||||
// unchanged.
|
||||
// unchanged. v1.4.23 H1 — split the annotation:
|
||||
// - parse_partial: at least one row parsed AND at least one
|
||||
// row failed (mixed-format drift on a single reply)
|
||||
// - parse_failed: the whole block was unusable
|
||||
// Both annotations carry the per-line `reasons` array so an ops
|
||||
// dashboard can attribute the failure cause without re-running
|
||||
// the parser.
|
||||
const reasons = sentinel.malformedEntries.map((entry) => entry.reason);
|
||||
const annotationName =
|
||||
sentinel.keyValues.length > 0 && sentinel.malformedEntries.length > 0
|
||||
? "coach.keyvalues.parse_partial"
|
||||
: "coach.keyvalues.parse_failed";
|
||||
annotate({
|
||||
action: { name: "coach.keyvalues.parse_failed" },
|
||||
action: { name: annotationName },
|
||||
meta: {
|
||||
kept: sentinel.keyValues.length,
|
||||
malformedCount: sentinel.malformedEntries.length,
|
||||
reasons,
|
||||
promptVersion: PROMPT_VERSION,
|
||||
},
|
||||
});
|
||||
|
||||
Reference in new issue
Block a user