Skip to content

refactor(reborn): rename LocalDevOutboundStores -> OutboundStores (§4.4) - #6220

Merged
ilblackdragon merged 1 commit into
mainfrom
refactor/reborn-rename-localdev-outbound-stores
Jul 18, 2026
Merged

ilblackdragon merged 1 commit into
mainfrom
refactor/reborn-rename-localdev-outbound-stores

Conversation

@ilblackdragon

Copy link
Copy Markdown
Member

What

Second §4.4 de-prefix (after C1's LocalDevRootFilesystem inline). Advances the doc's §4.4 enforcement endgame — "no public type name contains Local/LocalDev/Hosted/Enterprise" — one more type.

LocalDevOutboundStores is a plain bundle struct (four outbound-store handle fields), not a cfg-switched policy/mode type. Its own constructor comment states it "works in both durable (libsql/postgres) and no-durable (in-memory backend) builds" — so the LocalDev prefix is factually wrong (used in libsql/postgres production builds, not just local-dev). This is a bucket-2-style mis-prefix (a genuine composition type that only looks like a mode leak), so the fix is a de-prefix rename — not the bucket-1 DeploymentConfig resolution the cfg-switched LocalDev*Store aliases require.

Changes

  • Rename the struct + its 3 use sites (all in factory.rs) → OutboundStores (name was free).
  • Trim it from the R2 reborn_localdev_typename ratchet allowlist.
  • local_dev_outbound_store builder fn keeps its name (fn names aren't type-name leaks; the ratchet inventories types only).

Pure type rename, semantically identical.

Verification

  • localdev ratchet 4 tests; cargo build -p ironclaw_reborn_composition (default + libsql+slack+telegram) clean; clippy -D warnings clean; fmt + pre-commit clean

Stack

Stacked on #6218.

🤖 Generated with Claude Code

@ironloopai

ironloopai Bot commented Jul 18, 2026 •

Copy link
Copy Markdown
Contributor

🔎 IronLoop Review Status

Head: bcc2a5c7ca12b69af39ff23187f0b859a9572c3f
Result: One or more review results were superseded by a newer PR head.
Next: Run @ironloopai review on the latest PR head.
Updated: 2026-07-18T03:49:50.784Z

Current reviewers:

Reviewer State Verdict Findings Last update
ironloop/common-reviewer (reviewer) Superseded N/A N/A 2026-07-18T01:26:45.571Z
Reviewer summaries
Reviewer Detail
ironloop/common-reviewer (reviewer) Superseded by a newer PR head. New head: 71ce0ec. Previous verdict: Changes requested.
Recent activity
Time Reviewer State Detail
2026-07-18T01:20:58.944Z ironloop/common-reviewer (reviewer) Queued Accepted review request for head 0f66c28.
2026-07-18T01:20:58.944Z ironloop/common-reviewer (reviewer) Queued Waiting for this reviewer lane to become available.
2026-07-18T01:20:59.883Z ironloop/common-reviewer (reviewer) Started Reviewer worker started.
2026-07-18T01:21:02.679Z ironloop/common-reviewer (reviewer) Workspace ready Prepared isolated checkout (head_ref) at 0f66c28.
2026-07-18T01:24:15.135Z ironloop/common-reviewer (reviewer) Superseded A newer PR head replaced this review (71ce0ec).
2026-07-18T01:26:45.571Z ironloop/common-reviewer (reviewer) Result captured Changes requested; 1 blocking finding.
2026-07-18T01:26:45.571Z ironloop/common-reviewer (reviewer) Superseded A newer PR head replaced this review (71ce0ec).
Available commands
  • @ironloopai help
  • @ironloopai agents
  • @ironloopai review
  • @ironloopai review --agent <agent>
Run metadata

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

@coderabbitai

coderabbitai Bot commented Jul 18, 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: 9e9f489e-313c-482c-b170-1fcfdcf57a64

📥 Commits

Reviewing files that changed from the base of the PR and between d1ceb09 and bcc2a5c.

📒 Files selected for processing (2)
  • crates/ironclaw_architecture/tests/reborn_localdev_typename_ratchet.rs
  • crates/ironclaw_reborn_composition/src/factory.rs
💤 Files with no reviewable changes (1)
  • crates/ironclaw_architecture/tests/reborn_localdev_typename_ratchet.rs

📝 Walkthrough

Summary by CodeRabbit

  • Refactor
    • Simplified internal outbound store naming and structure for local development.
    • No user-visible behavior changes.

Walkthrough

Renames LocalDevOutboundStores to OutboundStores in the local-dev outbound store factory and removes the former name from the local-dev typename ratchet allowlist. Outbound role wiring remains unchanged.

Changes

Outbound store type rename

Layer / File(s) Summary
Rename factory bundle and enforce typename ratchet
crates/ironclaw_reborn_composition/src/factory.rs, crates/ironclaw_architecture/tests/reborn_localdev_typename_ratchet.rs
The factory returns and constructs OutboundStores while preserving all four outbound-role assignments; the ratchet no longer allows LocalDevOutboundStores.

Estimated code review effort: 1 (Trivial) | ~5 minutes

Possibly related PRs

Suggested reviewers: serrrfirat

🚥 Pre-merge checks | ✅ 3 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description covers the rename and validation, but it misses most required template sections like Change Type, Linked Issue, Security Impact, and Rollback Plan. Rewrite it using the repository template and fill in all required sections, especially Change Type, Linked Issue, Validation, Security Impact, Database Impact, and Rollback Plan.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title uses conventional-commits style and accurately summarizes the rename and ratchet update.
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.

@railway-app
railway-app Bot temporarily deployed to ironclaw-ci-preview / ironclaw-pr-6220 July 18, 2026 01:21 Destroyed
@github-actions github-actions Bot added scope: dependencies Dependency updates size: XL 500+ changed lines risk: medium Business logic, config, or moderate-risk modules contributor: core 20+ merged PRs labels Jul 18, 2026

@gemini-code-assist gemini-code-assist 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.

Code Review

This pull request consolidates the in-memory test stores by removing InMemoryOutboundStateStore, InMemoryDeliveredGateRouteStore, and InMemoryTriggeredRunDeliveryStore in favor of using the production FilesystemOutboundStateStore backed by an in-memory filesystem (InMemoryBackend). A new test_support module is introduced in ironclaw_outbound to provide a helper for instantiating this consolidated store in tests. Usages across multiple crates and integration tests have been updated accordingly, and the architecture ratchets have been adjusted to reflect these removals. Additionally, redundant aliases like LocalDevRootFilesystem and LocalDevOutboundStores have been cleaned up and renamed to CompositeRootFilesystem and OutboundStores. As there are no review comments, I have no feedback to provide.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

@ilblackdragon
ilblackdragon force-pushed the refactor/reborn-rename-localdev-outbound-stores branch from 0f66c28 to 71ce0ec Compare July 18, 2026 01:24
@railway-app
railway-app Bot temporarily deployed to ironclaw-ci-preview / ironclaw-pr-6220 July 18, 2026 01:24 Destroyed
@github-actions github-actions Bot added size: XS < 10 changed lines (excluding docs) risk: low Changes to docs, tests, or low-risk modules and removed size: XL 500+ changed lines risk: medium Business logic, config, or moderate-risk modules labels Jul 18, 2026
@railway-app

railway-app Bot commented Jul 18, 2026 •

Copy link
Copy Markdown

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

Service Status Web Updated (UTC)
ironclaw 🕒 Building (View Logs) Web Jul 18, 2026 at 3:49 am

@ilblackdragon

Copy link
Copy Markdown
Member Author

✅ Ready for merge

Reviewed — trivial §4.4 rename (LocalDevOutboundStores → OutboundStores, +3/−4) with the LocalDev ratchet allowlist trimmed in lock-step; already based on the restacked #6218, no review comments, local ratchet + composition gates green. Stacked: merges after #6218.

🤖 Generated with Claude Code

@ilblackdragon
ilblackdragon force-pushed the refactor/reborn-inline-localdev-rootfilesystem branch from 4fad36a to bca5038 Compare July 18, 2026 03:04
@ilblackdragon
ilblackdragon force-pushed the refactor/reborn-rename-localdev-outbound-stores branch from 71ce0ec to 2cdd519 Compare July 18, 2026 03:05
ilblackdragon added a commit that referenced this pull request Jul 18, 2026
…name ratchet (§4.4/§10)

Completes the §4.4-mandated enforcement — "no public type name contains
Local/LocalDev/Hosted/Enterprise" (the doc says: "Enforce it with an
ironclaw_architecture test"). The existing `reborn_localdev_typename_ratchet`
owns `LocalDev*` (shrinking to empty as Slice B lands) and explicitly scopes out
"the broader Local*/Hosted* audit ... as a separate concern." This companion
ratchet owns that separate concern — the OTHER three prefixes:

- `Enterprise*` — NONE exist (achieved). Empty allowlist locks it in: a new
  `EnterpriseTierPolicy`-style mode leak fails the "no new" check.
- `Hosted*` — all `HostedMcp*`/discovery/egress, a Bucket-3 FALSE POSITIVE
  ("hosted MCP" is a real domain concept — a platform-hosted MCP server — not a
  hosted-TIER deployment mode). Frozen/justified so a genuine `HostedTierRuntime`
  leak can't slip in behind them.
- `Local*` (excluding `LocalDev*` → sibling ratchet, and `Locale*` → localization
  false positive) — the `LocalTriggerAccess*` family is genuine Bucket-1 debt
  (§4.4 folds `local_trigger_access` into "seed owner grant from config at boot,"
  a policy value); `LocalInvocationServicesResolver` awaits a design-call rename.

Reuses the shared `ratchet_support` scanner (comments/strings stripped,
visibility-aware, skips tests/examples/benches). Same frozen-set contract as the
sibling ratchets: no new type, no duplicate definition, trim on delete/rename.
Predicate uses `starts_with` (not `contains`) so mid-word `Local` (`HookLocalId`)
is not flagged; a self-test pins that + the `LocalDev`/`Locale` exclusions.

Test-only, no production change. Verified: 2 tests pass (frozen allowlist +
predicate self-test); clippy -D warnings clean; fmt + pre-commit clean.

Stacked on #6220.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@railway-app
railway-app Bot temporarily deployed to ironclaw-ci-preview / ironclaw-pr-6220 July 18, 2026 03:05 Destroyed
@ilblackdragon

Copy link
Copy Markdown
Member Author

Post-restack confirmation: rebased onto the updated chain after the #6212/#6214/#6221 merges. CI fully green — 18 pass / 0 fail. Still ready for merge.

@ilblackdragon
ilblackdragon force-pushed the refactor/reborn-inline-localdev-rootfilesystem branch from bca5038 to 0f07808 Compare July 18, 2026 03:30
@ilblackdragon
ilblackdragon force-pushed the refactor/reborn-rename-localdev-outbound-stores branch from 2cdd519 to e739afb Compare July 18, 2026 03:30
ilblackdragon added a commit that referenced this pull request Jul 18, 2026
…name ratchet (§4.4/§10)

Completes the §4.4-mandated enforcement — "no public type name contains
Local/LocalDev/Hosted/Enterprise" (the doc says: "Enforce it with an
ironclaw_architecture test"). The existing `reborn_localdev_typename_ratchet`
owns `LocalDev*` (shrinking to empty as Slice B lands) and explicitly scopes out
"the broader Local*/Hosted* audit ... as a separate concern." This companion
ratchet owns that separate concern — the OTHER three prefixes:

- `Enterprise*` — NONE exist (achieved). Empty allowlist locks it in: a new
  `EnterpriseTierPolicy`-style mode leak fails the "no new" check.
- `Hosted*` — all `HostedMcp*`/discovery/egress, a Bucket-3 FALSE POSITIVE
  ("hosted MCP" is a real domain concept — a platform-hosted MCP server — not a
  hosted-TIER deployment mode). Frozen/justified so a genuine `HostedTierRuntime`
  leak can't slip in behind them.
- `Local*` (excluding `LocalDev*` → sibling ratchet, and `Locale*` → localization
  false positive) — the `LocalTriggerAccess*` family is genuine Bucket-1 debt
  (§4.4 folds `local_trigger_access` into "seed owner grant from config at boot,"
  a policy value); `LocalInvocationServicesResolver` awaits a design-call rename.

Reuses the shared `ratchet_support` scanner (comments/strings stripped,
visibility-aware, skips tests/examples/benches). Same frozen-set contract as the
sibling ratchets: no new type, no duplicate definition, trim on delete/rename.
Predicate uses `starts_with` (not `contains`) so mid-word `Local` (`HookLocalId`)
is not flagged; a self-test pins that + the `LocalDev`/`Locale` exclusions.

Test-only, no production change. Verified: 2 tests pass (frozen allowlist +
predicate self-test); clippy -D warnings clean; fmt + pre-commit clean.

Stacked on #6220.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@railway-app
railway-app Bot temporarily deployed to ironclaw-ci-preview / ironclaw-pr-6220 July 18, 2026 03:30 Destroyed
@ilblackdragon

Copy link
Copy Markdown
Member Author

Post-restack confirmation (after #6213's merge): rebased onto main, CI fully green on the current head. Still ready for merge.

Base automatically changed from refactor/reborn-inline-localdev-rootfilesystem to main July 18, 2026 03:49
Second §4.4 de-prefix slice (after C1's LocalDevRootFilesystem inline). Advances
the doc's §4.4 enforcement endgame — "no public type name contains
Local/LocalDev/Hosted/Enterprise" — one more type.

`LocalDevOutboundStores` is a plain bundle struct (four outbound-store handle
fields), NOT a cfg-switched policy/mode type. Its own constructor comment says it
"works in both durable (libsql/postgres) and no-durable (in-memory backend)
builds" — so the `LocalDev` prefix is factually wrong (it is used in libsql/
postgres PRODUCTION builds, not just local-dev). This is a bucket-2-style
mis-prefix: a genuine composition type that only LOOKS like a deployment-mode
leak, so the fix is a de-prefix rename, not the bucket-1 DeploymentConfig
resolution the cfg-switched `LocalDev*Store` aliases need.

Renamed the struct + its 3 use sites (all in factory.rs) to `OutboundStores`
(name was free); trimmed it from the R2 `reborn_localdev_typename` ratchet
allowlist. The `local_dev_outbound_store` builder fn keeps its name (fn names are
not type-name leaks; the ratchet inventories types only).

Pure type rename, semantically identical. Verified: localdev ratchet 4; `cargo
build -p ironclaw_reborn_composition` (default + libsql+slack+telegram) clean;
clippy -D warnings clean; fmt + pre-commit clean.

Stacked on #6218.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@ilblackdragon
ilblackdragon force-pushed the refactor/reborn-rename-localdev-outbound-stores branch from e739afb to bcc2a5c Compare July 18, 2026 03:49
ilblackdragon added a commit that referenced this pull request Jul 18, 2026
…name ratchet (§4.4/§10)

Completes the §4.4-mandated enforcement — "no public type name contains
Local/LocalDev/Hosted/Enterprise" (the doc says: "Enforce it with an
ironclaw_architecture test"). The existing `reborn_localdev_typename_ratchet`
owns `LocalDev*` (shrinking to empty as Slice B lands) and explicitly scopes out
"the broader Local*/Hosted* audit ... as a separate concern." This companion
ratchet owns that separate concern — the OTHER three prefixes:

- `Enterprise*` — NONE exist (achieved). Empty allowlist locks it in: a new
  `EnterpriseTierPolicy`-style mode leak fails the "no new" check.
- `Hosted*` — all `HostedMcp*`/discovery/egress, a Bucket-3 FALSE POSITIVE
  ("hosted MCP" is a real domain concept — a platform-hosted MCP server — not a
  hosted-TIER deployment mode). Frozen/justified so a genuine `HostedTierRuntime`
  leak can't slip in behind them.
- `Local*` (excluding `LocalDev*` → sibling ratchet, and `Locale*` → localization
  false positive) — the `LocalTriggerAccess*` family is genuine Bucket-1 debt
  (§4.4 folds `local_trigger_access` into "seed owner grant from config at boot,"
  a policy value); `LocalInvocationServicesResolver` awaits a design-call rename.

Reuses the shared `ratchet_support` scanner (comments/strings stripped,
visibility-aware, skips tests/examples/benches). Same frozen-set contract as the
sibling ratchets: no new type, no duplicate definition, trim on delete/rename.
Predicate uses `starts_with` (not `contains`) so mid-word `Local` (`HookLocalId`)
is not flagged; a self-test pins that + the `LocalDev`/`Locale` exclusions.

Test-only, no production change. Verified: 2 tests pass (frozen allowlist +
predicate self-test); clippy -D warnings clean; fmt + pre-commit clean.

Stacked on #6220.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@railway-app
railway-app Bot temporarily deployed to ironclaw-ci-preview / ironclaw-pr-6220 July 18, 2026 03:49 Destroyed
@github-actions

Copy link
Copy Markdown
Contributor

Coverage ratchet

Ratchet mode: ENFORCING

RATCHET PASS: global
  observed: 85.58% (306523 / 358153 lines)
  floor:    85.3% (tolerance 0.5pp -> effective floor 84.8%)
  denominator: 358153 lines now vs 320188 at floor capture (+37965 lines, +11.86%) — 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.58% — 306523 / 358153 lines

Per-crate breakdown (65 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_observability 61.54% 16 / 26
ironclaw_authorization 62.46% 604 / 967
ironclaw_mcp 64.89% 595 / 917
ironclaw_triggers 65.44% 2142 / 3273
ironclaw_dispatcher 67.15% 92 / 137
ironclaw_filesystem 67.69% 3932 / 5809
ironclaw_channel_host 68.65% 219 / 319
ironclaw_memory 69.2% 773 / 1117
ironclaw_reborn_migration 71.64% 1551 / 2165
ironclaw_trust 72.88% 661 / 907
ironclaw_reborn_cli 73.98% 7095 / 9591
ironclaw_capabilities 74.36% 1685 / 2266
ironclaw_wasm_limiter 74.6% 47 / 63
ironclaw_reborn_event_store 74.67% 958 / 1283
ironclaw_extractors 74.72% 538 / 720
ironclaw_projects 76.48% 400 / 523
ironclaw_llm 78.27% 20216 / 25827
ironclaw_product_context 78.57% 11 / 14
ironclaw_telegram_extension 80.18% 4842 / 6039
ironclaw_wasm_product_adapters 80.36% 1448 / 1802
ironclaw_process_sandbox 80.65% 671 / 832
ironclaw_first_party_extensions 81.06% 5965 / 7359
ironclaw_memory_native 81.22% 3205 / 3946
ironclaw_events 81.43% 1539 / 1890
ironclaw_secrets 82.79% 2794 / 3375
ironclaw_network 82.98% 673 / 811
ironclaw_reborn_identity 83.59% 433 / 518
ironclaw_processes 83.76% 939 / 1121
ironclaw_run_state 83.96% 424 / 505
ironclaw_reborn_config 84.02% 1830 / 2178
ironclaw_wasm 84.44% 1069 / 1266
ironclaw_auth 84.81% 3233 / 3812
ironclaw_product_workflow 84.91% 11031 / 12992
ironclaw_turns 85.04% 13722 / 16136
ironclaw_host_api 85.37% 2701 / 3164
ironclaw_channel_delivery 85.79% 1383 / 1612
ironclaw_common 86.13% 1714 / 1990
ironclaw_threads 86.93% 4708 / 5416
ironclaw_slack_v2_adapter 87.3% 1491 / 1708
ironclaw_skills 87.58% 4470 / 5104
ironclaw_hooks 87.78% 9921 / 11302
ironclaw_product_adapter_registry 88.06% 531 / 603
ironclaw_product_adapters 88.1% 3384 / 3841
ironclaw_reborn_traces 88.2% 11946 / 13544
ironclaw_reborn_composition 88.38% 70503 / 79773
ironclaw_webui 88.42% 7333 / 8293
ironclaw_host_runtime 88.76% 18005 / 20284
ironclaw_extensions 89.38% 2971 / 3324
ironclaw_runner 89.5% 16990 / 18983
ironclaw_reborn_openai_compat 89.5% 3778 / 4221
ironclaw_telegram_v2_adapter 89.7% 2717 / 3029
ironclaw_approvals 90.18% 1598 / 1772
ironclaw_conversations 90.39% 3123 / 3455
ironclaw_event_streams 90.82% 1009 / 1111
ironclaw_resources 91.65% 4476 / 4884
ironclaw_loop_host 92.25% 15051 / 16316
ironclaw_attachments 93.06% 630 / 677
ironclaw_agent_loop 94.88% 9184 / 9680
ironclaw_safety 95.04% 3677 / 3869
ironclaw_outbound 95.52% 3451 / 3613
ironclaw_first_party_extension_ports 95.62% 3672 / 3840

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

@ilblackdragon
ilblackdragon merged commit a0bd735 into main Jul 18, 2026
64 checks passed
@ilblackdragon
ilblackdragon deleted the refactor/reborn-rename-localdev-outbound-stores branch July 18, 2026 04:03
@ilblackdragon

Copy link
Copy Markdown
Member Author

Post-restack confirmation (after #6216/#6218 merges): rebased onto main, CI fully green — 56 pass / 0 fail. Verified the default and libsql-only clippy lanes locally per the new feature-matrix rule (PR CI runs only the all-features lane). Ready for merge — next in the chain.

ilblackdragon added a commit that referenced this pull request Jul 18, 2026
…name ratchet (§4.4/§10) (#6222)

* refactor(reborn): rename LocalDevOutboundStores -> OutboundStores (§4.4)

Second §4.4 de-prefix slice (after C1's LocalDevRootFilesystem inline). Advances
the doc's §4.4 enforcement endgame — "no public type name contains
Local/LocalDev/Hosted/Enterprise" — one more type.

`LocalDevOutboundStores` is a plain bundle struct (four outbound-store handle
fields), NOT a cfg-switched policy/mode type. Its own constructor comment says it
"works in both durable (libsql/postgres) and no-durable (in-memory backend)
builds" — so the `LocalDev` prefix is factually wrong (it is used in libsql/
postgres PRODUCTION builds, not just local-dev). This is a bucket-2-style
mis-prefix: a genuine composition type that only LOOKS like a deployment-mode
leak, so the fix is a de-prefix rename, not the bucket-1 DeploymentConfig
resolution the cfg-switched `LocalDev*Store` aliases need.

Renamed the struct + its 3 use sites (all in factory.rs) to `OutboundStores`
(name was free); trimmed it from the R2 `reborn_localdev_typename` ratchet
allowlist. The `local_dev_outbound_store` builder fn keeps its name (fn names are
not type-name leaks; the ratchet inventories types only).

Pure type rename, semantically identical. Verified: localdev ratchet 4; `cargo
build -p ironclaw_reborn_composition` (default + libsql+slack+telegram) clean;
clippy -D warnings clean; fmt + pre-commit clean.

Stacked on #6218.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* test(reborn): add the Hosted*/Enterprise*/Local* deployment-mode-typename ratchet (§4.4/§10)

Completes the §4.4-mandated enforcement — "no public type name contains
Local/LocalDev/Hosted/Enterprise" (the doc says: "Enforce it with an
ironclaw_architecture test"). The existing `reborn_localdev_typename_ratchet`
owns `LocalDev*` (shrinking to empty as Slice B lands) and explicitly scopes out
"the broader Local*/Hosted* audit ... as a separate concern." This companion
ratchet owns that separate concern — the OTHER three prefixes:

- `Enterprise*` — NONE exist (achieved). Empty allowlist locks it in: a new
  `EnterpriseTierPolicy`-style mode leak fails the "no new" check.
- `Hosted*` — all `HostedMcp*`/discovery/egress, a Bucket-3 FALSE POSITIVE
  ("hosted MCP" is a real domain concept — a platform-hosted MCP server — not a
  hosted-TIER deployment mode). Frozen/justified so a genuine `HostedTierRuntime`
  leak can't slip in behind them.
- `Local*` (excluding `LocalDev*` → sibling ratchet, and `Locale*` → localization
  false positive) — the `LocalTriggerAccess*` family is genuine Bucket-1 debt
  (§4.4 folds `local_trigger_access` into "seed owner grant from config at boot,"
  a policy value); `LocalInvocationServicesResolver` awaits a design-call rename.

Reuses the shared `ratchet_support` scanner (comments/strings stripped,
visibility-aware, skips tests/examples/benches). Same frozen-set contract as the
sibling ratchets: no new type, no duplicate definition, trim on delete/rename.
Predicate uses `starts_with` (not `contains`) so mid-word `Local` (`HookLocalId`)
is not flagged; a self-test pins that + the `LocalDev`/`Locale` exclusions.

Test-only, no production change. Verified: 2 tests pass (frozen allowlist +
predicate self-test); clippy -D warnings clean; fmt + pre-commit clean.

Stacked on #6220.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* test(reborn): deployment-mode ratchet matches contained words, not prefixes

Addresses all three review findings on #6222:

- IronLoop: §4.4's rule is "no public type name CONTAINS Local/Hosted/
  Enterprise" — the predicate now matches the terms at any CamelCase word
  boundary (followed by uppercase/digit/underscore/end), which surfaces
  and freezes 16 previously-invisible mode-shaped mid-names: the
  RebornLocal* composition family, the Reborn*LocalTriggerAccess*
  backends, mid-name LocalDev types, and HookLocalId (justified-keep:
  hook-local id is a domain concept, annotated as such).
- Gemini (both): localization names need no hand-listed exceptions under
  boundary matching — Locale*/Localization*/Localised* continue lowercase
  so the word is not "Local"; the self-test now pins those exclusions plus
  the mid-name positives (RebornLocalRuntimeServices, HookLocalId,
  SelfHostedMcpClient).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
ilblackdragon added a commit that referenced this pull request Jul 18, 2026
)

* refactor(reborn): rename LocalDevOutboundStores -> OutboundStores (§4.4)

Second §4.4 de-prefix slice (after C1's LocalDevRootFilesystem inline). Advances
the doc's §4.4 enforcement endgame — "no public type name contains
Local/LocalDev/Hosted/Enterprise" — one more type.

`LocalDevOutboundStores` is a plain bundle struct (four outbound-store handle
fields), NOT a cfg-switched policy/mode type. Its own constructor comment says it
"works in both durable (libsql/postgres) and no-durable (in-memory backend)
builds" — so the `LocalDev` prefix is factually wrong (it is used in libsql/
postgres PRODUCTION builds, not just local-dev). This is a bucket-2-style
mis-prefix: a genuine composition type that only LOOKS like a deployment-mode
leak, so the fix is a de-prefix rename, not the bucket-1 DeploymentConfig
resolution the cfg-switched `LocalDev*Store` aliases need.

Renamed the struct + its 3 use sites (all in factory.rs) to `OutboundStores`
(name was free); trimmed it from the R2 `reborn_localdev_typename` ratchet
allowlist. The `local_dev_outbound_store` builder fn keeps its name (fn names are
not type-name leaks; the ratchet inventories types only).

Pure type rename, semantically identical. Verified: localdev ratchet 4; `cargo
build -p ironclaw_reborn_composition` (default + libsql+slack+telegram) clean;
clippy -D warnings clean; fmt + pre-commit clean.

Stacked on #6218.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* test(reborn): add the Hosted*/Enterprise*/Local* deployment-mode-typename ratchet (§4.4/§10)

Completes the §4.4-mandated enforcement — "no public type name contains
Local/LocalDev/Hosted/Enterprise" (the doc says: "Enforce it with an
ironclaw_architecture test"). The existing `reborn_localdev_typename_ratchet`
owns `LocalDev*` (shrinking to empty as Slice B lands) and explicitly scopes out
"the broader Local*/Hosted* audit ... as a separate concern." This companion
ratchet owns that separate concern — the OTHER three prefixes:

- `Enterprise*` — NONE exist (achieved). Empty allowlist locks it in: a new
  `EnterpriseTierPolicy`-style mode leak fails the "no new" check.
- `Hosted*` — all `HostedMcp*`/discovery/egress, a Bucket-3 FALSE POSITIVE
  ("hosted MCP" is a real domain concept — a platform-hosted MCP server — not a
  hosted-TIER deployment mode). Frozen/justified so a genuine `HostedTierRuntime`
  leak can't slip in behind them.
- `Local*` (excluding `LocalDev*` → sibling ratchet, and `Locale*` → localization
  false positive) — the `LocalTriggerAccess*` family is genuine Bucket-1 debt
  (§4.4 folds `local_trigger_access` into "seed owner grant from config at boot,"
  a policy value); `LocalInvocationServicesResolver` awaits a design-call rename.

Reuses the shared `ratchet_support` scanner (comments/strings stripped,
visibility-aware, skips tests/examples/benches). Same frozen-set contract as the
sibling ratchets: no new type, no duplicate definition, trim on delete/rename.
Predicate uses `starts_with` (not `contains`) so mid-word `Local` (`HookLocalId`)
is not flagged; a self-test pins that + the `LocalDev`/`Locale` exclusions.

Test-only, no production change. Verified: 2 tests pass (frozen allowlist +
predicate self-test); clippy -D warnings clean; fmt + pre-commit clean.

Stacked on #6220.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* test(reborn): deployment-mode ratchet matches contained words, not prefixes

Addresses all three review findings on #6222:

- IronLoop: §4.4's rule is "no public type name CONTAINS Local/Hosted/
  Enterprise" — the predicate now matches the terms at any CamelCase word
  boundary (followed by uppercase/digit/underscore/end), which surfaces
  and freezes 16 previously-invisible mode-shaped mid-names: the
  RebornLocal* composition family, the Reborn*LocalTriggerAccess*
  backends, mid-name LocalDev types, and HookLocalId (justified-keep:
  hook-local id is a domain concept, annotated as such).
- Gemini (both): localization names need no hand-listed exceptions under
  boundary matching — Locale*/Localization*/Localised* continue lowercase
  so the word is not "Local"; the self-test now pins those exclusions plus
  the mid-name positives (RebornLocalRuntimeServices, HookLocalId,
  SelfHostedMcpClient).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* feat(host_api): introduce Slice-C Invocation payload vocabulary (#6168)

First sub-slice of Slice C (arch-simplification §3/§5) — the capability-path
DTO collapse. Per the migration plan (§9), the kernel vocabulary lands in
`ironclaw_host_api` *first*, ahead of any wiring; this PR adds the single
data-plane payload every layer will reference, replacing the request side of
the ~14-hop re-wrap (§1.1).

- ids.rs (via the crate's own `uuid_id!`/`string_id!` macros):
  - `ActivityId` — the invocation's idempotency identity (§11.3); what §1.1's
    dead-future `idempotency_key` becomes, unified rather than deleted.
  - `ProductKind` / `RoutineId` — validated string newtypes for the two non-loop
    origins (kept strings, not enums, while the product/routine sets evolve, §5.8).
- invocation.rs (new):
  - `InvocationOrigin { LoopRun(RunId) | Product(ProductKind) | Automation(RoutineId) }`
    — sealed-at-membrane origin (§5.2.1); snake_case wire-tagged; `.kind()`
    discriminant pinned to the tag for per-origin accounting views (§5.3.3).
  - `Invocation { activity_id, capability, input, scope, actor, origin, estimate }`
    — the "one payload" (§3/§4.1). Reuses existing host_api types; `actor` is
    required (sealed), and authorization *outputs* (`mounts`, `resource_reservation`)
    are deliberately absent — they move into the sealed `Authorized` in a later slice.

Additive only — nothing is wired into the dispatch path yet. The five old request
DTOs still exist and function; per §9 the type count rises before it falls
(~14 → ~18 → ~11) as the new vocabulary and old shapes coexist.
`check-type-duplicates.py` does not flag `Invocation` against
`CapabilityDispatchRequest` (it is a genuinely distinct state, not a mirror).

Tests are crate-tier because the types are not production-wired yet; integration
coverage is owed when a later slice threads `&Invocation` through the four
capability mediators (testing.md: crate-tier when the harness cannot reach the path).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* test(host_api): assert specific validation rejections in origin-id tests

Gemini note on #6223: pin the kind + reason of each expected rejection
instead of bare is_err(), so an infrastructure failure can't masquerade
as a validation pass.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

This branch was successfully deployed

No deployments
ironclaw-ci-preview / ironclaw-pr-6220 — bcc2a5c7 Deployed Jul 18, 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: dependencies Dependency updates size: XS < 10 changed lines (excluding docs)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant