Skip to content

Fix cligen schema walker to recurse through nested array items - #135

Merged
ysyneu merged 1 commit into
feat/ai-srefrom
feat/skilldoc-nested-filter-schema
Aug 6, 2026
Merged

Fix cligen schema walker to recurse through nested array items#135
ysyneu merged 1 commit into
feat/ai-srefrom
feat/skilldoc-nested-filter-schema

Conversation

@ysyneu

@ysyneu ysyneu commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

What

The request/response field-tree walker in internal/cmd/cligen/main.go only unwrapped one array level before checking whether the element schema was an object. A nested array field — the OR-of-AND filter tree shape used by filters/source_filters/target_filters across silence, escalate, inhibit, and unsubscribe rules (array<array<object>>) — never expanded its key/oper/vals item fields the way a plain array<object> field (e.g. layers) already did. The type label had the same bug, collapsing to the uninformative array<array> instead of array<array<object>>.

Both --help and the skill-card generator (internal/skilldoc) read from this same walker's output, so the gap showed up in both places.

Fix

  • tree()'s array case now unwraps items through any depth of nested arrays (via a new arrayLeafSchema helper, bounded defensively) before testing for an object leaf — generalized, not special-cased per command.
  • schemaType() is now recursive for the same reason, so nested array type labels show their real depth (array<array<object>>, array<array<string>>, …).
  • Regenerated all zz_generated_*.go command files and the skill-card fences (go run ./internal/cmd/cligen + go run ./internal/cmd/skilldoc gen). Affected commands: escalate-rule-create/update (filters), inhibit-rule-create/update (source_filters/target_filters), silence-rule-create/update (filters), unsubscribe-rule-create/update (filters), plus the alert-pipeline read paths that document the same filter shape (if, nested source_filters).
  • Added unit tests: nested array-of-object expansion, nested array-of-scalar (no false-positive children), the type-label recursion, and a regression guard on the existing single-level array<object> behavior.

Card content

skills/flashduty/reference/channel.md's hand-written "add a silence rule during maintenance" flow previously built a rule from only a time_filter, which the server rejects (no matching scope). Replaced it with a flow that pulls the target incident's labels and builds filters from them, and added a general "Building filters from incident labels" rule: base severity condition, per-label conditions with exclusions for id-shaped/long/date-shaped/noise-key values, the valid key vocabulary and oper enum, a note that an out-of-vocabulary key silently never matches instead of erroring, and verifying via the matching *-rule-list command.

Verification

  • make check (fmt, lint, go test -race ./..., build): all green, 0 lint issues, no test failures.
  • go run ./internal/cmd/skilldoc check: cards OK.
  • ./bin/flashduty channel silence-rule-create --help confirms filters now renders key/oper/vals children with descriptions and the IN/NOTIN enum.

Follow-up (not in this PR)

fc-safari holds its own copy of this fence at logic/runtime/bootstrap/skills/flashduty/reference/channel.md and needs a resync after this merges. No other repo under the org was found holding a copy.

The request/response field-tree walker only unwrapped one array level
before checking whether the element schema was an object, so a nested
array field like an OR-of-AND filter tree (array<array<object>>) never
expanded its item fields the way a plain array<object> field did — and
its rendered type label collapsed to the uninformative "array<array>".
Both --help and the skill-card generator read from this same walker, so
every filters/source_filters/target_filters field across silence,
escalate, inhibit, and unsubscribe rules (and any other nested-array
field) silently dropped its key/oper/vals schema.

Generalize the array case to unwrap items through any depth of nested
arrays (bounded, not per-command special-cased) before testing for an
object leaf, and apply the same fix to the type-label formatter. Add
unit tests covering the nested-object, nested-scalar, and single-level
regression cases.

Also rewrite the channel card's maintenance-silence example, which
built a rule with only a time window — servers reject that as having no
matching scope — and add a general rule for constructing `filters` from
an incident's own labels (severity + distinguishing labels, with the
value/key exclusions and key vocabulary needed to avoid silently
building a rule that never matches).
@ysyneu
ysyneu merged commit 96eecd0 into feat/ai-sre Aug 6, 2026
12 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant