Skip to content

feat(adlc): add Agent Declarative Lifecycle Configuration spec - #452

Merged
markturansky merged 8 commits into
mainfrom
feat/adlc-agent-runtime-spec
Oct 6, 2026
Merged

markturansky merged 8 commits into
mainfrom
feat/adlc-agent-runtime-spec

Conversation

@markturansky

Copy link
Copy Markdown
Collaborator

Introduces specs/adlc/agents.spec.md, which defines the data model and requirements for running autonomous AI agents as first-class HyperShell API resources.

New top-level kinds: AgentRuntime, SandboxTemplate, ProviderSpec, SecretSource. Workspace-scoped sub-resources: Workspace, WorkspaceMembership, ProviderBinding, InferenceRoute.

Key design decisions captured in the spec:

  • Gateway-agnostic capability model: no OpenShell CLI flags or driver names appear in the API; the controller translates them.
  • ProviderSpec and SandboxTemplate are reusable across AgentRuntimes.
  • SecretSource purpose enum drives env var wiring without operator annotation.
  • ManifestWork delivers scheduling resources to target clusters via OCM.
  • Bootstrap Job provisions gateway-side workspace, members, and providers idempotently.
  • AgentRuntime owns exactly one Workspace (isolation primitive).

Adds the ADLC section to specs/index.spec.md and registers adlc/agents.spec.md in the spec registry table.

@coderabbitai

coderabbitai Bot commented Oct 6, 2026 •

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration
  • Configuration used: Repository YAML (base), Central YAML (inherited)
  • Review profile: CHILL
  • Plan: Enterprise
  • Run ID: 9de22c25-44f0-4175-8c1a-07bcae58bcac

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

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

@hypershell-delivery

hypershell-delivery Bot commented Oct 6, 2026 •

Copy link
Copy Markdown

Amber review: changes requested

Amber review

Status: Complete

View the submitted review.

hypershell-delivery[bot]

This comment was marked as outdated.

@hypershell-delivery hypershell-delivery Bot added the amber/changes-requested Amber requested changes on this PR label Oct 6, 2026
hypershell-delivery[bot]

This comment was marked as outdated.

hypershell-delivery[bot]

This comment was marked as outdated.

@github-actions

github-actions Bot commented Oct 6, 2026 •

Copy link
Copy Markdown

HyperShell environment destroyed

This ephemeral OpenShift environment has been destroyed. Comment /pr-extend to redeploy it.

hypershell-delivery[bot]

This comment was marked as outdated.

@markturansky

Copy link
Copy Markdown
Collaborator Author

Status update - IBM ROKS e2e validation in progress

What's merged into this PR

The branch now contains all ADLC data model changes plus the e2e cleanup:

  • feat(data-model): Remove GatewayRelease + GatewayNetwork kinds, add 6 ADLC kinds (AgentRuntime, SandboxTemplate, ProviderSpec, ProviderBinding, InferenceRoute, SecretSource)
  • test(e2e): Remove E2E_RELEASE_ID and release_id from all gateway create payloads and lib_test.sh assertions

IBM ROKS e2e - blockers resolved during validation

Deployed the new API server + control plane to hysh-ibm-01 and worked through several sequential blockers:

Blocker Root cause Fix
Controller gRPC stream silently dead IBM ROKS TCP idle timeout killed the stream; controller seeded 0 gateways oc rollout restart deployment/hypershell-controller
CREATE ROLE DDL failed hypershell PG user lacked CREATEROLE ALTER ROLE hypershell CREATEROLE
CREATE DATABASE permission denied hypershell PG user lacked CREATEDB ALTER ROLE hypershell CREATEDB
Helm RBAC escalation: sandbox role pods: create/delete/patch Controller ClusterRole only had pods: get,list,watch Patched ClusterRole
Helm RBAC escalation: node.k8s.io/runtimeclasses + scheduling.k8s.io/priorityclasses ClusterRole missing these permissions needed to create the openshell node-reader ClusterRole Patched ClusterRole
Gateway pod CrashLoopBackOff: unknown field 'name' Chart template (from openshell v0.1.2 upstream bump) generates config fields that gateway binary v0.0.109 doesn't recognize Schema mismatch - being addressed separately

Remaining: chart/gateway image version mismatch

The openshell chart in this repo was bumped to v0.1.2 (PR #374) but the gateway images on the ROKS cluster are still at 0.0.109. The v0.1.2 chart generates a config structure ([openshell.drivers.kubernetes] subsection, singular compute_driver, name field) that is incompatible with the 0.0.109 binary schema.

This is a pre-existing infrastructure gap unrelated to the ADLC data model changes in this PR. The e2e gateway lifecycle test cannot pass until either:

  • The ROKS cluster gateway images are updated to v0.1.2-rhaiv.0 (what deploy/ibm/kustomization.yaml specifies), or
  • The ClusterRole live patches are persisted to the deploy manifests so they survive controller restarts

The ADLC API kinds (AgentRuntime, SandboxTemplate, etc.) and the GatewayRelease/GatewayNetwork removal are independently correct and do not affect this infrastructure issue.

hypershell-delivery[bot]

This comment was marked as outdated.

hypershell-delivery[bot]

This comment was marked as outdated.

user and others added 7 commits October 6, 2026 16:08
Introduces specs/adlc/agents.spec.md, which defines the data model and
requirements for running autonomous AI agents as first-class HyperShell
API resources.

New top-level kinds: AgentRuntime, SandboxTemplate, ProviderSpec,
SecretSource. Workspace-scoped sub-resources: Workspace,
WorkspaceMembership, ProviderBinding, InferenceRoute.

Key design decisions captured in the spec:
- Gateway-agnostic capability model: no OpenShell CLI flags or driver
  names appear in the API; the controller translates them.
- ProviderSpec and SandboxTemplate are reusable across AgentRuntimes.
- SecretSource purpose enum drives env var wiring without operator
  annotation.
- ManifestWork delivers scheduling resources to target clusters via OCM.
- Bootstrap Job provisions gateway-side workspace, members, and providers
  idempotently.
- AgentRuntime owns exactly one Workspace (isolation primitive).

Adds the ADLC section to specs/index.spec.md and registers
adlc/agents.spec.md in the spec registry table.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…emove adlc/

The ADLC spec introduced AgentRuntime, SandboxTemplate, ProviderSpec,
ProviderBinding, InferenceRoute, and SecretSource as a separate specs/adlc/
namespace. These are regular HyperShell API kinds reconciled by the existing
controller - no architectural separation is warranted.

Fold all kinds, ER entities, requirements, and design decisions into the
existing specs/platform/data-model.spec.md alongside Gateway, GatewayNetwork,
and ManagedCluster. Remove specs/adlc/ entirely.

Two architectural corrections applied vs. the original ADLC draft:
- No ManifestWork: the controller applies cluster resources directly,
  same as gateway infrastructure today.
- No bootstrap Job: the controller provisions gateway-side workspace,
  members, and provider bindings via the gateway gRPC API in its normal
  reconcile loop, same as database provisioning.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Mark both kinds as Slated for Removal in the data model spec:
- GatewayRelease: Gateway image/supervisor_image fields make the release
  indirection layer unnecessary; canary rollout was never adopted.
- GatewayNetwork: The reconciler owns no K8s resources and only validates
  topology fields; real mesh/tunnel provisioning was never defined.

Remove both from the ER diagram. Add deprecation banners to their
requirement sections. Mark API routes, CLI sections, and hsctl apply rows
as [REMOVED]. Add design decision rationale for both removals.

Add 20 RM- gap items to skills/RECONCILE.md covering all 8 implementation
layers (FE -> CLI -> CP -> BE+gRPC -> API+SDK -> DB) in reverse-dependency
removal order.

Extend skills/build/reconcile/SKILL.md with a Kind Removal Wave Pattern
and skills/build/full-stack-pipeline/SKILL.md with a reverse-dependency
execution note, so /reconcile can plan and execute kind deletion the same
way it plans additions.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…kinds

Remove GatewayRelease and GatewayNetwork across all implementation layers:
- FE: deleted gateway-release-distribution-aggregation adapter + tests;
  removed GatewayRelease metric from dashboard-control-plane adapter
- CLI: deleted 8 command dirs (create/get/list/delete for both kinds);
  removed URL constants, TUI kind enum entries, release selector from form
- CP: deleted GatewayReleaseReconciler, GatewayNetworkReconciler, WatchGatewayReleases,
  WatchGatewayNetworks; removed release_id propagation from GatewayReconciler;
  watchCount 4->2
- BE: deleted plugins/gatewayReleases and plugins/gatewayNetworks; removed
  release_id/observed_release_id from Gateway model, handler, service, presenters;
  removed GatewayReleaseService+GatewayNetworkService from grpc_authorization.go
- Proto: deleted gateway_releases.proto, gateway_networks.proto and generated stubs
- API: deleted openapi.gatewayReleases.yaml, openapi.gatewayNetworks.yaml;
  removed release_id from openapi.gateways.yaml; cleaned openapi.yaml references
- DB: added drop-table migrations for gateway_releases and gateway_networks tables;
  added drop-column migration for gateways.release_id/observed_release_id

Add 6 new ADLC API kinds (REST layer, no CP watcher/reconciler yet):
- AgentRuntime, SandboxTemplate, ProviderSpec, ProviderBinding,
  InferenceRoute, SecretSource
- OpenAPI specs, models, DAOs, handlers, services, presenters, migrations,
  plugin registrations for all 6 kinds
- Regenerated Go SDK (make generate)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
GatewayRelease and GatewayNetwork were removed from the data model in
6dcd9b8. This removes E2E_RELEASE_ID seeding, release_id from all
gateway create payloads, and the corresponding lib_test.sh unit test
assertions so the e2e suite runs cleanly against the new schema.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
… e2e

- gofmt fixes in reconciler.go, main.go, factory_test.go, inferenceRoutes/model.go
- Regenerate sdk-typescript/src: add AgentRuntime, SandboxTemplate, ProviderSpec,
  ProviderBinding, InferenceRoute, SecretSource; remove GatewayRelease, GatewayNetwork
- e2e area 13 (gateway release promotion): permanently skip since GatewayRelease
  and GatewayNetwork kinds were removed from the data model
- Remove E2E_RELEASE_ID forwarding from e2e-performance.sh

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…e area 13

Seed scripts (kind, openshift) still created GatewayRelease resources and
included release_id in gateway create bodies; these 400 with the new API
server. Remove the GatewayRelease block and release_id field from both.

Web console adapter still referenced gateway.release_id (ESLint
no-unsafe-assignment) and the gateway create payload still sent release_id.
Remove releaseId from GatewayRecord type, gateway-operations adapter, and all
test/story fixtures. Remove the gatewayReleaseId message and en.json entry.

e2e area 13 permanently skipped (GatewayRelease/GatewayNetwork removed).
e2e-performance.sh E2E_RELEASE_ID forwarding removed.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@markturansky
markturansky force-pushed the feat/adlc-agent-runtime-spec branch from b26552e to 30225a6 Compare October 6, 2026 20:08
hypershell-delivery[bot]

This comment was marked as outdated.

… tests

GatewayRelease was removed from the data model; remaining test assertions
checking for release_id / release-1 cause CI failures in shell unit tests,
frontend unit tests, and Playwright e2e.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

@hypershell-delivery hypershell-delivery 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.

Verdict

This PR removes GatewayRelease/GatewayNetwork and scaffolds six new ADLC API kinds (AgentRuntime, SandboxTemplate, ProviderSpec, ProviderBinding, InferenceRoute, SecretSource), but the removal stops at the Go model/DB layer and the new spec/code carry unresolved security and consistency gaps. I am requesting changes: the gRPC contract and control plane still carry the removed release fields, the spec still documents them as live while companion specs stay Active, the new REST resources list/get/delete across all tenants, and the coordinator pod spec omits a restricted SecurityContext. The latest commit only strips stale release_id test assertions, so every prior finding remains.

Findings

Major

1. GatewayRelease removal is incomplete across the gRPC contract and the control plane (components/api-server/proto/hypershell/v1/gateways.proto L29, L63, L97, L122; components/control-plane/internal/reconciler/reconciler.go L618, L640, L1106).
The model, REST surface, and DB migration drop release_id/observed_release_id, but the removal stops there. gateways.proto still declares release_id (field 5 on Gateway, field 4 on CreateGatewayRequest, field 5 on UpdateGatewayRequest) and observed_release_id (fields 25/22) - unlike fleet_id/database_id, which this same file retires with reserved, these numbers are left live, so the generated gateways.pb.go keeps them and the gRPC contract advertises fields the server now silently ignores. The control plane still carries the full observed-release machinery: advanceObservedRelease(... gw.GetObservedReleaseId(), gw.GetReleaseId()) on both provisioning paths (L618, L640), and advanceObservedRelease writes ObservedReleaseId back via UpdateGateway (L1106) - a write the handler now discards. gw.GetReleaseId() is always empty now, so this is dead code pointing at a deleted concept. Either finish the removal (reserve the proto fields, regenerate, delete the observed-release machinery) or keep the fields intentionally and document why. See existing thread r4198052241. Confidence: High.

2. Code removes release_id/GatewayRelease but data-model.spec.md still documents them as live, and the companion specs stay Active (specs/platform/data-model.spec.md L55, L218, L256, L272, L844).
The ER diagram still carries string release_id FK (L55) and string observed_release_id (L70); the create scenario still starts "GIVEN a valid cluster_id and release_id" (L218); the provisioning-fields prose still says release_id is optional and "when both are set, release_id takes precedence" (L256); and the client reference still lists Gateway release_id as implemented (L844). The spec contradicts the code shipped in the same PR. Separately, gateway-release-rollout.spec.md, gateway-release-reconciliation.spec.md, gateway-release-distribution.spec.md, and gateway-network-reconciliation.spec.md remain Status: Active and define these kinds as desired state, so /reconcile would re-generate exactly what this PR deletes; no RM- item deprecates them. See existing thread r4196462174. Confidence: High.

3. New ADLC REST resources list/get/delete all records with no tenancy scoping (components/api-server/plugins/agentRuntimes/handler.go L24-L74, and the sibling inferenceRoutes/providerSpecs/providerBindings/sandboxTemplates/secretSources handlers).
List calls generic.List with no per-subject/per-workspace filter; Get/Delete do existence-only checks. In isAuthorized/AuthorizeApi the new resource paths fall through to the final return hasGatewayCreator(bindings) (pkg/rbac/authorization.go L421) - no case was added for the new kinds - so any authenticated gateway-creator can list, read, and delete every AgentRuntime, ProviderBinding, SecretSource, etc. across all tenants. Contrast the gateways handler, which scopes List to the caller's RoleBindings per security.spec.md "Gateway Access Isolation", and the stated "AgentRuntime owns exactly one AgentWorkspace (isolation primitive)" goal. If intentional for the initial scaffold, call it out and track the scoping work; otherwise add binding-scoped filtering before these endpoints ship. See existing thread r4197331386. Confidence: Medium.

4. Coordinator CronJob pod omits the required restricted SecurityContext (specs/platform/data-model.spec.md L450-L465).
The "AgentRuntime Cluster Resource Provisioning" resource list mandates automountServiceAccountToken: false and a default-deny NetworkPolicy, but requires no restricted SecurityContext on the coordinator CronJob pod; a scan finds no runAsNonRoot/SecurityContext anywhere in the spec. CLAUDE.md and security.spec.md require runAsNonRoot: true, allowPrivilegeEscalation: false, and Capabilities.Drop: ["ALL"] on all pod specs. Add that requirement so the implementation inherits it. See existing thread r4195774763. Confidence: Medium.

5. Inference model not cross-referenced to openshell-inference-routing.spec.md (specs/platform/data-model.spec.md; specs/index.spec.md L31).
InferenceRoute/ProviderBinding are the declarative counterpart of the already-specified workspace inference route and credential-free sandbox model access in platform/openshell-inference-routing.spec.md, but that spec is still not referenced in the body and the registry Depends On for data-model.spec.md lists only managed-cluster-registration, openshell-gateway-service-accounts. Cross-reference it and declare the dependency so the two models do not drift. See existing thread r4195774747. Confidence: Medium.

Minor

6. WorkspaceMembership has no population path and no implementing component (specs/platform/data-model.spec.md L504-L515, L485).
L513-515 say "the API server creates or updates the WorkspaceMembership" and validates at least one admin membership (422 otherwise), while L485 says the controller provisions memberships via the gateway gRPC API. There is still no REST route, no apply kind, and no AgentRuntime field carrying member subjects/roles; the code adds plugins only for the six flat kinds (no workspaces/workspaceMemberships plugin), so the admin-membership validation has no owner. Specify where membership subject+role originate and which component owns create/update. See existing thread r4196236920. Confidence: Medium.

7. Pending definition reads as a slight mismatch with the create/reconcile scenario (specs/platform/data-model.spec.md L696, L462-465).
Pending is defined as "Created; reconciliation not yet started" (L696), while the reconcile scenario starts from a Pending AgentRuntime, runs the reconcile loop, and transitions to Provisioning (L462-465). Tighten the wording so the "not yet started" phrasing and the reconcile-from-Pending trigger clearly agree. Confidence: Low.

8. PR description is stale relative to the delivered change.
The body still describes a spec-only change introducing specs/adlc/agents.spec.md, OCM/ManifestWork delivery, and Workspace/WorkspaceMembership/ProviderBinding/InferenceRoute as sub-resources. The delivered change folds the model into data-model.spec.md, records "No ManifestWork" as the decision (L1043), removes two kinds across all layers, and adds six flat top-level kinds with full REST/SDK/CLI scaffolding. Update the description so reviewers and /reconcile see the actual scope. Confidence: High.

Cross-PR coordination

Three open pull requests take a direction that collides with this PR's removal of GatewayRelease/GatewayNetwork and need a maintainer decision plus a defined merge order:

  • #412 reworks the Gateway create contract to placement intent while keeping release_id a required create field: the GatewayCreateRequest required list becomes name, placement, release_id, and release_id/ReleaseId stay on the OpenAPI model, the generated model, and gateways.proto. This PR deletes release_id from the create contract and deletes both kinds, editing the same openapi.gateways.yaml, gateways.proto/gateways.pb.go, and model_gateway_create_request.go with opposite intent. Maintainers must decide whether the placement rework should also drop release_id, and sequence the two so the create contract does not end up requiring a field the other PR removes.
  • #445 adds Go and TypeScript SDK columns to the exact Gateway Networks and Gateway Releases client-reference rows this PR marks [REMOVED], documenting both kinds as a supported SDK surface in the same data-model.spec.md table. Opposite intent on the same rows; maintainers must decide whether those SDK bindings should be documented at all given the removal, and order the two edits to that table.
  • #185 specifies net-new periodic control-plane inventory polling and explicitly lists GatewayRelease and GatewayNetwork as kinds the world-sync cycle must poll ("Adding inventory polling for Fleet, ManagedCluster, GatewayRelease, and GatewayNetwork is net-new control-plane work"). That builds new reconciler work on the two kinds this PR deletes. Maintainers must decide whether the world-sync scope should drop those kinds and in which order the two land.

Previous concerns

  • Em dashes (r4195774738): Addressed. specs/adlc/ was removed; a U+2014 scan of the changed files returns no matches.
  • OCM/ManifestWork delivery divergence (r4195774755): Addressed. The controller applies cluster resources directly (data-model.spec.md L452) and the design-decision table records "No ManifestWork" (L1043).
  • GatewayRelease/GatewayNetwork deprecation inconsistent (r4196462174): Still present. See Finding 2 - data-model.spec.md still documents release_id as live (L55, L256, L844) and the companion specs remain Active.
  • Restricted SecurityContext on generated pods (r4195774763): Still present. See Finding 4 - no SecurityContext on the coordinator CronJob (L450-465).
  • Inference model duplicates openshell-inference-routing.spec.md (r4195774747): Still present. See Finding 5 - no body reference, dependency absent from index.spec.md L31.
  • WorkspaceMembership population path (r4196236920): Still present. See Finding 6 - no route/apply kind/field and no implementing plugin.
  • New ADLC REST resources lack tenancy scoping (r4197331386): Still present. See Finding 3 - unscoped generic.List and fall-through to hasGatewayCreator (authorization.go L421).
  • GatewayRelease removal incomplete below the model/DB layer (r4198052241): Still present. See Finding 1 - proto fields still live, control-plane observed-release machinery intact.

Findings Summary

  1. [Major] GatewayRelease removal incomplete: proto + control plane still carry release_id/observed_release_id after the model/DB removed them - Spec/Code Consistency (gateways.proto L29, reconciler.go L618, L1106)
  2. [Major] Code removes release_id/GatewayRelease but spec still documents them as live and companion specs stay Active - Spec Consistency (L55, L256, L844)
  3. [Major] New ADLC REST resources list/get/delete all records with no tenancy scoping - Security / Isolation (agentRuntimes/handler.go L24-74, authorization.go L421)
  4. [Major] Coordinator CronJob pod omits the required restricted SecurityContext - Security (L450-465)
  5. [Major] Inference model not cross-referenced to openshell-inference-routing.spec.md; dependency missing - Spec Consistency (data-model, index L31)
  6. [Minor] WorkspaceMembership has no population path and no implementing plugin - Spec Completeness (L504-515)
  7. [Minor] Pending definition wording mismatches the create/reconcile scenario - Spec Completeness (L696, L462-465)
  8. [Minor] PR description is stale relative to the delivered change - Process

Convention Checklist

Convention Result
No em dashes Pass
No panic() in new production code Pass
Secret references, not inline secrets (SecretSource stores backend/path refs) Pass
DB migrations reversible (drop column has rollback) Pass
Test diff scrutiny (stale release_id assertions removed, no flipped guarantees) Pass
Removed kind leaves no dangling references across all layers (proto, control plane) Fail
Restricted SecurityContext on all pod specs Fail
Tenancy/RBAC scoping consistent with the gateway handler Fail
Verify contracts and references before building on them (spec vs. code; inference xref) Fail
Reconcile / idempotent (update-or-create) pattern Pass

@markturansky
markturansky added this pull request to the merge queue Oct 6, 2026
Merged via the queue into main with commit 5aa67a6 Oct 6, 2026
36 checks passed
@markturansky
markturansky deleted the feat/adlc-agent-runtime-spec branch October 6, 2026 21:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

amber/changes-requested Amber requested changes on this PR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant