Skip to content

matrix: add openhands, amp, kiro and factory_droid (A3, vendor-docs) - #180

Merged
jothimani-rajendran merged 4 commits into
mainfrom
a3-openhands-amp-kiro-factory
Oct 11, 2026
Merged

jothimani-rajendran merged 4 commits into
mainfrom
a3-openhands-amp-kiro-factory

Conversation

@jothimani-rajendran

@jothimani-rajendran jothimani-rajendran commented Oct 11, 2026 •

Copy link
Copy Markdown
Collaborator

What this changes

This is batch A3 of org-plan plan/one-oh-gaps.md (at 5271b89). It adds four matrix rows, all at basis: vendor-docs.

  • openhands gets a real, config-only adapter in the flat_decision family.
    • src/agentseam/data/vendors/openhands.json is added and joins _CONFIG_DRIVEN.
    • A golden fixture, tests/test_adapter_openhands.py (14 tests) and examples/generated/openhands.md come with it.
    • No core or engine change was needed.
  • amp, kiro and factory_droid get unadapted rows with events {}, dated doc links and a note saying why.

Derived tiers at pre_tool, from agentseam tier-table. The table's own Tier column is the matrix's categorical tier field, which is set in the row; the grade and fail mode are derived.

Agent Tier Grade Fail mode Basis Recorded
openhands block best-effort open vendor-docs 2026-10-11
amp unadapted none n/a vendor-docs 2026-10-11
kiro unadapted none n/a vendor-docs 2026-10-11
factory_droid unadapted none n/a vendor-docs 2026-10-11

openhands' grades at its other events: best-effort at prompt_submit and stop; detect at post_tool, session_start and session_end.

Evidence-wanted issues, each linked from its row's notes:

Claim check

Why each of the three is unadapted

  • Amp. The only hook surface is an in-process TypeScript plugin API, which OPERATING keeps on watch. The legacy delegate permission helper is an exit-code check. It receives no event name and runs only when the user has already opted into the old permissions system.
  • Kiro. It has command hooks, but in a dialect no family speaks:
    • the config is {version: "v1", hooks: [{name, trigger, matcher, action: {type, command}}]}, which no install wrapper writes;
    • the verdict is an exit code only, and the IDE and CLI read it differently;
    • the payload has no key that separates it from Claude Code's.
  • Factory Droid. It speaks the Claude Code dialect, but its payload carries Claude Code's own keys, including transcript_path and permission_mode, which looks_like_claude_code treats as markers. A factory_droid claim would make detection ambiguous for every Claude Code payload too, and an ambiguous payload is allowed through. Separating the two needs a value-based probe, which is a core change.

Checks

  • pytest -q passes locally: 2117 passed, 4 skipped
  • ruff check . and ruff format --check . pass
  • The runtime path is still stdlib-only (tests/check_stdlib_only.py OK)
  • Commits are signed off

Notes for the reviewer

Measured risk, recorded in the kiro row rather than fixed (it would need a core change). Today detect() assigns a Kiro-shaped payload to claude_code. A deny then goes back as a JSON body with exit 0, and Kiro reads only the exit code, so the deny would not block. The row says Kiro is not a supported target. A Droid-shaped payload is also detected as claude_code, and its wire answer is the one Droid documents. However, Droid's Execute and Create tools are not in Claude Code's tool lists, so a policy keyed on shell or write tools would not recognise those calls. The factory_droid row records this.

Known OpenHands limit, recorded in the row. file_editor carries its own sub-command (create, str_replace and so on) in tool_input.command, the same key the shell tool uses. So Event.command carries it for file-editor calls.

Changes beyond the plan's Touches, all required by invariant tests or CI generators:

  • Per-agent data: instructions.py (AGENTS.md for all four agents), allow-semantics for openhands, and the packaging and permissions unrecorded reasons.
  • Capture footprint: an openhands entry in tools/capture.py.
  • Recount entries: in tables.py and dialects.py.
  • Test probe: the test_decision_vocabulary probe adds event_type=.
  • Pins: the test_instructions pin moves from 21 to 25, as do the make_matrix and make_social pins.
  • Regenerated: the figures and the social preview.
  • Re-measured counts:
    • wiring counts in the event_log.py and notify.py docstrings: 11 of 14 and 13 of 14 adapters wire;
    • the adapter counts in tools/VERIFY.md and tools/capture.py: 12 of 14 adapters rest on docs or source.

README counts are left alone on purpose: A4 owns them.

Missing label: evidence wanted does not exist in this repo. The four issues carry help wanted only. Should the owner create the label?

🤖 Generated with Claude Code

jothimani-rajendran and others added 2 commits October 11, 2026 03:33
openhands gets a config-driven adapter in the flat_decision family. Its
hooks page (docs.openhands.dev, read 2026-10-11, against OpenHands v1.26.0
and agent SDK v1.54.0) documents a per-repository .openhands/hooks.json
that accepts the Claude Code format, the event name under `event_type`,
and a block as {"decision": "deny", "reason"} or exit 2 at PreToolUse,
UserPromptSubmit and Stop. A bare allow is exit 0. Any other exit code
proceeds, so the row is fail-open. Escalate and transform degrade to a
block. The derived grades are best-effort at pre_tool, prompt_submit and
stop, and detect elsewhere.

amp, kiro and factory_droid get unadapted rows with events {} and dated
doc links:
- Amp documents only an in-process TypeScript plugin API. Its legacy
  delegate permission helper is an exit-code check with no event name.
- Kiro has command hooks, but in a dialect no family speaks: a versioned
  list of named hooks with an action object, and an exit-code verdict
  that the IDE and CLI read differently.
- Factory Droid speaks the Claude Code dialect, but its payload carries
  the same keys as Claude Code's, including the markers used to
  recognise Claude Code. A factory_droid adapter would make detection
  ambiguous for Claude Code payloads too. Separating them needs a
  value-based probe, which is a core change.

The instruction-count pin moves to 25. The example docstrings' wiring
counts and the VERIFY.md adapter count are re-measured against 14
adapters.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Jothi Mani Rajendran <250249270+jothimani-rajendran@users.noreply.github.com>
The figure generator's 21-agent layout pin moves to 25. Its description
names the three new agents with nothing gateable at pre_tool, and the
thirteenth best-effort one. The figures and the brand-assets card are
regenerated from the package (14 adapters, 25 in the matrix).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Jothi Mani Rajendran <250249270+jothimani-rajendran@users.noreply.github.com>
jothimani-rajendran and others added 2 commits October 11, 2026 03:36
Each row's notes now point at its evidence-wanted issue: #181
(openhands), #182 (amp), #183 (kiro) and #184 (factory_droid). The
openhands example page is regenerated to carry the new note.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Jothi Mani Rajendran <250249270+jothimani-rajendran@users.noreply.github.com>
make_social.py renders the PNG from social-card.svg when cairosvg is
installed. The committed PNG still said 21 agents; this one matches
the SVG (25 agents x 12 events, 0 of 300 cells enforced). CI does not
reproduce the PNG, so the SVG stays the asserted artifact.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Jothi Mani Rajendran <250249270+jothimani-rajendran@users.noreply.github.com>
@jothimani-rajendran
jothimani-rajendran marked this pull request as ready for review October 11, 2026 03:40
@jothimani-rajendran
jothimani-rajendran merged commit 6af4365 into main Oct 11, 2026
19 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