RFC: NetScript Deploy Plugin Family — plugin-deploy core + per-cloud adapters, Deno-native first (#824)#891
RFC: NetScript Deploy Plugin Family — plugin-deploy core + per-cloud adapters, Deno-native first (#824)#891rickylabs wants to merge 20 commits into
Conversation
…worklog Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EWs7xBg7oNqCCkxipVM5HR
…+ synthesis Prior-run distillation, auth composition anatomy, deploy-layer inventory, doctrine constraints, board parity (#871-#887), live provider deploy surfaces; research.md synthesis with drift-candidate ledger. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EWs7xBg7oNqCCkxipVM5HR
…y graph, deploy-core DP-0 locks the carried-forward laws (owner conformance rule, leaf-port authority, capability manifest + build-time rejection, probes) and the three-tier Deno-native-first frame. DP-1 supplies the explicit package/import graph adversarial F5 demanded. DP-2 designs plugin-deploy-core as the DEPLOY-ARCHETYPE-7-CORE-SEED extraction with the 7-op port, emitter split, capability compiler, and binding-transport contract. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EWs7xBg7oNqCCkxipVM5HR
…t design, wrapping map DP-3: per-target adapter cards with wrap surfaces, capability sketches, probe gates, and the shared conformance suite. DP-4: plugins/deploy A5 shape, manifest triad, multi-target install model, three named host extensions (cli-command axis, doctor union, capability flag), CLI back-compat shim. DP-5: selective-wrapping decision map with the Nitro conditional re-entry path. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EWs7xBg7oNqCCkxipVM5HR
…on matrix, scaffold stories DP-6: item-by-item migration of the shipped deploy layer with debt-ledger effects and the user-facing compatibility contract. DP-7: per-layer contribution matrix and the leaf-backing selection mechanism that keeps provider-first scaffolds credible. DP-8: five walked scaffold stories (deno-native default, cloudflare, aws, container/paas, vercel) with cross-story acceptance gates. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EWs7xBg7oNqCCkxipVM5HR
…ge complete LD-1..LD-12 locked; owner forks OF-1..OF-8 numbered, none silently taken; wave train W1-W5 with 21-child draft board sketch; risk register, gate selection, debt effects, deferred scope, downstream attack list. Worklog carries the Design checkpoint and ends STAGE-COMPLETE: generator; context-pack primes the integration resume. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EWs7xBg7oNqCCkxipVM5HR
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EWs7xBg7oNqCCkxipVM5HR
… accepted Triage record + corpus revision r2: eight-op lifecycle with pure plan/emit+provenance; structural namespaced capability contracts with scoped per-variant verdicts; user-declared deployment cells (suggestedCells, never silent partition); empty duplicate-rejecting core registry (collision error is NEW; defaults externalized); two-phase config loader (unknown target errors, never stripped); refactor-then-extract W1; protocol-valid tooling installer manifest; mount-children CLI contributions + async bootstrap; doctor-checks as data; descriptor-based adapter composition with per-target permission profiles; legacy verbs as compat handlers until semver-major; board recut to 29 DPB-n children. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EWs7xBg7oNqCCkxipVM5HR
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EWs7xBg7oNqCCkxipVM5HR
…dings accepted doc-story-kimi.md (docs IA + 4 forecast pages + KF-1..KF-13) + triage + corpus r3: DP-6 default-target contradiction fixed; deploy-deno declares no emit (flagship showcases declared subsets; getting-started = plan -> up); baremetal unified as one target with windows|linux variants; declarations/settings/generated-descriptor homes pinned; --env invocation grammar; .deploy/<target>/artifact-manifest.json --prebuilt contract; op-level CLI grammar sketch; deploy cells apply + selector vocabulary; target remove semantics; capability preview catalog; verdict-surface precedence; stories re-headed on the locked target-add flow. Board stays 29 children (KF scope folded into DPB-16/17). Doc-story authored by Kimi K3 (moonshotai/kimi-k3 via OpenCode+OpenRouter). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EWs7xBg7oNqCCkxipVM5HR
rfc.md presents the ratified direction, laws, public API design, wave plan, 29-child placeholder board, migration/supersession map, and owner forks OF-1..OF-8 in the #822 RFC format. Drift D-6 records the owner's in-turn stop-line lift for the draft PR (board filing still withheld). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EWs7xBg7oNqCCkxipVM5HR
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EWs7xBg7oNqCCkxipVM5HR
|
[PHASE: REVIEW] [VERDICT: ADVISORY — one composition pass required before epic filing] Owner review pass (pre-filing), transcribed and structured. The RFC as proposed is clean and the architecture is sound — the family shape, the dependency laws, the capability model, and the board stand as ratified. This is not a rethink. Before the epic is dispatched, one focused pass is required on a single layer: the deployment-pipeline mechanics, examined against what Aspire's own deployment stack already ships for free. The questionFor every pipeline seam the RFC defines, answer COULD it compose with the Aspire deployment pipeline — and SHOULD it, instead of NetScript re-implementing the seam? Aspire is not a "target" like the others: it is the platform NetScript already generates the AppHost for, and it ships a documented deployment stack we must not duplicate:
Concretely re-examine at least: the The doctrine steerThe anticipated objection — "what about projects scaffolded without Aspire?" — is pre-answered: the more NetScript evolves, the more Aspire is a first-class citizen. Nothing prevents a non-Aspire project from adding Aspire later when it needs deployment automation; a graceful basic fallback for non-Aspire projects is a deferred concern, not a design driver. Do not shape the core pipeline around Aspire's absence. Radius — track it, it changes the enterprise calculus
This meets exactly the enterprise-grade CI/CD + unified-deployment ambition of this RFC — evaluate it as such (and consult the Radius docs at radapp.io alongside). Also #18696 itself is a worked example of a custom deployment integration to model against. Practical notes for the pass
Expected outputA composition-delta addendum to the corpus (keep-or-delegate decision per seam, with rationale), amendments to the affected DP docs/adapter cards where a seam collapses into Aspire, and a Radius tracking position — the family architecture itself stays as proposed. Epic dispatch happens after this pass lands. |
…p-or-delegate per seam Owner-directed pre-filing review: every pipeline seam examined against Aspire's shipped deployment stack (TS tab). Delegate on Aspire-managed targets: publish emission, deploy/ destroy, --list-steps dry-run, --environment selection + state cache, Parameters__ secrets convention. Keep: capability/topology verdict, artifact-manifest + up --prebuilt (aspire deploy does not consume published assets), status/logs/rollback, the TS env-overlay file (appsettings overlays are C#-only), workflow generation, the Deno OCI path (no upstream generic-executable publish helper; image builder C#-only). New: netscript-capability-check registered via the TS-available builder.pipeline.addStep. Radius (aspire#18696 merged, #18759 open) tracked as a future 'radius' target key on deploy-aspire (DPB-29). Family architecture, ports, and 29-child board unchanged. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EWs7xBg7oNqCCkxipVM5HR
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EWs7xBg7oNqCCkxipVM5HR
… + consistency sweep
…pted SG-1 prebuilt applier matrix (no row, no op); SG-2 no-save secret/state policy with fail-closed doctor; SG-3 pipeline step re-homed to DPB-17 with conditional registration; SG-4 single compiler entrypoint + CapabilityCheckInput snapshot with parity tests; SG-5 resolveDeploymentEnvironment normalization (alias registrations rejected); SG-6 aspire target-by-op table as the generated operations source; SG-7 honest compatibility enumeration (legacy via shim, canonical changes deliberate); SG-8 predicate-gated Radius variant with per-environment unverified recipe capabilities; SG-9 scoped plan purity + AspirePipelineInspectionError. Quick wins applied; family topology, ports, and the 29-child board unchanged. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EWs7xBg7oNqCCkxipVM5HR
|
[PHASE: PLAN] [VERDICT: ARCHITECTURE LOCKED — corpus r5] Final architecture after five hardening passes (Fable 5 generator → Sol xhigh round 1 16/16 → Kimi K3 doc-story 13/13 → owner Aspire-composition review → Sol xhigh round 2 9/9). Every finding across all passes was accepted and integrated; the family topology survived all of them unchanged. This comment is the at-a-glance lock; the corpus under The family (locked)The laws (locked)
Delivery (locked shape, milestones pending OF-6)W1 core extraction (6 sub-slices, e2e:cli per slice, F-DEPLOY-1/2 → Pending (the only open items)
Full trail: |
|
@openhands-agent model=openrouter/qwen/qwen3.7-max output=pr-comment use harness You are the formal PLAN-EVAL evaluator (separate session, open model) for the planning-only seed run SKILLRead in order, from the repository at this PR's head:
What to evaluateThe run dir
Context: this is a seed run (deliverable = a board, not code). The plan-gate items are mapped in Output contract
Report the raw result honestly; a plan-gate box that cannot be verified is a finding, not a silent pass. |
OpenHands Agent — CompletedOPENHANDS_VERDICT: PASS Model: OpenHands Run Summary — PLAN-EVAL for
|
…892, children #893-#921) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EWs7xBg7oNqCCkxipVM5HR
|
[PHASE: PLAN-EVAL→FILED] Board filed on PLAN-EVAL PASS — 2026-07-19 The formal PLAN-EVAL (OpenHands ·
Implementation can launch from the board + the design corpus without reverse-engineering this run. First pull: the four p0s — #893, #895, #897, #898. |
RFC — NetScript Deploy Plugin Family:
plugin-deploycore + per-cloud adapters, Deno-native firstplan-unified-runtime--seed(nitro-vs-own analysis, both adversarial rounds); live provider surfaces 2026-07-18 (Cloudflare/Vercel/AWS/Fly/Deno Deploy/thin PaaS/Nitro v3, primary sources); aspire.dev deployment docs (TypeScript tab) + microsoft/aspire#18696/#18759; shipped deploy layer inventory; auth-plugin composition anatomy; doctrine A7 +DEPLOY-ARCHETYPE-7-CORE-SEEDdebt; full corpus in.llm/runs/plan-deploy-plugin--seed/(this PR)Abstract
NetScript's deploy story is rebuilt as a plugin family — exactly the way auth composes:
One goal frame governs every target — "Deno native first, then Node compat where needed" — made operational as three declared tiers (Deno-native process / Web-standard isolate / Node-compat), and one credibility mechanism makes the cloud story honest: every target ships a capability manifest whose verdicts are compiled against the app's requirements at plan time — build-time rejection with an explanation, never a runtime surprise, never a silent downgrade. Provider-optimized scaffolds (Cloudflare-first seams, AWS suites, Vercel marketplace, the container PaaS tier) then make provider-first real without ever forking application code.
1. Motivation
The prior unified-runtime seed (#824) ended in an adversarial verdict that killed its own architecture: a Nitro-hosted "giant deploy package" was rejected as a god-object with a dependency-cycle risk, unproven provider-family claims, and a board whose canonical bodies could not survive the pivot. The owner ratified the redirect (2026-07-18): no giant package — use NetScript at what it is best at, composability. A deploy plugin with a core and provider adapters, modeled on the auth family, redefines the whole deploy story:
Doctrine had already reserved the seat: Archetype 7 models deploy as an A2 core + A6 router composite, its F-DEPLOY gates are seeded awaiting the packages, and the shipped CLI kernel already contains the target port, registry, and activation/secrets/rollback/health conventions as target-agnostic modules (
DEPLOY-ARCHETYPE-7-CORE-SEED). This family is an extraction and pluginization, not an invention.2. The ratified decision and its rationale
Decision. Deploy ships as the package family above, composed like auth: a provider-agnostic core owning ports + registry + conventions + the capability compiler; thin per-provider adapters wrapping each platform's first-class tooling; a thin plugin that wires, declares, contributes, and re-exports. Laws carried forward from the prior run's surviving ground:
KvStore,MessageQueue, saga/worker/trigger/stream ports) stay authoritative; provider primitives are capability-scoped backings — each a feasibility question, not a mapping exerciseunsupportedfails the plan with the note;partialwarns and must be acknowledged; sagas aresupported | externalized | rejectedper targetServiceShutdownCoordinatorlifecycleWrap map (selective wrapping): wrangler (invoked as a tool) + emitted
wrangler.jsonc; Vercel Build Output API v3 (.vercel/output→vercel deploy --prebuilt); the built-indeno deployCLI (Deno-native flagship); Fly Machines REST API + the four PaaS REST APIs over one owned OCI path; AWS Lambda Web Adapter (HTTP sidecar — scope-limited honestly) + optional Pulumi Automation API for IaC; Aspire-native for local/self-host/azure/k8s lanes (aspire publish|deploy|destroy|do— Aspire remains composer/executor, never the contract; delegation depth per seam in Addendum A). Rejected: Serverless Framework v4 (license-gated). Nitro: no dependency — presets are welded to Nitro's build and its Deno preset is Node-built; kept as a reference corpus with a named L-1-gated re-entry as an optional emitter package if a target ever proves cheaper that way.3. Public API design (with implementation detail)
3.1 The eight-operation target port (core)
The shipped kernel port moves to
plugin-deploy-coreand is sharpened —planis pure,emitmaterializes,up --prebuiltconsumes:emitwrites.deploy/<target>[@<env>]/withartifact-manifest.json(artifact digest, source revision, target variant, emitter version);up --prebuilt <path-to-manifest>digest-verifies before pushing. (r5, SG-1) On Aspire-managed variantsup --prebuiltexists only where a per-variant applier row is declared (compose →docker compose -f … up -d; kubernetes →kubectl apply -f …; azure rows absent until an Azure-native applier is proven) — no row, no op, no advertised CI split.DeployOperationUnsupportedError; the flagshipdeno-deploytarget deliberately declares noemit(the platform builds from source) — the declared-subset mechanism on display.netscript deploy <target> <op> --env <name>. (r5, SG-5)resolveDeploymentEnvironmentnormalizes once, before registry/overlay/artifact resolution — omitted Aspire env ⇒production; one value keys registry, overlay merge, artifact path, cache, events, and the--environmentpass-through; bare +@productionalias registrations rejected.ArtifactEmitterPort(formats:deno-binary,oci-image,wrangler-worker,vercel-build-output,aspire-publish);ContainerBuildPortis the core-owned OCI specialization thatdeploy-containerimplements and composition roots inject into the cloudflare/aws lanes (nodeploy-*package ever imports anotherdeploy-*package — an import-graph gate).3.2 Capability contracts — honest agnosticism, structurally
Core owns only these structures plus a small
runtime:*trait vocabulary; leaf packages contribute namespaced descriptors through them — core imports no leaf package, no provider SDK. Manifests are per target variant (Workers ≠ Containers; Lambda ≠ Fargate).losslessrequires a live-platform conformance cell; unproven/not-installed/credential-missing states areunverified-family diagnostics, never provider impossibility. Precedence when surfaces disagree: livedoctor>plan(recompiles from installed manifests) >capabilities(rendered data). (r5, SG-4)compileCapabilityVerdictis one pure entrypoint over a versionedCapabilityCheckInputsnapshot (graph digest, effective env, registry digest, manifest ids/versions/probe dates); every consumer — plan, scaffold selection, the Aspire pipeline step — invokes it, with parity tests asserting identical verdict JSON.3.3 Topology cells — never silently partitioned
Cells are user-declared in
deploy/targets.ts. When an app exceeds a variant's profile (sagas on an isolate, CAS on Workers KV),planrejects and writes machine-readablesuggested-cells.json;deploy cells applymaterializes it into the user-owned file with the diff shown. Every service/consumer/schedule has exactly one owning cell; cross-cell transport is explicit.3.4 The plugin, its manifest triad, and three host extensions
Three surfaces are named and homed: target declarations (
deploy/targets.ts, user-owned), target settings (netscript.config.ts→deploy.targets.<key>), and descriptors (generated registry module, regenerated bytarget add/remove):The plugin depends only on core and composes resolved descriptors — adapters are peer install choices (
deploy target add <key>), never static imports. New verbs:target add|remove,capabilities [<target>] [--json|--preview](a bundled published-manifest preview catalog serves check-then-decide before install),cells apply,doctor(states:unsupported | unverified | adapter-not-installed | credential-unavailable; reports per-target permission profiles and orphaned declarations). No resident HTTP service in v1; the plugin also contributes adeploy-eventsdurable stream (versioned audit envelope), telemetry spans with secret redaction, and a tinydeployruntime-config topic.Host (
@netscript/plugin+ CLI) gains three generic extensions: (1) CLI mount-children contributions ({mount, id, loader, export}) + async bootstrap — the built-indeployshell stays host-owned (reserved mount,desktop, help, install hint) and contributions can never shadow a top-level command; duplicate(mount,id)fails before parsing; (2) doctor checks as data ({id, loader}registry — replacing the hard-coded literal union); (3) an installer-protocolofficialSourcevariant{ sourceKind: 'tooling' }+capabilities.contributionAxes— no deploy-specific field enters the generic protocol.3.5 Config: two-phase loader
Adapter-owned target schemas require a real bootstrap contract: (1) bootstrap-parse project identity +
plugins+deploy.targetsunstripped → (2) resolve plugin/adapterschemaLoaders → (3) compose the target schema registry → (4) full parse. An unknown target key becomesDeployTargetAdapterMissingError— the one deliberate config behavior change (today unknown keys are silently stripped).@netscript/configkeeps the loader seam + a frozen delegating legacy union for the window. The bare-metal lane unifies as one targetbaremetalwithwindows | linuxvariants; legacy config keys map in unchanged.4. What ships when (plan)
deployshell split preservingdesktop; capability+topology contracts + compiler; two-phase config loader. F-DEPLOY-1/2 flipreviewed→gatede2e:cligreen after every sub-slicedeploy-aspire(target×op table as the generatedoperationssource, applier matrix, SG-2 secret/state policy,runCapabilityCheck),deploy-baremetal(build pipeline + legacy-verb compat handlers),deploy-denoextracted; adapter-side config members; compatibility gate (state-transition + help goldens + unknown-target paths)plugins/deploy(manifest triad, descriptor composition, doctor, verify-plugin) → plugin CLI children → scaffolder + Story-0scaffold.runtimeE2E + the conditional capability-check pipeline step → streams/telemetryplugin install deploy→target add deno-deploy→planon a generated workspacedeploy-container(OCI build/push + Dockerfile emission) + thin PaaS clients + container scaffold storydeploy-cloudflare(workers variant) + story; Vercel probe →deploy-vercel+ story; AWS-PROBE-HTTP →deploy-aws(lambda variant, HTTP scope) + storyMilestone proposal (owner fork OF-6): W1–W3 →
0.0.1-beta.13, W4–W5 → beta.14/stable; the epic supersedes #824 and re-scopes #823's deploy half. Legacy flat verbs (build/install/start/stop/copy/upgrade/package-cli/uninstall) stay first-class compat handlers with their exact shipped semantics through the next semver-major (their semantics are notup/down-equivalent); onlybuild → plan+emit,status,logsalias — pinned to thebaremetaltarget.5. Proposed board (placeholders — filed only after owner ratification)
One umbrella epic (
type:umbrella,epic:deploy-plugin) + 29 childrenDPB-1…DPB-29, in the enterprise-auth body template (Part of #EPIC→ scoping paragraph with anti-scope boundary →- [ ] gate:acceptance predicates →Dependencies:+Delivery shape:) with its defects fixed (single id scheme, every child milestoned, GitHub-native sub-issues). Summary of the DAG:runCapabilityCheck; Radius watch) · DPB-9 deno · DPB-10 config members · DPB-11 compatibility gatecells apply,target remove, preview catalog) · DPB-17 scaffolder + conditional capability-check pipeline step (deps DPB-5/8/15) · DPB-18 Story-0 E2E · DPB-19 streams/telemetryFull table with per-child dependencies:
plan.md§5 (this PR). Issue numbers are assigned at the supervisor-coordinated filing step — not by this PR.6. Migration and supersession map
Migration (behavior-preserving; full item map M-1…M-18 in
DP-6): the shipped 8-op port, registry, conventions, and compile pipeline are extractions frompackages/cli; config keys and every documented verb survive; Aspire legacy invocations keep today's exact semantics through the compat shim while the plugin-era canonical verbs change deliberately (pure plan,aspire destroyteardown, env normalization, no-save secret policy — Addendum A r5); scaffolded workflows keep functioning; desktop packaging stays outside this family (epic #830 boundary). Debt retired:DEPLOY-ARCHETYPE-7-CORE-SEED(conditional on the externalized composition root),DEPLOY-SECRETS-ROLLBACK-CORE,DEPLOY-BAREMETAL-PUBLIC-WIRING, the deploy slice ofconfig-plugin-specific-schema-debt, the container half ofcli-deploy-artifacts-missing(NetScript finally emits a Dockerfile — as adapter output),cli-deploy-linux-integration-untested(as a live-probe cell).Supersession proposals (owner arbitration at filing; no closes by this PR):
offlineworkload constraint names the seam); not deploy's to close7. Security & operational posture (summary)
Secrets are references end-to-end — values never in plans, artifact manifests, telemetry, stream events, argv, or errors (negatively tested; sentinel tests extend to Aspire's deployment state cache under the r5 no-save policy). Per-target least-privilege permission profiles, reported exactly by doctor; no aggregate all-provider permission claim. CI auth OIDC-first where platforms support it (AWS role-assume, Deno Deploy org tokens), token-based where not (Cloudflare — documented). Health-gated activation with retain/rollback conventions; audit stream whose sink can never fail a deploy.
8. Open forks for owner arbitration
@netscript/plugin-deploy-core(auth parity)@netscript/deploy-core(kickoff literal)deploy-container; graduate on SDK/auth/lifecycle divergencedeployshell; plugin contributes children (never shadows)epic:deploy-pluginsupersedes #824, re-scopes #823's deploy half; W1–W3 → beta.13, W4–W5 → beta.14/stabledeploy-nitroemitter in the first wavesOpen decisions deferred rework-safe: cloud-run re-home timing (W4);
init --deploy <provider>sugar (no story depends on it); deploy dashboard service; secrets rotation overlap-window card.Addendum A — Aspire pipeline composition (owner review pass, 2026-07-19; corpus r4 + r5 hardening)
Per the review comment below, every deployment-pipeline seam was re-examined against Aspire's shipped deployment stack (docs read on the TypeScript tab) — full analysis in
design/canonical/DP-9-aspire-composition.md. The family architecture is unchanged; the Aspire-lane realization deepens its delegation:Delegate (Aspire-managed targets):
emitmechanics →aspire publish --output-path;up/down→aspire deploy/aspire destroy;plan's pipeline-step section →aspire deploy --list-steps(built-in no-execution dry-run); environment selection →--environment(omitted env normalizes to Aspire'sproduction); per-env provisioning state → Aspire's deployment state cache;secretsinjection → theaddParameter({secret:true})+Parameters__*convention.Keep (Aspire lacks it, or it's C#-only today): the capability/topology verdict; the
artifact-manifest.json+up --prebuiltcontract (Aspire states verbatim that "aspire deploydoes not consume previously published assets" — our manifest formalizes the hand-off its CI example leaves to upload-artifact conventions); deploy-timestatus/logs/rollback; the environments overlay file (appsettings.{env}.jsonis C#-only — a documented TS gap we fill, not duplication); workflow generation (Aspire ships an example, not a generator — ours adopts its documentedaspire do push→aspire publish→ upload-artifact shape); and the Deno OCI path (IResourceContainerImageBuilderis C#-only and no generic-executable publish helper exists —deploy-containerfills a real gap, withaspire do build|pushnamed as the convergence backend).New integration point: the TS-available
builder.pipeline.addStep(...)lets the generated NetScript AppHost register anetscript-capability-checksteprequiredBy: ["deploy"]— the capability compiler then gates even a rawaspire deploy. Registration is conditional (deploy plugin present + ≥1 Aspire target descriptor; otherwise no import, no step) and ships with the scaffolder card DPB-17. Binding is CLI + application-level pipeline steps only: the callback-annotation surface is mid-migration upstream (13.0 pipeline system; Aspire's own pages currently disagree) and C#-only; resource-level needs would route via the #825 NuGet vehicle (not v1).Radius: microsoft/aspire#18696 (merged — Radius as a first-class compute environment:
publish→app.bicep,deploy→rad deploy, control-plane credentials) + microsoft/aspire#18759 (open — the full TypeScript AppHost projection) are tracked as a future descriptor-selectedradiusvariant ondeploy-aspire— not a new adapter package.Round-2 hardening (r5 — Sol adversarial SG-1…SG-9, all accepted;
adversarial-sol-r4.md+ triage):up --prebuiltnow carries a per-variant applier matrix (compose →docker compose -f … up -d; kubernetes →kubectl apply; azure rows absent until an Azure-native applier is proven — a variant without a row does not declare--prebuilt); the Aspire state cache falls under a no-save secret policy (secret-resolving operations run clear-cache mode; persistence only for a non-secret allow-list; doctor fails closed on a cache containing secret-mapped keys, with sentinel-absence tests); the capability compiler is one pure entrypoint over a versionedCapabilityCheckInputsnapshot with CLI/pipeline-step parity tests and a standardized failure contract (recovery command + diagnostics + stable exit code); environment identity is normalized once (resolveDeploymentEnvironment— alias registrations rejected); Radius graduation is predicate-gated (pinned CLI version,deno checkfixture,app.bicepemission, Radius step visible in--list-steps, recipe-derived binding fixture) with per-environment Recipe capabilitiesunverifieduntil probed; plan purity is scoped precisely (no workspace deploy artifacts, no provider mutation; isolated toolchain inspection permitted,AspirePipelineInspectionErroron failure); the Aspire card's target×op table is the generated source ofoperations, and the compatibility contract now states honestly which canonical behaviors change vs what the legacy shim preserves.Provenance. This PR lands the full planning record under
.llm/runs/plan-deploy-plugin--seed/: six-surface research corpus (research/), canonical design docsDP-0…DP-9(r5),plan.md(locked decisions LD-1…12, the 29-child board table, risk register, gates),rfc.md(this document incl. Addendum A), the Sol adversarial trail (rounds 1+2:adversarial-brief.md,adversarial-sol.md,adversarial-sol-triage.md— 16/16;adversarial-brief-r4.md,adversarial-sol-r4.md,adversarial-sol-r4-triage.md— 9/9), and the Kimi doc-story trail (kimi-doc-story-brief.md,doc-story-kimi.md— docs IA + four forecast pages,doc-story-kimi-triage.md— 13/13 accepted; where a forecast page predates a correction, the corpus is authority). Board numbers are placeholders — filing is a later supervisor-coordinated step. Refs #820 #327 #823 #824 #825 — no closing keywords.🤖 Generated with Claude Code
https://claude.ai/code/session_01EWs7xBg7oNqCCkxipVM5HR