Skip to content

Warn when a first action's guard reads a staged field no row holds - #1686

Merged
Muizzkolapo merged 1 commit into
mainfrom
guards/first-action-guard-reads
Nov 8, 2026
Merged

Muizzkolapo merged 1 commit into
mainfrom
guards/first-action-guard-reads

Conversation

@Muizzkolapo

@Muizzkolapo Muizzkolapo commented Nov 8, 2026 •

Copy link
Copy Markdown
Owner

Summary

  • The staged-row check compares each source.<field> an action reads with the fields the staged rows hold. It read every action below the first stage, but not the first action's own guard. A first action with guard: { condition: "source.scroe IS NULL", on_false: filter } passed every record with no message.
  • The check now also reads the first action's guard reads and logs the warning a later action gets:
    Action 'tag' guards on source.scroe, but no record staged from staging/rows.json holds 'scroe'. Records from that file will not have it.
  • It never refuses. A guard decides what a record without the field does, and a staged file may lack an optional field. The first action's prompt and observe reads stay with the first-record render, which already checks them.
  • validate_source_reads_below is renamed to validate_staged_source_reads. It has one caller, in initial_pipeline.py. That caller now passes the first action's config the way the seed-selector check beside it does.
  • Docs: guards.md documents the warning. Its sentence about an upstream with no schema or with additionalProperties said the guard "says nothing". Preflight warns Cannot validate field 'descriptio' in both cases, so the sentence now says that. input-formats.md, input/ARCHITECTURE.md and the staging and input manifests describe the first action's guard read.

Verification

  • gate.sh red recorded test_a_first_action_guard_on_a_field_no_row_holds_warns_and_runs (a real agac run) failing on the missing warning line for == 'x' and IS NULL. The stored counts already matched (0 and 1), so the run itself does not change. The later-action guard test in the same file is the live positive control.
  • gate.sh green: RED target passes, ruff format --check, ruff check, mypy agent_actions, full pytest 17242 passed, 37 skipped.
  • Unit test test_a_first_action_guard_on_a_field_no_row_holds_warns.py: one exact warning for a misspelled guard field, none for a held field, and no scan of the first action's prompt, observe or passthrough reads. A mutant that also scans passthrough fails it (mutate.sh: KILLED).
  • Sample project, ql_guard_probe with source.scroe IS NULL on tag: this branch prints the warning and Guard pre-filter for 'tag': 2 passed, exit 0. main prints no warning.
  • An LLM upstream on the mock provider with additionalProperties: true, and with no schema: agac inspect warns Cannot validate field 'descriptio'; agac run passes 2 of 2 records.
  • agac inspect and agac run --fresh on ql_staging_precheck and ql_contract_probe: validated, exit 0, no new refusal.
  • Three blind reviewers, HIGH tier (risk.sh): 2 YES, 1 NO. The NO named a false design note in the staging manifest; it is corrected, with input-formats.md and the passthrough test case the other reviewers named. GREEN ran again after those edits. Recorded YES_WITH_ISSUES.
  • gate.sh smoke --skip: risk.sh reported smoke_required=no; the change is in staging validation only, and the sample-project runs above cover it.

Known limit

  • Each staged-row warning prints two times per run: the precheck and the walk both log it. main does the same for a later action. This change does not fix it.

@Muizzkolapo
Muizzkolapo added this pull request to stack #1689 November 8, 2026 01:09
@Muizzkolapo Muizzkolapo changed the title guards/first action guard reads Warn when a first action's guard reads a staged field no row holds Nov 8, 2026
@Muizzkolapo
Muizzkolapo force-pushed the guards/first-action-guard-reads branch from ed2cd83 to 5f972d9 Compare November 8, 2026 12:39
The staged-row check compared the source reads of every action below the
first stage with the fields the staged rows hold, but it never read the
first action's own guard. A misspelled field there under IS NULL passed
every record with no message, while the same guard on a later action was
warned of. The first-record render covers the first action's prompt and
observe reads, but it does not evaluate a guard.

The check now also reads the first action's guard and logs the same
warning. It never refuses: a guard decides what a record without the
field does. The function is renamed to validate_staged_source_reads,
because it no longer covers only the actions below the first.
@Muizzkolapo
Muizzkolapo force-pushed the guards/first-action-guard-reads branch from 5f972d9 to 61200c2 Compare November 8, 2026 13:43
@Muizzkolapo
Muizzkolapo merged commit 2336b32 into main Nov 8, 2026
5 checks passed
@github-actions github-actions Bot locked and limited conversation to collaborators Nov 8, 2026
@Muizzkolapo
Muizzkolapo deleted the guards/first-action-guard-reads branch November 8, 2026 16:02
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant