Skip to content

docs(spec): ground the AG-UI L2 construct spec against ag-ui main + CAO main (#458 audit)#29

Draft
plauzy wants to merge 6 commits into
spec/agui-l2-constructsfrom
claude/kiro-specs-ag-ui-l2-tyclkz
Draft

docs(spec): ground the AG-UI L2 construct spec against ag-ui main + CAO main (#458 audit)#29
plauzy wants to merge 6 commits into
spec/agui-l2-constructsfrom
claude/kiro-specs-ag-ui-l2-tyclkz

Conversation

@plauzy

@plauzy plauzy commented Jul 17, 2026

Copy link
Copy Markdown
Owner

What this is

A grounding audit of the agui-l2-constructs Kiro spec against the two sources of truth — ag-ui main @ b646b46 (protocol) and cli-agent-orchestrator main @ 1b00753 (merged L1 from awslabs#436) — plus the revised spec that resolves every finding, and the companion AG-UI Dojo integration spec (plan + promoted requirements/design/tasks). Re-audited 2026-07-18 against the latest fork mains — ag-ui 3a7433e, CAO 41c8ce7: no cited surface changed (full delta analysis in the audit addendum); the two new upstream example-server conventions from the ag-ui delta (no credentialed wildcard CORS, root /health route) are folded into the dojo spec. Full finding-by-finding evidence: .kiro/specs/agui-l2-constructs/audit.md (F1–F22 + re-audit addendum, each with file:line pins).

Scope: awslabs#458 (Phase 2 — L2 constructs + L1 cleanups; Phase-3 Dojo-listing plan).

Headline findings

  1. AG-UI main now has a first-class interrupt lifecycle — and the draft didn't use it. RunFinishedEvent.outcome = {type:"interrupt", interrupts[]}, RunAgentInput.resume[], <framework>:<name> namespaced reasons (exactly the issue's claude-code:permission_request scheme), approve-with-edits payload {approved, editedArgs?}. The revision maps CAO prompts onto the real lifecycle instead of a CAO-local invention (F1).
  2. A stock AG-UI client cannot read GET /agui/v1/stream. The stock SSE parser reads only data: lines (ignores event:/id:), requires camelCase payloads with a type field, and HttpAgent is POST-only. The draft's AC3 demo ("point Dojo at the GET stream, zero adapter") was unimplementable. The revision adds a protocol-faithful run plane POST /agui/v1/run (official ag-ui-protocol encoder, lifecycle-legal ordering, interrupts/resume) — which is also what makes finding 1 possible (F2).
  3. Replay/dedup requirements contradicted the code. Event ids are uuid4 (not monotonic), ?since= is an ISO-8601 timestamp (not an id cursor), and STATE_* frames carry no ids and are per-connection (already torn-proof). Dedup is now a seen-id-set contract; snapshot-before-delta is pinned as a regression, not built (F3, F4).
  4. The timeline was keyed on frames that never occur. a2a_delegation (and file_mod) have no producers; all real dispatches normalize to kind handoff discriminated by orchestration_type. Cleanup A now maps handoff/assignTOOL_CALL_START + correlated synthesized TOOL_CALL_END (matching the table docs/agui.md already publishes), keeping send_messageTEXT_MESSAGE_CONTENT (F5).
  5. The approval construct had no trigger and no real prompt to approve. WAITING_USER_ANSWER transitions never reach the fleet stream (internal EventBus only) → new ApprovalBridge requirement/tasks. CAO launches providers auto-approve (--dangerously-skip-permissions / --trust-all-tools / --yolo) → the approval example documents an approval-mode profile, and mock_cli gains a scripted-prompt mode for credentials-free CI (F6, F7).

Also fixed: expiry must send zero keystrokes (was "at most once" into a live terminal), edit cap aligned to the existing 4,000-char answer limit, per-provider reason sets grounded in the actual detection regexes, RING_CAPACITY is 500 not 1,000, convergence property re-quantified over the ordered fold, AguiStreamReader added so examples don't hand-roll SSE (F8–F22).

What was preserved

The L2 contract (fold frames / write only through the emit path), emit refusal parity (allow-list · JSON-serializability · 8 KiB · props unmutated — all verified exact), the privacy boundary, EARS style, Hypothesis property testing (already a dep), run.sh/showcase.sh conventions, and module placement.

Files

  • .kiro/specs/agui-l2-constructs/audit.md — the audit report (verdicts ✅/❌/⚠️/🔧 with evidence pins) + 2026-07-18 re-audit addendum
  • .kiro/specs/agui-l2-constructs/requirements.md — revised (15 requirements, EARS)
  • .kiro/specs/agui-l2-constructs/design.md — revised (two-plane model, grounding pins, corrected low-level design)
  • .kiro/specs/agui-l2-constructs/tasks.md — revised (20 tasks, P1–P9 traceability)
  • .kiro/specs/agui-dojo-integration/{plan,requirements,design,tasks}.md — the upstream ag-ui-protocol/ag-ui integration spec (the Dojo listing — [Feat] AG-UI Phase 2 — L2 construct library (builds on #386; L1 shipped in #436) awslabs/cli-agent-orchestrator#458's deferred Phase-3 item): evidence-backed uniqueness case, complete verified dojo file-touch checklist, phased execution plan; every upstream claim adversarially verified against ag-ui main and re-verified @ 3a7433e

Docs-only; no runtime code changes. The spec files are ready to copy/paste into Kiro.

🤖 Generated with Claude Code

https://claude.ai/code/session_01AXeAoddjxobXLUw72RBh1o

@plauzy
plauzy force-pushed the claude/kiro-specs-ag-ui-l2-tyclkz branch 2 times, most recently from 94857e6 to ed31d1a Compare July 17, 2026 09:32
alexmercenary and others added 4 commits July 17, 2026 20:42
…_agent_step (awslabs#423)

When a handoff call does not supply an explicit working_directory,
run_agent_step now resolves it from the caller's terminal via
terminal_service.get_working_directory(caller_id). Without this, the
handoff worker starts in the cao-server process CWD instead of the
supervisor's project directory.

This is a server-side fix (Option B): the resolution is a local Python
call, not an extra HTTP round-trip. The assign path resolved CWD
client-side over HTTP; this PR resolves server-side in-process.

Best-effort: if resolution fails (e.g. caller terminal no longer live),
working_directory stays None and the server default is used — same
degraded behaviour as the assign path.

Co-authored-by: Alex Mercer <alex.mercer@digitalriot.co.uk>
…sinks (awslabs#166/awslabs#167/awslabs#168) (awslabs#461)

* fix(security): colocate CodeQL path-injection guards with fs sinks in workflow_spec_service

Clears three py/path-injection alerts (code-scanning awslabs#166/awslabs#167/awslabs#168) on
src/cli_agent_orchestrator/services/workflow_spec_service.py:

- awslabs#166 open() in load_and_validate
- awslabs#167 open() in validate_only
- awslabs#168 os.path.isfile() in get_workflow

Root cause: _safe_spec_path resolved + containment-checked a spec path
then RETURNED it. CodeQL's str.startswith barrier is flow-sensitive and
function-local, so the checked state was lost across the return and the
caller's open()/isfile() sink saw a normalized-but-unchecked path. (Sinks
reached via the SQLite index round-trip are not flagged because taint is
not propagated through the DB.)

Fix: colocate the containment SafeAccessCheck with each filesystem sink
inside guarded helpers so the guard dominates the sink within one
function:
- _read_contained_spec_bytes: guard + isfile + open (used by
  load_and_validate, validate_only, _read_script_spec)
- _contained_spec_file: guard + isfile (used by get_workflow's probe)

The guard uses the single positive startswith(base + os.sep) idiom from
CodeQL's own GOOD example (the trailing separator also closes the
/base vs /base-evil prefix hole). Containment semantics, the byte cap,
the single-read TOCTOU guarantee, and validate_only's never-raise
contract are all preserved. Adds TestColocatedPathGuards (11 tests).

* fix(security): use clean single-startswith guard in _contained_spec_file

The first push cleared alerts awslabs#166/awslabs#167 but CodeQL raised a new
py/path-injection at the os.path.isfile sink in _contained_spec_file
because that helper kept the COMPOUND guard (real_path != base and not
startswith): on the real_path == base branch the sink is reached without
the startswith holding, so CodeQL does not treat it as a barrier.

Switch to the same clean single positive startswith(base + os.sep) guard
_read_contained_spec_bytes uses (which cleared its own sinks). A path
resolving exactly to the base dir is not a spec file, so rejecting it is
correct behavior; get_workflow's downstream outcome (ValueError -> 400)
is unchanged.
… policy

Adds the Kiro spec for the AG-UI L2 construct library (issue awslabs#458):
requirements, design, tasks and an audit grounding the spec against
ag-ui main and CAO main. Also documents the version-control policy for
agent context files (.kiro/ and .agents/).
Promotes the AG-UI Dojo integration plan to a full Kiro spec
(requirements, design, tasks, plan) describing how the CLI Agent
Orchestrator is wired into the ag-ui dojo (awslabs#458 Phase-3).
@plauzy
plauzy force-pushed the claude/kiro-specs-ag-ui-l2-tyclkz branch from ed31d1a to b099060 Compare July 18, 2026 01:51
…CAO 41c8ce7)

Delta review since the original grounding pins (ag-ui b646b46, CAO 1b00753):
no cited surface changed in either repo — full delta analysis appended to
.kiro/specs/agui-l2-constructs/audit.md as a re-audit addendum.

Applied updates:
- Refresh grounding pins across all six spec documents.
- Fold in the two new upstream example-server conventions from the ag-ui
  delta: never combine allow_credentials with wildcard CORS origins
  (CORS_ALLOW_ORIGINS pattern, 3b370a5 / #1939 #1940) and expose /health at
  the root path (691dae8) — new AC 3.7 + design/tasks notes in the dojo spec.
- Fix the Discord channel name to #-💎-contributing (emoji is part of the
  actual channel name per CONTRIBUTING.md).
- Reviewed the Kiro-promoted dojo spec trio (requirements/design/tasks)
  line-by-line against the verified plan: faithful, no ungrounded claims
  introduced; CAO's own CORS confirmed safe (explicit origin list, not the
  banned wildcard+credentials pattern).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AXeAoddjxobXLUw72RBh1o
plauzy added a commit that referenced this pull request Jul 18, 2026
…ementation

Add the Phase-3 AG-UI Dojo integration spec so both AG-UI specs travel with
the CAO implementation on this branch. Content is the canonical folded version
from spec/agui-standalone-v3 (source of truth commit b9b4d29, PRs #29/#30;
pins ag-ui 3a7433e / CAO 41c8ce7). The agui-l2-constructs spec already on this
branch is left untouched.

Co-authored-by: plauzy <plauzy@users.noreply.github.com>
…clkz

Resolves the add/add conflicts in .kiro/specs/agui-l2-constructs/{audit,design}.md
by keeping the branch versions, which strictly supersede the base versions
(verified: base contributes zero unique content lines — its side only lacked
the 2026-07-18 re-audit additions).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AXeAoddjxobXLUw72RBh1o
plauzy added a commit that referenced this pull request Jul 20, 2026
…ementation

Add the Phase-3 AG-UI Dojo integration spec so both AG-UI specs travel with
the CAO implementation on this branch. Content is the canonical folded version
from spec/agui-standalone-v3 (source of truth commit b9b4d29, PRs #29/#30;
pins ag-ui 3a7433e / CAO 41c8ce7). The agui-l2-constructs spec already on this
branch is left untouched.

Co-authored-by: plauzy <plauzy@users.noreply.github.com>
plauzy added a commit that referenced this pull request Jul 20, 2026
…ementation

Add the Phase-3 AG-UI Dojo integration spec so both AG-UI specs travel with
the CAO implementation on this branch. Content is the canonical folded version
from spec/agui-standalone-v3 (source of truth commit b9b4d29, PRs #29/#30;
pins ag-ui 3a7433e / CAO 41c8ce7). The agui-l2-constructs spec already on this
branch is left untouched.

Co-authored-by: plauzy <plauzy@users.noreply.github.com>
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.

5 participants