Skip to content

feat(extensions): capability-surface vocabulary and manifest projection (NEA-25 stack 1/7) - #5833

Closed
BenKurrek wants to merge 1 commit into
mainfrom
nea25/01-manifest-surface-model
Closed

BenKurrek wants to merge 1 commit into
mainfrom
nea25/01-manifest-surface-model

Conversation

@BenKurrek

Copy link
Copy Markdown
Collaborator

Summary

Stack PR 1/7 for NEA-25 (unified extension surfaces — the top-level product object is always an extension; a channel is one capability surface an extension declares, not a sibling product type).

  • Adds CapabilitySurfaceKind (tool / channel / auth + reserved trigger / file) to ironclaw_host_api — shared vocabulary beside RuntimeKind. Placement note: product_workflow depends on host_api but not on ironclaw_extensions, so the vocabulary lives in host_api to keep the facade layer off substrate types.
  • Derives an order-stable ExtensionManifestV2::capability_surfaces() projection:
    • one tool surface per capability declaration (top-level or capability_provider projected);
    • host-API contract sections project their declared kinds via HostApiManifestProjection::surfaces, origin-stamped with the owning host-API id + section path — the real ironclaw.product_adapter/v1 contract projects channel for external_channel sections; host-native web/cli/synchronous_api sections project none;
    • one auth surface per distinct product-auth provider (OAuth scopes unioned sorted-dedup; OAuth masks weaker manual-token setups; retired-only providers surface as retired rather than being dropped).
  • Fail closed: a contract projecting tool/auth section surfaces is rejected — those kinds have dedicated declaration paths.
  • RuntimeKind stays internal: runtime never decides surface taxonomy.
  • Contract doc: docs/reborn/contracts/extensions.md new "Capability surfaces" section names the pinned tests (house pattern).

No product behavior change: existing manifests parse unchanged; surfaces are derived read-model vocabulary consumed by the next PRs in the stack (surface discovery replaces the connectable-channels rail; Slack unifies to one slack extension).

Testing

  • cargo test -p ironclaw_host_api — wire-shape pin for the new enum
  • cargo test -p ironclaw_extensions --test manifest_v2_contract — 52 pass, incl. new: tool-only projection; per-provider auth surface with unioned scopes; gmail/google-drive-shaped manifests sharing provider google with provider id ≠ extension id; tool+channel manifest via the real capability-provider contract + a channel-projecting contract; fail-closed tool/auth section-surface rejection
  • cargo test -p ironclaw_product_adapter_registry — incl. new caller-level tests through parse_product_adapter_manifest_record with the real contract: external_channel section → channel surface with origin; web section → none
  • cargo test -p ironclaw_architecture — boundary tests pass
  • cargo clippy on the three touched crates — clean; cargo check -p ironclaw_host_runtime -p ironclaw_reborn_composition -p ironclaw_reborn_migration --all-features — clean
  • Not run: --features integration (no DB-shaped change; substrate parser/vocabulary only — integration harness has no seam observing a pure manifest projection)

🤖 Generated with Claude Code

@ironloopai

ironloopai Bot commented Jul 8, 2026 •

Copy link
Copy Markdown
Contributor

🔎 IronLoop Review Status

Head: 60e98ab92725dd9cece8526b95f94757d6657073
Result: No reviewer jobs are scheduled yet.
Next: Run @ironloopai review to start reviewers.
Updated: 2026-07-09T17:40:48.747Z

Current reviewers:

Reviewer State Verdict Findings Last update
none Queued N/A No reviewer jobs scheduled yet. N/A
Reviewer summaries
Reviewer Detail
none No reviewer jobs scheduled yet.
Recent activity
Time Reviewer State Detail
N/A N/A Waiting No progress events recorded yet.
Available commands
  • @ironloopai help
  • @ironloopai agents
  • @ironloopai review
  • @ironloopai review --agent <agent>
  • @ironloopai status
Run metadata

Admission: webhook accepted the request and IronLoop persisted reviewer state before this projection.

@railway-app
railway-app Bot temporarily deployed to ironclaw-ci-preview / ironclaw-pr-5833 July 8, 2026 14:25 Destroyed
@github-actions github-actions Bot added scope: docs Documentation size: L 200-499 changed lines risk: low Changes to docs, tests, or low-risk modules contributor: core 20+ merged PRs labels Jul 8, 2026
@coderabbitai

coderabbitai Bot commented Jul 8, 2026 •

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 265e808c-6b75-47c4-9453-30838155851e

📥 Commits

Reviewing files that changed from the base of the PR and between b081db0 and 0fda67b.

📒 Files selected for processing (6)
  • crates/ironclaw_extensions/src/host_api/capability_provider.rs
  • crates/ironclaw_extensions/src/lib.rs
  • crates/ironclaw_extensions/src/v2.rs
  • crates/ironclaw_extensions/tests/manifest_v2_contract.rs
  • crates/ironclaw_host_api/src/lib.rs
  • crates/ironclaw_host_api/src/surface.rs

📝 Walkthrough

Summary by CodeRabbit

  • New Features
    • Added capability-surface projection for extension manifests (tool, channel, auth), including host-API contract section–derived surfaces.
    • Product adapter manifests can project a channel surface for external_channel sections.
  • Bug Fixes
    • Host API contracts are now strictly rejected from projecting tool or auth surfaces (fail-closed).
    • Capability-surface results are order-stable and include consistent origin details for contract-derived surfaces.
  • Documentation
    • Documented capability-surface projection rules in the extensions contracts guide.
  • Tests
    • Added coverage for capability-surface projection, including auth scope merging and fail-closed behavior.

Walkthrough

Adds capability-surface vocabulary and projection plumbing across host APIs, manifest aggregation, product-adapter projection, tests, and contract documentation.

Changes

Capability surface projection

Layer / File(s) Summary
Capability surface vocabulary
crates/ironclaw_host_api/src/lib.rs, crates/ironclaw_host_api/src/surface.rs
Defines CapabilitySurfaceKind with serde serialization, string conversion, display behavior, and unit tests.
Manifest surface projection
crates/ironclaw_extensions/src/v2.rs, crates/ironclaw_extensions/src/host_api/capability_provider.rs, crates/ironclaw_extensions/src/lib.rs
Adds host-API surface declarations, rejects Tool and Auth section projections, and combines tool, host-API, and auth surfaces in manifest output.
Product adapter channel projection
crates/ironclaw_product_adapter_registry/src/lib.rs, crates/ironclaw_product_adapter_registry/tests/manifest_ingestion.rs
Projects Channel for external_channel sections and validates channel origin and non-channel behavior.
Projection contract validation
crates/ironclaw_extensions/tests/manifest_v2_contract.rs, docs/reborn/contracts/extensions.md, crates/ironclaw_product_adapter_registry/CLAUDE.md
Tests tool, auth, provider-grouping, host-API, and fail-closed projection rules, and documents the capability-surface contract.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
  participant ExtensionManifest
  participant HostApiContract
  participant ProductAdapterContract
  participant ManifestSurfaceAggregator

  ExtensionManifest->>HostApiContract: project host-api section
  HostApiContract->>ProductAdapterContract: parse and classify section
  ProductAdapterContract-->>ExtensionManifest: return Channel surface for external_channel
  ExtensionManifest->>ManifestSurfaceAggregator: combine tool, host-api, and auth surfaces
  ManifestSurfaceAggregator-->>ExtensionManifest: return ordered capability surfaces
Loading

Possibly related PRs

  • nearai/ironclaw#5893: Refactors ProductAdapterHostApiContract registration and discovery used by this projection path.
🚥 Pre-merge checks | ✅ 3 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Description check ⚠️ Warning The summary/testing are detailed, but required template sections like Change Type, Linked Issue, Security Impact, and Rollback Plan are missing. Fill out the template sections, especially Change Type, Linked Issue, Validation, Security Impact, Database Impact, Blast Radius, and Rollback Plan.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed Conventional Commits-style title matches the extension-surface vocabulary and projection changes, with the stack marker included.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@gemini-code-assist

Copy link
Copy Markdown
Contributor

Warning

Gemini encountered an error creating the review. You can try again by commenting /gemini review.

@ironloopai ironloopai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ IronLoop Review: reviewer

Review at a glance

Verdict Blocking Notes Inline Head
✅ Approved 0 0 0 014e49adaa27

Head: 014e49adaa2705a08eaaf21240b1b9954bbd36f4
Next: No reviewer action needed.

Run details

Status: Current
Needs human: no
Needs validation: no

Summary

No concrete blocking issues found in the reviewed merge diff. The change adds capability-surface vocabulary, manifest projection, product-adapter channel projection, and focused contract coverage.

Findings

None.

Developer follow-up

After fixing this feedback:

  1. Push the fix to this PR branch.
  2. Re-run this reviewer with @ironloopai review --agent reviewer if you only changed this reviewer's findings.
  3. Re-run all reviewers with @ironloopai review when the fix may affect multiple areas.
  4. Use @ironloopai status to check queued/running/completed/stale/stalled state while reviewers run.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@crates/ironclaw_extensions/tests/manifest_v2_contract.rs`:
- Around line 1624-1727: Add a retired-only auth projection regression test
because the manifest contract suite currently covers OAuth/manual-token auth
surfaces but not provider references that resolve only to
RuntimeCredentialAccountSetup::Retired. In
crates/ironclaw_extensions/tests/manifest_v2_contract.rs, add a test alongside
tool_only_manifest_projects_one_tool_surface_per_capability_and_nothing_else and
product_auth_credentials_project_one_auth_surface_per_provider_with_unioned_scopes
that builds a manifest with a provider setup resolving to Retired, then assert
capability_surfaces() returns exactly one CapabilitySurfaceDeclV2::Auth with the
expected provider and setup = Retired.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: c8218b14-a74e-4902-b309-3b8f8ef3c985

📥 Commits

Reviewing files that changed from the base of the PR and between 1ae9310 and 014e49a.

📒 Files selected for processing (10)
  • crates/ironclaw_extensions/src/host_api/capability_provider.rs
  • crates/ironclaw_extensions/src/lib.rs
  • crates/ironclaw_extensions/src/v2.rs
  • crates/ironclaw_extensions/tests/manifest_v2_contract.rs
  • crates/ironclaw_host_api/src/lib.rs
  • crates/ironclaw_host_api/src/surface.rs
  • crates/ironclaw_product_adapter_registry/CLAUDE.md
  • crates/ironclaw_product_adapter_registry/src/lib.rs
  • crates/ironclaw_product_adapter_registry/tests/manifest_ingestion.rs
  • docs/reborn/contracts/extensions.md

Comment thread crates/ironclaw_extensions/tests/manifest_v2_contract.rs
@github-actions

github-actions Bot commented Jul 8, 2026 •

Copy link
Copy Markdown
Contributor

Coverage ratchet

Ratchet mode: ENFORCING

RATCHET PASS: global
  observed: 85.39% (297181 / 348046 lines)
  floor:    85.3% (tolerance 0.5pp -> effective floor 84.8%)
  denominator: 348046 lines now vs 320188 at floor capture (+27858 lines, +8.7%) — material change (>5%)

⚠️ 2 Reborn crate(s) have 0 int-tier coverage (target: 0) — ironclaw_prompt_envelope, ironclaw_scripts

Reborn integration-tier coverage

Line coverage (Reborn crates): 85.39% — 297181 / 348046 lines

Per-crate breakdown (63 crates, lowest-covered first)
Crate Line % Covered / Total
ironclaw_prompt_envelope 0% 0 / 88
ironclaw_scripts 0% 0 / 345
ironclaw_runtime_policy 31.75% 80 / 252
ironclaw_event_projections 43.31% 673 / 1554
ironclaw_run_state 52.36% 222 / 424
ironclaw_authorization 53.66% 462 / 861
ironclaw_triggers 59.89% 1792 / 2992
ironclaw_observability 61.54% 16 / 26
ironclaw_webui_v2 62.93% 2679 / 4257
ironclaw_mcp 63.03% 578 / 917
ironclaw_reborn_cli 66.2% 4492 / 6785
ironclaw_reborn_migration 67.09% 1215 / 1811
ironclaw_filesystem 67.1% 3833 / 5712
ironclaw_dispatcher 67.15% 92 / 137
ironclaw_memory 69.2% 773 / 1117
ironclaw_trust 72.88% 661 / 907
ironclaw_capabilities 74.39% 1685 / 2265
ironclaw_wasm_limiter 74.6% 47 / 63
ironclaw_reborn_event_store 74.67% 958 / 1283
ironclaw_extractors 74.72% 538 / 720
ironclaw_first_party_extensions 78.23% 5439 / 6953
ironclaw_llm 78.36% 20328 / 25941
ironclaw_product_context 78.57% 11 / 14
ironclaw_process_sandbox 80.65% 671 / 832
ironclaw_wasm_product_adapters 80.71% 1448 / 1794
ironclaw_memory_native 81.22% 3205 / 3946
ironclaw_secrets 82.7% 2791 / 3375
ironclaw_wasm 82.72% 996 / 1204
ironclaw_events 82.86% 1765 / 2130
ironclaw_reborn_identity 83.59% 433 / 518
ironclaw_auth 83.87% 3078 / 3670
ironclaw_reborn_config 84.06% 1814 / 2158
ironclaw_processes 84.44% 993 / 1176
ironclaw_turns 84.85% 13560 / 15982
ironclaw_common 84.85% 1490 / 1756
ironclaw_host_api 85.28% 2688 / 3152
ironclaw_product_workflow 85.56% 10836 / 12665
ironclaw_projects 85.92% 659 / 767
ironclaw_threads 86.07% 4404 / 5117
ironclaw_network 86.12% 670 / 778
ironclaw_product_adapter_registry 86.33% 537 / 622
ironclaw_slack_v2_adapter 86.79% 1806 / 2081
ironclaw_product_adapters 86.98% 3207 / 3687
ironclaw_skills 87.6% 4471 / 5104
ironclaw_hooks 87.75% 9917 / 11302
ironclaw_reborn_traces 88.19% 11946 / 13546
ironclaw_host_runtime 88.53% 17271 / 19509
ironclaw_reborn_composition 89.08% 76644 / 86040
ironclaw_extensions 89.19% 2922 / 3276
ironclaw_approvals 89.24% 1584 / 1775
ironclaw_runner 89.28% 16696 / 18700
ironclaw_reborn_openai_compat 89.46% 3768 / 4212
ironclaw_conversations 90.33% 3120 / 3454
ironclaw_event_streams 90.82% 1009 / 1111
ironclaw_loop_host 92.51% 14755 / 15950
ironclaw_resources 92.83% 4736 / 5102
ironclaw_attachments 93.06% 630 / 677
ironclaw_reborn_webui_ingress 93.19% 2217 / 2379
ironclaw_telegram_v2_adapter 93.62% 2511 / 2682
ironclaw_agent_loop 94.57% 8789 / 9294
ironclaw_safety 94.88% 3671 / 3869
ironclaw_first_party_extension_ports 95.24% 3343 / 3510
ironclaw_outbound 95.59% 3556 / 3720

This table itself is informational and never gates the PR on its own — not the percentage, not the per-crate holes, not the 0-coverage callout. A separate coverage ratchet (dry-run until enforce=true; see tests/integration/coverage-floor.toml) can fail the build on specific configured floors.

Exemptions (3 entry/entries excluded from the accounting above)
Module / Crate Reason Issue
crate: ironclaw_embeddings v1-only: consumed only by root ironclaw (src/app.rs, src/tools/builtin/memory.rs, src/workspace/mod.rs, src/config/{mod,embeddings}.rs); no crates/* dependents. Covered by "Tests (Legacy)". #5657
crate: ironclaw_gateway v1-only: consumed only by root ironclaw (src/channels/web/platform/static_files.rs, src/channels/web/handlers/frontend.rs); no crates/* dependents. Covered by "Tests (Legacy)". #5657
crate: ironclaw_tui v1-only: consumed only by root ironclaw (src/main.rs, src/channels/tui.rs); no crates/* dependents. Crate's own doc comment confirms it bridges INTO v1, not Reborn. Covered by "Tests (Legacy)". #5657

@railway-app

railway-app Bot commented Jul 8, 2026 •

Copy link
Copy Markdown

🚅 Deployed to the ironclaw-pr-5833 environment in ironclaw-ci-preview

Service Status Web Updated (UTC)
ironclaw ✅ Success (View Logs) Web Jul 13, 2026 at 4:25 pm

Introduce CapabilitySurfaceKind (tool/channel/auth + reserved
trigger/file) in ironclaw_host_api and derive an order-stable
capability-surface projection on ExtensionManifestV2: one tool surface
per capability declaration, contract-projected section surfaces
(ironclaw.product_adapter/v1 external_channel sections project the
channel surface; host-native web/cli/synchronous_api sections project
none), and one auth surface per distinct product-auth provider with
OAuth scopes unioned. Host API contracts projecting tool/auth section
surfaces fail closed - those kinds have dedicated declaration paths.

The extension is the top-level product object; surfaces answer "which
faces of this extension can be enabled?" without a separate channel
registry and without runtime kind leaking into product taxonomy
(NEA-25, stack PR 1 of unified extension surfaces).

Contract: docs/reborn/contracts/extensions.md "Capability surfaces"
names the pinned tests (manifest_v2_contract.rs surface block;
manifest_ingestion.rs projection through the real adapter contract).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@BenKurrek
BenKurrek force-pushed the nea25/01-manifest-surface-model branch from 60e98ab to 0fda67b Compare July 13, 2026 16:15
@railway-app
railway-app Bot temporarily deployed to ironclaw-ci-preview / ironclaw-pr-5833 July 13, 2026 16:25 Destroyed
BenKurrek added a commit that referenced this pull request Jul 13, 2026
…#5850)

Atomic roll-up of the 8-PR NEA-25 taxonomy stack onto current main. Extension is
the only installable product object; tool/channel/auth are derived capability
surfaces; runtime kind controls loading only; manifest projection (v2, host_api
contracts) is the sole surface-discovery source of truth. The connectable-channels
rail and the parallel `kind` taxonomy are removed and pinned by a zero-legacy gate.
slack_bot and slack_personal are retired into one `slack` extension with bounded
forward migrations. Extensions wire carries runtime + surfaces, not a conflated kind.

Supersedes #5833, #5839, #5842, #5845, #5847, #5848, #5849, #5850. Conflicts with
main since the train forked were reconciled preserving main's newer behavior
(#5851 unified slack cleanup, #6054 get_conversation_info DM resolution, #5499
extension import, #6057 TS source conventions). provider_identity domain
duplication removed; the residual is a legitimate up-layer port adapter. See the PR
description for the per-PR crosswalk, resolutions, placement audit, and verification.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@BenKurrek BenKurrek closed this Jul 20, 2026

This branch was successfully deployed

No deployments
ironclaw-ci-preview / ironclaw-pr-5833 — 0fda67b3 Deployed Jul 13, 2026 by railway-app[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

contributor: core 20+ merged PRs risk: low Changes to docs, tests, or low-risk modules scope: docs Documentation size: L 200-499 changed lines

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant