feat(agent): declare workflow convergence criteria - #762
ayushtr-aws wants to merge 7 commits into
Conversation
Self-review — principal-architect passReviewed via the Verdict: Approve with nitsClean, backward-compatible, explicitly declarative-only. The Vision alignment ✅Serves reviewable outcomes — makes "what counts as done" a declarative, validated per-workflow contract while explicitly preserving the defensive Blocking issuesNone. Non-blocking suggestions / nits
Documentation ✅
Tests & CI
Review agents run
Human heuristics
Recommendation: Approve pending 🤖 Generated with Claude Code |
|
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #762 +/- ##
=======================================
Coverage ? 92.53%
=======================================
Files ? 340
Lines ? 98376
Branches ? 10874
=======================================
Hits ? 91030
Misses ? 7346
Partials ? 0 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
|
Addressed all self-review nits in
Also tightened schema-path assertions in the convergence validation tests. Validation:
|
|
Tightly-scoped contract addition, and the v1 "descriptive only, no runtime branch" boundary is stated clearly in both the
1, 4 and 5 are cheap; 2 and 3 are design calls I'd defer to you on. |
scottschreckengaust
left a comment
There was a problem hiding this comment.
Verdict: Approve (with non-blocking nits)
A tightly-scoped, additive, backward-compatible change that makes the workflow stopping contract explicit as declarative metadata. The v1 "descriptive only, no runtime branch" boundary is stated clearly in both the Convergence docstring and WORKFLOWS.md, and I verified it holds: parse_workflow runs validate_shape (JSON Schema) before Workflow.model_validate, and nothing in runner.py/pipeline.py consumes the new block. No blocking issues survived verification.
Governance
- Backing issue #517 carries the
approvedlabel (P1, agent-runtime, v1). Branchfeat/517-explicit-convergencefollows convention; PRCloses #517. - Acceptance criteria met: schema updated, all three shipped coding workflows declare convergence, invalid config fails at load with clear JSON-pointer paths, design-doc section with a repo-less
artifact_deliveredexample, and no change to default terminal behavior.
Vision alignment
Advances reviewable, bounded outcomes (VISION.md) by making "what counts as done" declarative per workflow without weakening _resolve_overall_task_status's guard against false-positive completion. No blast-radius or cost change; no tenet trade requiring an ADR (ADR-014 already covers workflow-driven tasks). Fail-closed: unknown modes/sensors/outcomes are rejected at load.
Blocking issues
None.
Non-blocking suggestions / nits
- Two production workflows still declare no convergence, and the shipped-workflow test can't notice. Verified at this head:
agent/workflows/coding/restack-v1.yaml,agent/workflows/default/agent-v1.yaml, andagent/workflows/knowledge/web-research-v1.yamlarestatus: productionwith noconvergenceblock.test_shipped_coding_workflow_declares_convergenceparametrizes over exactly the three files this PR edits, so it structurally cannot flag the omission. The field is optional so this is not a correctness bug, and #517's scope named only the three coding workflows — but a test that enumerates the registry and asserts eachproductionworkflow either declares convergence or is an explicit documented exclusion would prevent silent drift. - Corpus fixture models a shape the shipped file lacks.
contracts/workflow-validation/valid-knowledge-web-research.jsonnow adds anartifact_deliveredconvergence block, while the realknowledge/web-research-v1.yamlhas none. Harmless (fixtures are synthetic vectors) but worth reconciling so the parity corpus reflects production intent. Convergencemodel permits states the JSON Schema rejects.required_sensors: list[... ] | None = Nonewith no model-level mode-coupling meansConvergence(mode="test_gated", terminal_outcomes=["pr_opened"])constructs fine while the equivalent file is rejected by the schemaallOf. Safe today because the loader always runs the schema first and the alias comment documents this, but it leaves two sources of truth; amodel_validator(mode="after")would state the invariant once and protect programmatic construction.test_gatedcan be structurally satisfied yet semantically vacuous. The step-matchingallOfrules only require averify_build/verify_lintstep to exist — a step withgate: informational, or any step in aread_onlyworkflow, never gates. A future harness reading the contract could be misled. Acceptable for descriptive v1; note it when a harness starts consuming the block.- README over-claims corpus coverage.
contracts/workflow-validation/README.mdsays schema failures cover "invalid modes/sensors", but the only added fixture isschema-bad-convergence-sensor.json(missing-step case). The Python parametrized negative tests don't travel to the Phase-4 registry validator (#246), so consider adding a bad-mode / mismatched-outcome fixture. - No
commentconvergence counterpart.TerminalOutcomeincludescomment, butConvergenceTerminalOutcomeoffers onlypr_opened/review_published/artifact_delivered/human_approved; a comment-terminal workflow cannot declare a truthful convergence signal. Fine for the current shipped set; revisit if a comment-terminal workflow ships.
Documentation
docs/design/WORKFLOWS.md and the generated Starlight mirror docs/src/content/docs/architecture/Workflows.md are updated in lockstep — I diffed the new Convergence section and it is byte-identical, so no stale-mirror / "Fail build on mutation" risk. The terminal_outcomes vs convergence.terminal_outcomes distinction (with the pr_url/pr_opened example) pre-empts the likely misreading. Schema $id description appends #517 provenance without dropping #248.
Tests & CI
- CI green (5/5):
build (agentcore)pass (15m), Secrets/deps/workflow scan pass, Validate PR title pass, Dead-code advisory pass. Codecov: all modified lines covered. - Coverage is genuinely additive — happy paths, optionality/backward-compat, sensor↔step (both
verify_buildandverify_lintnow negatively tested), mode↔outcome coupling forreview_submitted/artifact_delivered/human_approved, JSON-pointer error paths, model-levelmin_length=1rejection, and all three shipped coding workflows end-to-end. Remaining gap is the registry-wide production-coverage assertion (nit 1). - Bootstrap synth-coverage: N/A — agent-runtime (Python) + docs + contract fixtures only; no CDK constructs/stacks/handlers and no new CloudFormation resource types, so ADR-002 bootstrap bundle updates do not apply.
Review agents run
My subagent execution context cannot spawn nested pr-review-toolkit agents, so I performed the equivalent analysis by hand and independently re-verified the substantive prior-thread findings against this head (d8c957f):
- code-reviewer (hand) — verified only
parse_workflowreachesmodel_validate, always aftervalidate_shape; enum parity betweenmodels.pyLiterals and the JSON Schemaenums is exact. - type-design-analyzer (hand) — confirmed the model/schema divergence (nit 3) is real but loader-gated and documented.
- pr-test-analyzer (hand) — confirmed negative-case coverage now symmetric for sensors and mode↔outcome; the registry-wide gap (nit 1) is genuine and I reproduced it by enumerating shipped workflows.
- comment-analyzer (hand) — docstrings/docs accurate; README over-claim is nit 5.
- silent-failure-hunter — omitted: no error-swallowing/fallback code; validation raises
WorkflowValidationErrorand fails closed. - /security-review — omitted: no IAM/Cedar/network/secrets/input-gateway change; workflow files are first-party trusted config and the change is additive fail-closed validation.
Human heuristics
- Proportionality ✅ — schema block + two thin frozen Pydantic models + 3 YAML declarations; no runtime machinery built ahead of need.
- Coherence
⚠️ minor — two disjoint "terminal outcome" vocabularies by design, documented and comment-annotated (agent/src/workflow/models.py:35). - Clarity ✅ — names/docstrings carefully bound v1 scope; clear JSON-pointer error paths.
- Appropriateness
⚠️ minor — tests assert intended behavior but the shipped-workflow test hardcodes three IDs rather than enumerating the registry (nit 1).
Approving; nits 1 and 3 are the most worthwhile follow-ups but none block merge.
Adds an optional, validated convergence contract so workflows can explicitly describe the sensors and terminal signals that define completion. The v1 contract is declarative and preserves existing runtime success behavior.
Area
cdk— infrastructure, handlers, constructsagent— Python runtime / Docker imagecli—bgagentclientdocs— guides or design sources (docs/guides/,docs/design/)tooling— rootmise.toml, scripts, CI workflowsRelated
Closes #517
Changes
convergenceschema and typed workflow models.Validation
mise run builduv run pytest --no-cov tests/test_workflow_loader.py tests/test_workflow_validation_corpus.py tests/test_workflow_tree_valid.py -q(64 passed)Acknowledgment
By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of the project license.