Skip to content

RFC: NetScript Deploy Plugin Family — plugin-deploy core + per-cloud adapters, Deno-native first (#824)#891

Draft
rickylabs wants to merge 20 commits into
mainfrom
plan/deploy-plugin
Draft

RFC: NetScript Deploy Plugin Family — plugin-deploy core + per-cloud adapters, Deno-native first (#824)#891
rickylabs wants to merge 20 commits into
mainfrom
plan/deploy-plugin

Conversation

@rickylabs

@rickylabs rickylabs commented Jul 19, 2026

Copy link
Copy Markdown
Owner

RFC — NetScript Deploy Plugin Family: plugin-deploy core + per-cloud adapters, Deno-native first

Status Adversarially hardened draft (r5) — direction ratified by owner 2026-07-18; Aspire-composition pass (Addendum A) + Sol round-2 verdicts (SG-1…SG-9, all accepted) integrated; package/API design pending owner arbitration of forks OF-1…OF-8 (§8); board not filed (numbers are placeholders)
Tracking Refs #820 (single-deployment charter) · #327 (Deployment epic) · #823 (Unified epic — re-scope proposal §6) · #824 (unified-runtime seed — superseded by this RFC, §6) · #825 (Aspire packaging NuGet — unaffected) · #871 (enterprise-auth board — the composition + board pattern this family mirrors)
Pipeline Fable 5 · xhigh generator → Sol · xhigh adversarial round 1 (16/16 accepted, r2) → Kimi K3 doc-story (13/13 accepted, r3) → owner Aspire-composition review (DP-9, r4) → Sol · xhigh adversarial round 2 (9/9 accepted, r5). Triage records in the run dir
Evidence base Prior seed run plan-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-SEED debt; 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:

plugins/deploy                     @netscript/plugin-deploy         (thin A5 plugin)
packages/plugin-deploy-core        @netscript/plugin-deploy-core    (A2 core: ports, registry,
                                                                    capabilities, conventions)
packages/deploy-aspire | deploy-baremetal | deploy-deno             (A2 adapters — extractions)
packages/deploy-container (+ fly/koyeb/sevalla/coolify/dokploy)     (A2 adapter — shared OCI path)
packages/deploy-cloudflare | deploy-vercel | deploy-aws             (A2 adapters — probe-gated)
netscript plugin install deploy
netscript deploy target add deno-deploy     # targets are explicit; several compose side by side
netscript deploy deno-deploy plan           # pure: capability verdict — no workspace deploy
                                            # artifacts written, no provider mutation
netscript deploy deno-deploy up             # ship

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:

  • the plugin contributes at every layer — CLI, scaffolding, streams/telemetry, doctor, and (when the frontend contribution axis lands) UI;
  • per-cloud adapters make provider-first scaffolding possible (a Cloudflare-optimized project ships Workers/DO/KV-first seams from day one, same for AWS suites, Vercel);
  • it "defeats" naive cloud-agnosticism while making the credible version real: strict NetScript-owned ports + honest per-target capability verdicts + explicit provider choices.

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:

# Law
L-1 Per target, a provider-native wrapper wins over any generic emitter iff it passes the same conformance suite, exposes every required native surface, and costs less to maintain. Nothing third-party enters the composition contract or leaf ports; whatever emits, emits behind a NetScript-owned port
L-2 Leaf ports (KvStore, MessageQueue, saga/worker/trigger/stream ports) stay authoritative; provider primitives are capability-scoped backings — each a feasibility question, not a mapping exercise
L-3 Capability manifest + build-time rejection: unsupported fails the plan with the note; partial warns and must be acknowledged; sagas are supported | externalized | rejected per target
L-4 One logical composition root; no application-created loopback; app code never forks per provider
L-5 Artifacts drive services through the shipped ServiceShutdownCoordinator lifecycle
L-6 The Docker-image long tail (Fly, Koyeb, Sevalla, Coolify, Dokploy, CF Containers) is one shared container path with thin platform clients
L-7 Probe before ownership claims: Cloudflare Workers, Vercel, and AWS adapters are gated on live conformance probes; AWS claims HTTP scope only until event-semantics probes pass

Wrap map (selective wrapping): wrangler (invoked as a tool) + emitted wrangler.jsonc; Vercel Build Output API v3 (.vercel/outputvercel deploy --prebuilt); the built-in deno deploy CLI (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-core and is sharpened — plan is pure, emit materializes, up --prebuilt consumes:

type DeployOperation =
  | 'plan' | 'emit' | 'up' | 'down' | 'status' | 'logs' | 'rollback' | 'secrets';

interface DeployTargetPort {
  readonly key: DeployTargetKey;
  readonly operations: readonly DeployOperation[];   // declared subset — never advertise more
  readonly capabilities: DeployCapabilityManifest;   // backend-truthful (§3.2)
  plan(ctx): Promise<DeployPlanResult>;              // pure (r5): no workspace deploy artifacts,
                                                     // no provider mutation; embeds its
                                                     // CapabilityCheckInput snapshot
  emit(ctx): Promise<EmittedArtifactManifest>;       // content-addressed artifacts + provenance
  up(ctx): Promise<DeployUpResult>;                  // plain up = plan → emit → up;
                                                     // up --prebuilt <manifest> consumes a build
  down(ctx): Promise<DeployDownResult>;
  status(ctx): Promise<DeployStatusResult>;
  logs(ctx): Promise<DeployLogsResult>;
  rollback(ctx): Promise<DeployRollbackResult>;      // platform-native or convention-backed
  secrets(ctx): Promise<DeploySecretsResult>;        // references + rotation; values never serialized
}
  • CI hand-off contract: emit writes .deploy/<target>[@<env>]/ with artifact-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 variants up --prebuilt exists 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.
  • Unsupported ops throw DeployOperationUnsupportedError; the flagship deno-deploy target deliberately declares no emit (the platform builds from source) — the declared-subset mechanism on display.
  • Environment grammar: netscript deploy <target> <op> --env <name>. (r5, SG-5) resolveDeploymentEnvironment normalizes once, before registry/overlay/artifact resolution — omitted Aspire env ⇒ production; one value keys registry, overlay merge, artifact path, cache, events, and the --environment pass-through; bare + @production alias registrations rejected.
  • Emission is a separate ArtifactEmitterPort (formats: deno-binary, oci-image, wrangler-worker, vercel-build-output, aspire-publish); ContainerBuildPort is the core-owned OCI specialization that deploy-container implements and composition roots inject into the cloudflare/aws lanes (no deploy-* package ever imports another deploy-* package — an import-graph gate).

3.2 Capability contracts — honest agnosticism, structurally

interface CapabilityRef { namespace: string; name: string; major: number }  // 'runtime' | '@netscript/kv' | …
interface BindingRequirement { binding: string; capability: CapabilityRef }
interface WorkloadConstraint { kind: 'singleton' | 'long-running' | 'co-locate' | 'offline' }

interface CapabilityVerdict {
  level: 'lossless' | 'partial' | 'unsupported' | 'unverified';
  scope: 'runtime' | 'adapter' | 'binding';
  evidence?: string;   // conformance-suite cell / probe id — a lossless row without one is a bug
  note?: string;       // the honest caveat, rendered by the CLI
}

interface DeployCapabilityManifest {
  schemaVersion: number;
  target: DeployTargetKey;
  variant: string;                       // 'workers' | 'containers' | 'lambda' | 'fargate' | …
  tier: 'deno-native' | 'web-standard' | 'node-compat';
  process: 'long-lived' | 'bounded-window' | 'isolate';
  verdicts: ReadonlyMap<CapabilityRefKey, CapabilityVerdict>;
  sagas: 'supported' | 'externalized' | 'rejected';
  toolVersions?: Record<string, string>; probedAt?: string;
}

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). lossless requires a live-platform conformance cell; unproven/not-installed/credential-missing states are unverified-family diagnostics, never provider impossibility. Precedence when surfaces disagree: live doctor > plan (recompiles from installed manifests) > capabilities (rendered data). (r5, SG-4) compileCapabilityVerdict is one pure entrypoint over a versioned CapabilityCheckInput snapshot (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

interface DeploymentCell {
  id: string; selectors: readonly string[];          // 'service:<name>' | 'app:<name>' | 'background:<kind>'
  target: DeployTargetKey; variant: string; bindings: readonly string[];
}
interface DeploymentTopologyPlan { cells: DeploymentCell[]; transports: CrossCellTransport[] }

Cells are user-declared in deploy/targets.ts. When an app exceeds a variant's profile (sagas on an isolate, CAS on Workers KV), plan rejects and writes machine-readable suggested-cells.json; deploy cells apply materializes 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.tsdeploy.targets.<key>), and descriptors (generated registry module, regenerated by target add/remove):

interface DeployTargetContribution {
  key: string;
  targetLoader: SafePackageExport;   // e.g. { pkg: '@netscript/deploy-deno', export: './target' }
  schemaLoader: SafePackageExport;   // the target's config member schema
  permissions: DeployPermissionProfile;  // exact per-target tool/net/fs profile
}

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 a deploy-events durable stream (versioned audit envelope), telemetry spans with secret redaction, and a tiny deploy runtime-config topic.

Host (@netscript/plugin + CLI) gains three generic extensions: (1) CLI mount-children contributions ({mount, id, loader, export}) + async bootstrap — the built-in deploy shell 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-protocol officialSource variant { 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.targets unstripped → (2) resolve plugin/adapter schemaLoaders → (3) compose the target schema registry → (4) full parse. An unknown target key becomes DeployTargetAdapterMissingError — the one deliberate config behavior change (today unknown keys are silently stripped). @netscript/config keeps the loader seam + a frozen delegating legacy union for the window. The bare-metal lane unifies as one target baremetal with windows | linux variants; legacy config keys map in unchanged.

4. What ships when (plan)

Wave Content Exit proof
W1 Core extraction as ordered refactor-then-extract sub-slices: contracts behind compat re-exports; pure conventions with constants; empty duplicate-rejecting registry (defaults externalized to the CLI composition root); host-owned deploy shell split preserving desktop; capability+topology contracts + compiler; two-phase config loader. F-DEPLOY-1/2 flip reviewed→gated e2e:cli green after every sub-slice
W2 deploy-aspire (target×op table as the generated operations source, applier matrix, SG-2 secret/state policy, runCapabilityCheck), deploy-baremetal (build pipeline + legacy-verb compat handlers), deploy-deno extracted; adapter-side config members; compatibility gate (state-transition + help goldens + unknown-target paths) per-package A2 gates; manifests published
W3 Host extensions (3 slices) → plugins/deploy (manifest triad, descriptor composition, doctor, verify-plugin) → plugin CLI children → scaffolder + Story-0 scaffold.runtime E2E + the conditional capability-check pipeline step → streams/telemetry plugin install deploytarget add deno-deployplan on a generated workspace
W4 deploy-container (OCI build/push + Dockerfile emission) + thin PaaS clients + container scaffold story live smoke ≥1 managed + ≥1 self-hosted platform
W5 Probe-gated clouds: CF-PROBE → deploy-cloudflare (workers variant) + story; Vercel probe → deploy-vercel + story; AWS-PROBE-HTTP → deploy-aws (lambda variant, HTTP scope) + story each adapter ships only behind its passing probe (L-7)

Milestone 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 not up/down-equivalent); only build → plan+emit, status, logs alias — pinned to the baremetal target.

5. Proposed board (placeholders — filed only after owner ratification)

One umbrella epic (type:umbrella, epic:deploy-plugin) + 29 children DPB-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:

  • W1 (6): DPB-1 contracts move (p0; incl. the stale "7-op" comment fix) · DPB-2 conventions · DPB-3 empty registry + compat composition root (p0) · DPB-4 shell split + router rewire · DPB-5 capability+topology contracts + compiler + conformance harness (p0) · DPB-6 two-phase config loader (p0)
  • W2 (5): DPB-7 baremetal · DPB-8 aspire (r5: target×op table, applier matrix, SG-2 secret/state policy, runCapabilityCheck; Radius watch) · DPB-9 deno · DPB-10 config members · DPB-11 compatibility gate
  • Host (3): DPB-12 mount-children contract · DPB-13 async bootstrap + collisions · DPB-14 doctor-as-data + tooling protocol variant
  • W3 (5): DPB-15 plugin · DPB-16 CLI children (grammar, cells 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/telemetry
  • W4 (3): DPB-20 OCI core · DPB-21 PaaS client tranche · DPB-22 container story
  • W5 (5): DPB-23 CF-PROBE · DPB-24 deploy-cloudflare + Story 1 · DPB-25 Vercel probe + adapter + Story 4 · DPB-26 AWS-PROBE-HTTP · DPB-27 deploy-aws + Story 2
  • Rolling/backlog (2): DPB-28 docs (target-matrix reference + per-target how-tos replace the alpha-minimal page) · DPB-29 deferred RFC: AWS event semantics + leaf backing catalog graduation + Radius target graduation (predicate-gated, Addendum A) (p2)

Full 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 from packages/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 destroy teardown, 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 of config-plugin-specific-schema-debt, the container half of cli-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):

Issue Proposal
#824 unified-runtime seed Superseded by this RFC — close at filing with a successor pointer to the deploy-plugin epic
#823 Unified epic Re-scope: its deploy half is owned by this family; its single-runtime product framing is re-stated against the plugin architecture (owner decision at filing)
#451 SDK transport surface Orthogonal to deploy — KEEP; re-homing decision stays with #823's re-scope
#453 desktop realization KEEP — consumed by epic #830 (desktop graph), not this family
#454 single-process realization Deploy aspect absorbed by the topology/cell + capability model (§3.3); close-or-fold proposal at filing with pointer
#455 offline-sync KEEP — leaf/database capability (offline workload constraint names the seam); not deploy's to close
#327 Deployment epic Body updated at filing to point at the new family as its architecture

7. 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

Fork Question Recommendation Alternative
OF-1 Core package name @netscript/plugin-deploy-core (auth parity) @netscript/deploy-core (kickoff literal)
OF-2 Thin PaaS packaging Subpaths of deploy-container; graduate on SDK/auth/lifecycle divergence One package per platform now
OF-3 CLI delivery Host-owned reserved deploy shell; plugin contributes children (never shadows) Fully plugin-owned group with a shadowing exception (rejected: makes a generic host facility plugin-aware)
OF-4 v1 service surface None — CLI + manifest is the machine surface; service seam deferred rework-safe Ship a deploy HTTP service + contracts/v1 now
OF-5 Legacy verbs First-class compat handlers until next semver-major; only build/status/logs alias Two-minor-release alias-and-remove (rejected by SF-9)
OF-6 Board/milestone relation New epic:deploy-plugin supersedes #824, re-scopes #823's deploy half; W1–W3 → beta.13, W4–W5 → beta.14/stable Fold under #823 as-is; or single milestone
OF-7 Nitro No dependency; reference corpus + L-1-gated re-entry as optional emitter Commission a deploy-nitro emitter in the first waves
OF-8 AWS first-wave scope HTTP-only until AWS-PROBE-EVENTS passes Commit the full event surface in W5

Open 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): emit mechanics → aspire publish --output-path; up/downaspire 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's production); per-env provisioning state → Aspire's deployment state cache; secrets injection → the addParameter({secret:true}) + Parameters__* convention.

Keep (Aspire lacks it, or it's C#-only today): the capability/topology verdict; the artifact-manifest.json + up --prebuilt contract (Aspire states verbatim that "aspire deploy does not consume previously published assets" — our manifest formalizes the hand-off its CI example leaves to upload-artifact conventions); deploy-time status/logs/rollback; the environments overlay file (appsettings.{env}.json is C#-only — a documented TS gap we fill, not duplication); workflow generation (Aspire ships an example, not a generator — ours adopts its documented aspire do pushaspire publish → upload-artifact shape); and the Deno OCI path (IResourceContainerImageBuilder is C#-only and no generic-executable publish helper exists — deploy-container fills a real gap, with aspire do build|push named as the convergence backend).

New integration point: the TS-available builder.pipeline.addStep(...) lets the generated NetScript AppHost register a netscript-capability-check step requiredBy: ["deploy"] — the capability compiler then gates even a raw aspire 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: publishapp.bicep, deployrad deploy, control-plane credentials) + microsoft/aspire#18759 (open — the full TypeScript AppHost projection) are tracked as a future descriptor-selected radius variant on deploy-aspire — not a new adapter package.

Round-2 hardening (r5 — Sol adversarial SG-1…SG-9, all accepted; adversarial-sol-r4.md + triage): up --prebuilt now 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 versioned CapabilityCheckInput snapshot 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 check fixture, app.bicep emission, Radius step visible in --list-steps, recipe-derived binding fixture) with per-environment Recipe capabilities unverified until probed; plan purity is scoped precisely (no workspace deploy artifacts, no provider mutation; isolated toolchain inspection permitted, AspirePipelineInspectionError on failure); the Aspire card's target×op table is the generated source of operations, 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 docs DP-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

rickylabs and others added 12 commits July 18, 2026 23:02
…+ 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
… 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
…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
@rickylabs rickylabs added this to the Backlog / Triage milestone Jul 19, 2026
@rickylabs rickylabs added type:docs ci:skip-e2e area:plugins plugins/* and plugin-core packages status:plan Harness plan phase priority:p1 High rfc Request for Comments - substantial/breaking design change area:deploy Deployment: CLI/Aspire deploy, targets, bare-metal ci:skip-scaffold Skip the scaffold-static (deno-only) scaffold gate labels Jul 19, 2026
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EWs7xBg7oNqCCkxipVM5HR
@rickylabs

Copy link
Copy Markdown
Owner Author

[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 question

For 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:

  • Pipeline modelPublishingCallbackAnnotation / DeployingCallbackAnnotation, PublishingContext / DeployingContext, IPipelineActivityReporter (hierarchical steps/tasks), custom deployment pipelines (aspire.dev/deployment/custom-deployments/?aspire-lang=typescript)
  • Manifest generationaspire publish artifact emission per compute environment
  • Environments — Aspire's own environments model (vs the RFC's --env / environments overlay)
  • Deployment state caching — vs the RFC's .deploy/<target>/artifact-manifest.json hand-off
  • Container image buildingIResourceContainerImageBuilder (vs deploy-container's OCI build path)
  • CI/CD — Aspire's documented app-lifecycle workflow (vs our scaffolded per-target GitHub workflows)
  • Compute environmentsAddKubernetesEnvironment / AddDockerComposeEnvironment / AddAzureContainerAppEnvironment and now AddRadiusEnvironment — the question of whether some "adapters" are better expressed as Aspire compute environments reached through the deploy-aspire lane

Concretely re-examine at least: the plan/emit artifact story vs aspire publish + deployment state caching; ArtifactEmitterPort formats that overlap aspire publish outputs; the environments overlay vs Aspire environments; the scaffolded CI workflows vs Aspire's CI/CD lifecycle guidance; deploy-container's image build vs IResourceContainerImageBuilder; and where the eight-op lifecycle should delegate rather than own when an Aspire compute environment is present.

The doctrine steer

The 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

  • Always read aspire.dev with ?aspire-lang=typescript — the default tab is .NET.
  • Be honest about the current constraint: callback-based custom-deployment extensibility is C#-only in the TS AppHost SDK today; ATS projection (the #18759 mechanism) is the path by which it reaches TypeScript. Factor that into COULD-vs-SHOULD and into timing.

Expected output

A 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.

rickylabs and others added 4 commits July 19, 2026 09:54
…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
…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
@rickylabs

Copy link
Copy Markdown
Owner Author

[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 .llm/runs/plan-deploy-plugin--seed/ (this PR's diff) is the normative record.

The family (locked)

plugins/deploy                    @netscript/plugin-deploy        A5 thin plugin — wires, declares,
                                                                  contributes, re-exports; depends on core ONLY
packages/plugin-deploy-core       @netscript/plugin-deploy-core   A2 core — eight-op DeployTargetPort,
                                                                  ArtifactEmitterPort + ContainerBuildPort,
                                                                  empty duplicate-rejecting registry,
                                                                  capability + topology contracts + compiler,
                                                                  pure conventions, two-phase config loader
packages/deploy-aspire            compose/docker/k8s/azure-* (+ future radius variant, predicate-gated)
packages/deploy-baremetal         windows|linux variants; owns the build pipeline + legacy-verb compat handlers
packages/deploy-deno              Deno Deploy flagship (declares NO emit — platform builds from source)
packages/deploy-container         shared OCI path + fly/koyeb/sevalla/coolify/dokploy subpath clients
packages/deploy-cloudflare|vercel|aws     probe-gated (CF-PROBE / Build-Output probe / AWS-PROBE-HTTP)

The laws (locked)

  1. Dependency graph — core imports no leaf package (structural CapabilityRef contracts only); no deploy-* imports another deploy-* (ContainerBuildPort by injection); the plugin composes descriptors (target add writes them to the generated registry); leaf provider backings live with the leaves. Deploy owns placement, artifacts, lifecycle; leaves own semantics.
  2. Eight-op lifecycleplan (pure: no workspace deploy artifacts, no provider mutation; embeds its CapabilityCheckInput snapshot) · emit (content-addressed artifacts + provenance → .deploy/<target>[@<env>]/artifact-manifest.json) · up / up --prebuilt (digest-verified; exists only where a per-variant applier row is declared) · down · status · logs · rollback · secrets — declared subsets, never advertised beyond them.
  3. Honest capabilities — per target-variant manifests; verdicts carry scope (runtime/adapter/binding) + level incl. unverifiedunsupported; lossless requires live-platform evidence; one pure compiler entrypoint with CLI ↔ pipeline-step parity; build-time rejection, never silent downgrade; sagas supported | externalized | rejected.
  4. Topology — cells are user-declared in deploy/targets.ts; the compiler emits suggested-cells.json + deploy cells apply, never partitions silently; one owning cell per service/consumer/schedule.
  5. Environment identityresolveDeploymentEnvironment normalizes once (omitted Aspire env ⇒ production; alias registrations rejected); one value keys registry, overlay merge, artifact path, cache, events, --environment pass-through.
  6. Host extensions (generic, data-driven) — CLI mount-children + async bootstrap (host-owned reserved deploy shell; no shadowing); doctor-checks as {id, loader} data; installer-protocol sourceKind:'tooling' + contributionAxes.
  7. Aspire composition — delegate what Aspire ships (publish emission, deploy/destroy, --list-steps dry-run, --environment, state cache under the no-save secret policy, Parameters__* injection); keep what it lacks or ships C#-only (the manifest/--prebuilt contract, status/logs/rollback, the TS env-overlay file, workflow generation, the Deno OCI path); one TS integration point — the conditional netscript-capability-check pipeline step. Radius = future descriptor-selected variant, predicate-gated.
  8. Selective wrapping — wrangler / Build Output API / deno deploy / Machines + PaaS REST / Lambda Web Adapter (+ optional Pulumi Automation API); Serverless v4 rejected (license); Nitro: no dependency — reference corpus with an L-1-gated re-entry only.
  9. Migration — behavior-preserving extraction; config keys + every documented verb survive; legacy flat verbs = compat handlers until next semver-major; the one deliberate change: unknown target keys error instead of silently stripping. Desktop packaging stays with epic epic: Desktop Singleton-Graph Deployment — install/update/supervise one artifact #830.

Delivery (locked shape, milestones pending OF-6)

W1 core extraction (6 sub-slices, e2e:cli per slice, F-DEPLOY-1/2 → gated) → W2 adapter extraction + compatibility gate → W3 host extensions + pluginization + Story-0 E2E → W4 container path → W5 probe-gated clouds. Board: 1 epic + 29 DPB-n children, enterprise-auth template with its defects fixed.

Pending (the only open items)

Full trail: rfc.md (r5, = this PR body) · plan.md · DP-0…DP-9 · adversarial rounds 1+2 with triages · Kimi doc-story + triage.

@rickylabs

Copy link
Copy Markdown
Owner Author

@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 plan-deploy-plugin--seed on branch plan/deploy-plugin (this PR, #891). You evaluate the plan; you do not implement anything.

SKILL

Read in order, from the repository at this PR's head:

  1. .agents/skills/netscript-harness/SKILL.md (evaluator separation, run artifacts)
  2. .llm/harness/evaluator/plan-protocol.md (your protocol)
  3. .llm/harness/gates/plan-gate.md (the checklist you enforce)

What to evaluate

The run dir .llm/runs/plan-deploy-plugin--seed/ at corpus revision r5:

  • research.md + research/ (six cited corpus files)
  • plan.md (locked decisions LD-1…12, owner forks OF-1…8, 29-child DPB-n board with dependencies, risk register, gates)
  • rfc.md (= this PR's body; the consolidated RFC incl. Addendum A)
  • design/canonical/DP-0…DP-9 (the canonical design corpus)
  • The hardening trail: adversarial-sol.md + triage (16/16 accepted, r2), doc-story-kimi.md + triage (13/13 accepted, r3), DP-9-aspire-composition.md (r4), adversarial-sol-r4.md + triage (9/9 accepted, r5)
  • drift.md (D-1…D-8 — note D-2: this run's kickoff replaced the default stage pipeline with an owner-defined one; your pass is the formal PLAN-EVAL of record)

Context: this is a seed run (deliverable = a board, not code). The plan-gate items are mapped in plan.md §1–§9. Spot-verify load-bearing repo claims first-hand (e.g. the shipped deploy port at packages/cli/src/kernel/domain/deploy/deploy-target-port.ts, the auth plugin composition under plugins/auth, the config deploy schema) rather than trusting the corpus's citations blindly.

Output contract

  1. Post the machine-readable verdict line EARLY in your PR comment: OPENHANDS_VERDICT: PASS or OPENHANDS_VERDICT: FAIL_PLAN.
  2. Then the formal comment: **[PHASE: PLAN-EVAL] [VERDICT: PASS|FAIL_PLAN]** with your plan-gate checklist results (item by item) and any findings (severity-tagged, with evidence).
  3. If your environment allows, also write .llm/runs/plan-deploy-plugin--seed/plan-eval.md with the same content and commit+push it to plan/deploy-plugin (explicit refspec git push origin HEAD:plan/deploy-plugin) — if the push fails, the PR comment remains the verdict of record; do not retry endlessly.
  4. Do not modify any other file, do not touch labels/milestones/issues, do not merge anything.

Report the raw result honestly; a plan-gate box that cannot be verified is a finding, not a silent pass.

@rickylabs

rickylabs commented Jul 19, 2026

Copy link
Copy Markdown
Owner Author

OpenHands Agent — Completed

OPENHANDS_VERDICT: PASS

Model: openrouter/qwen/qwen3.7-max
Provider: OPENROUTER
Job status: success
Verdict source: summary-file
Verdict comment: #891 (comment)
Summary source: agent-after-retry
Housekeeping: ack=success trace=success commit-artifacts=success replies=skipped draft-pr=skipped
Trace: .llm/tmp/run/openhands/pr-891/run-29681236970-1 (in the Actions artifact)
Artifact: openhands-agent-29681236970-1

OpenHands Run Summary — PLAN-EVAL for plan-deploy-plugin--seed

Summary

Ran the formal PLAN-EVAL against the r5 corpus of the deploy-plugin seed run. Verdict: PASS.

All 8 plan-gate boxes satisfied:

  1. Research present and current
  2. Decisions locked (LD-1…LD-12)
  3. Open-decision sweep (OF-1…OF-8 + 4 "safe to defer"; evaluator re-sweep found none)
  4. Commit slices (29 DPB-n cards, under the 30 cap, DAG-ordered — seed-run interpretation: proving-gate + files-touched metadata lives in the filed issue bodies at stage-H board filing)
  5. Risk register (10 items × severity × mitigation)
  6. Gate set selected (A5 plugin + A2 core/adapters + A7 union + F-DEPLOY-1/2 + scan/lint/fmt/doc/publish/scaffold/conformance/scaffold.runtime)
  7. Deferred scope explicit (8 items with ownership/epic pointers)
  8. jsr-audit surface scan (no slow-type exception, export budgets ≤20/subpath, string-constant templates)

Spot-verified four load-bearing repo claims first-hand against the tree (rather than trusting corpus citations):

  • packages/cli/src/kernel/domain/deploy/deploy-target-port.ts:12-20 — shipped DeployOperation = plan|emit|up|down|status|logs|rollback|secrets matches the corpus's DP-0 8-op claim verbatim
  • packages/cli/src/kernel/domain/deploy/deploy-target-registry-port.ts — registry port confirmed
  • packages/config/src/domain/schemas/deploy-schema.ts — config deploy schema present
  • plugins/auth/ — auth composition mirror template confirmed as the model for the planned plugins/deploy/ layout

Evaluator-run open-decision sweep: none. Specifically tested SG-1 (prebuilt applier matrix — captured in DPB-8), SG-3 (capability pipeline step — moved to DPB-17), SG-8 (Radius predicate gates — captured in DPB-29), plus three additional discharged candidates (stage-H fileability, DPB-17 DAG order, W1–W4/W5 probe-gate independence).

Changes

Files actually written by this session:

  • .llm/runs/plan-deploy-plugin--seed/plan-eval.md (new) — the formal PLAN-EVAL artifact with checklist table, evaluator-run open-decision sweep, load-bearing verification table, hardening-trail tally, and verdict
  • .llm/tmp/run/openhands/pr-891/run-29681236970-1/plan-eval-review.md (new) — identical review copy for the workflow artifact
  • .llm/tmp/run/openhands/pr-891/run-29681236970-1/summary.md (new) — the harness-local run summary

Committed and pushed:

  • Commit: PLAN-EVAL: PASS for plan-deploy-plugin--seed (r5 corpus, 3 adversarial trails integrated) on branch plan/deploy-plugin
  • Push git push origin HEAD:plan/deploy-plugin succeeded (after a git pull --rebase to integrate one intervening remote commit from the supervisor lane)

PR comment posted:

No other files created, modified, removed, or touched. No labels, milestones, or issue metadata changed. No PRs merged.

Validation

Validation for a PLAN-EVAL is corpus-driven and first-hand-verification-driven, not test-driven. The validation steps performed:

  1. Protocol chain verified: AGENTS.md → .agents/skills/netscript-harness/SKILL.md.llm/harness/evaluator/plan-protocol.md.llm/harness/gates/plan-gate.md — all present and consistent on how seed runs are interpreted.
  2. Read the full r5 corpus: research.md + 6 corpus files, plan.md (LD/OF/DPB/risk/gate/deferred sections), rfc.md + Addendum A, design/canonical/DP-0 through DP-9, the three hardening trails (Sol-xhigh 16/16, Kimi-K3 13/13, Sol round-2 9/9), drift.md (D-1…D-8), supervisor.md, worklog.md, context-pack.md.
  3. Spot-verified four load-bearing repo claims first-hand (listed above under Summary).
  4. Walked the plan-gate.md checklist box-by-box, matching to plan.md §1–§9.
  5. Re-ran the open-decision sweep independently against the full r5 corpus — no open decisions found.
  6. Hardening trail integrity verified: triage files exist and totals match the drift.md accounting.

Outcome of validation: every plan-gate box passed. Implementation may begin after owner ratification of OF-1…OF-8 and stage-H board filing — neither of which this evaluator pass performs.

Remaining risks

  • Owner arbitration pending (informational, not a plan-gate finding): OF-1…OF-8 are explicit owner forks that require owner arbitration before implementation; the evaluator did not resolve them.
  • Seed-run interpretation of the commit-slices box: the plan-gate text ("each names what it proves, the gate that proves it, and the files it touches") is literal for implementation-bound plans. For a seed run (fileable board), the convention — stated in plan.md §5 and accepted by the evaluator — is that this metadata lives in the filed issue body at stage-H. A future implementer PLAN-EVAL against filed issue bodies would re-check per-card enumeration. This is documented, not a finding.
  • No implementation validated: this is PLAN-EVAL, not IMPL-EVAL. No code paths were exercised because no implementation exists on this seed run.

OPENHANDS_VERDICT: PASS

Run: https://github.com/rickylabs/netscript/actions/runs/29681236970

This was referenced Jul 19, 2026
@rickylabs

Copy link
Copy Markdown
Owner Author

[PHASE: PLAN-EVAL→FILED] Board filed on PLAN-EVAL PASS — 2026-07-19

The formal PLAN-EVAL (OpenHands · openrouter/qwen/qwen3.7-max) returned PASS (verdict comment above; plan-eval.md committed to this branch by the evaluator). The one-shot filing then executed from the committed filing-manifest.md:

Implementation can launch from the board + the design corpus without reverse-engineering this run. First pull: the four p0s — #893, #895, #897, #898.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:deploy Deployment: CLI/Aspire deploy, targets, bare-metal area:plugins plugins/* and plugin-core packages ci:skip-e2e ci:skip-scaffold Skip the scaffold-static (deno-only) scaffold gate priority:p1 High rfc Request for Comments - substantial/breaking design change status:plan Harness plan phase type:docs

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants