diff --git a/.llm/runs/plan-unified-runtime--seed/adversarial-findings.md b/.llm/runs/plan-unified-runtime--seed/adversarial-findings.md new file mode 100644 index 000000000..dbece43f7 --- /dev/null +++ b/.llm/runs/plan-unified-runtime--seed/adversarial-findings.md @@ -0,0 +1,120 @@ +# Stage-F adversarial findings + +## 1. [BLOCKER] The `deno_deploy` cell validates a platform and CLI that are being shut down, not the surviving Deno Deploy + +- **Claim:** C2 is not a validated v1 runtime cell. The locked plan treats Nitro's `deno_deploy` preset and its `deployctl` flow as current, but the cited Nitro page targets Deno Deploy Classic. Classic and `deployctl` are sunset on 2026-07-20, two days after this corpus's evidence date. The new Deno Deploy uses `deno deploy`, has a different build/runtime model, and does not support Deno queues. Therefore neither the deployment path nor the C2 queue capability claims have been proved for the platform that will exist during implementation. +- **Evidence:** `research/nitro-v3.md:22` and `:48` accept the Nitro provider page without following its `dash.deno.com`/`deployctl` target; `design/D2-capability-matrix/proposal.md:35-38` locks C2 and `:101` calls queue enqueue lossless. The cited [Nitro Deno Deploy page](https://nitro.build/deploy/providers/deno-deploy) still instructs users to obtain a token from `dash.deno.com` and invoke `deployctl`. Deno's [official migration guide](https://docs.deno.com/deploy/migration_guide/) says Classic shuts down on 2026-07-20, `deployctl` is sunset in favor of `deno deploy`, and Deno queues are unavailable on the new platform; the [current platform comparison](https://docs.deno.com/deploy/) confirms queues are unsupported. No corpus artifact validates a Nitro v3 output on the new platform. +- **Severity:** BLOCKER. +- **Suggested disposition:** Return C2 to research before PLAN-EVAL. Execute and document a real Nitro build/deploy/conformance probe on the new Deno Deploy, select and prove any external queue/database bindings, and then rewrite the C2 matrix, issue bodies, and gates. If that proof is unavailable, remove or defer C2 rather than filing it as a v1 lossless cell. + +## 2. [BLOCKER] Folding #451 into UR-4 would falsely close most of #451's public SDK contract + +- **Claim:** UR-4 is a host-side Fetch/oRPC bridge, while #451 is primarily a new public SDK transport surface. The proposed fold loses the transport discriminant, registry, convenience factory, HTTP-default compatibility, HTTP/in-process byte parity, W3C propagation, JSR/export gates, and the owner decision about the SDK-to-service dependency direction. A UR-4 PR carrying `Closes #451` could satisfy UR-4 as drafted while leaving nearly all of #451 unfinished. +- **Evidence:** The live [#451 body](https://github.com/rickylabs/netscript/issues/451) specifies `createInProcessClientLink`, an in-process registry, `ServiceClientTransport`, a `transport` option, `createInProcessServiceClient`, seven acceptance groups, and owner fork O-1. In contrast, `design/D1-composition-host/epic-and-issues.md:89-113` covers server-side delegation/context/error/upgrade behavior only, and `design/D3-board-mechanics/proposal.md:47` and `:128` direct UR-4 to close #451. Shipped reality confirms the missing work: `packages/sdk/src/client/service-client.ts:40-61` always constructs `createHttpClientLink`; the only existing transport seam is the internal structural port at `packages/sdk/src/ports/client-link-factory.ts:17-24`. Live desktop issues [#836](https://github.com/rickylabs/netscript/issues/836) and [#837](https://github.com/rickylabs/netscript/issues/837) still depend on #451. `design/D3-board-mechanics/decision-brief.md:53-55` even predicts O-1, but `plan.md:26-38` drops it from the claimed exhaustive fork sweep. +- **Severity:** BLOCKER. +- **Suggested disposition:** Keep #451 open as its own SDK slice, or expand UR-4's canonical body to preserve every #451 acceptance item and downstream edge. Restore O-1 to the owner sweep and select the public dependency direction before implementation. Remove the planned `Closes #451` until a PR actually proves the complete SDK contract. + +## 3. [BLOCKER] UR-7 and UR-10 do not preserve #453/#454's desktop realization contracts + +- **Claim:** The plan converts concrete packaged-desktop work into generic capability declarations, then schedules downstream PRs to close the original issues. Declaring lock compatibility in UR-7 does not implement #453's per-user filesystem relocation or packaged-binary proof; scoping process identity in UR-10 does not implement #454's generated link-mode switch or packaged dashboard round trip. The stated “desktop consumer stays on #830” boundary does not repair this because the legacy issues themselves remain dependencies of #830's live children. +- **Evidence:** Live [#453](https://github.com/rickylabs/netscript/issues/453) requires OS-specific per-user data-dir resolution, `DATABASE_URL`, a real-filesystem Prisma/Turso path, a b→c cutover guard, sole lock ownership, and validation inside a `deno desktop` packaged binary. UR-7 is only the declared capability in `design/D3-board-mechanics/proposal.md:50` and `design/D2-capability-matrix/epic-and-issues.md:130-152`. Live [#454](https://github.com/rickylabs/netscript/issues/454) requires a generated web/desktop link-mode flag, identical generated client code apart from that flag, and a packaged-binary data-plane E2E. UR-10 at `design/D3-board-mechanics/proposal.md:53` contains only the preset-scoped one-process realization; the manifest edits only acceptance §1 and then promises closure (`filing-manifest.md:84-91`). Live [#837](https://github.com/rickylabs/netscript/issues/837) still depends on #454 and tests both composition modes. +- **Severity:** BLOCKER. +- **Suggested disposition:** Treat UR-7/UR-10 as foundations and KEEP #453/#454 as explicit desktop-consumer realization issues, or create exact #830 successor cards carrying every legacy acceptance item and move the dependency edges. Do not authorize `Closes #453` or `Closes #454` from the generic capability PRs. + +## 4. [BLOCKER] A track-only profile declaration cannot supersede #455's offline-sync implementation + +- **Claim:** UR-8 records that offline sync is a database-target profile; #455 implements offline behavior. Those are different deliverables. Closing #455 from a track-only UR-8 PR would erase the required sync engine and behavioral acceptance without implementing them. +- **Evidence:** Live [#455](https://github.com/rickylabs/netscript/issues/455) requires Turso Sync `pull()`/`push()`, fully disconnected operation, reconnect reconciliation, and a documented last-push-wins/custom-transform conflict policy. D2-S7 says it is “track-only” and limits acceptance to a profile declaration and cross-reference (`design/D2-capability-matrix/epic-and-issues.md:210-230`; `agent-briefs.md:111-119`). Nevertheless, D3 declares “folds #455” and a future UR-8 PR `Closes #455` (`design/D3-board-mechanics/proposal.md:51`, `:131`; `filing-manifest.md:86-91`). The legacy dependency on #454 is also converted into a UR-10→UR-8 ordering even though UR-8 contains no implementation. +- **Severity:** BLOCKER. +- **Suggested disposition:** KEEP #455 as the downstream implementation issue and let UR-8 be a prerequisite/profile contract, or expand UR-8 to carry and test the entire live #455 scope. A deferred declaration PR must not contain a closing keyword for #455. + +## 5. [BLOCKER] The proposed Nitro host path bypasses shipped service startup/shutdown semantics + +- **Claim:** D1 assumes it can mount `ServiceApp.fetch` under Nitro and replace listener teardown with a new disposal registry. In shipped code, however, `build()` returns only the app and neither executes nor exposes builder lifecycle hooks. Startup hooks and shutdown hooks are private; they are honored only by `serve()`, the very listener-owning path D1 forbids. Existing services using `.onStartup()`/`.onShutdown()` would silently lose lifecycle behavior when hosted as drafted. +- **Evidence:** D1 makes Nitro the sole listener and assigns teardown to a new registry (`design/D1-composition-host/proposal.md:46-91`; `epic-and-issues.md:42-63`). `ServiceBuilderImpl` stores hooks privately (`packages/service/src/builder/service-builder-impl.ts:70-71`), registers them through `onStartup`/`onShutdown` (`:299-340`), but `build()` merely installs routes and returns the app (`:423-432`). Only `serve()` runs startup hooks and passes shutdown hooks into the Deno listener (`:501-521`). The existing package-private `ServiceShutdownCoordinator` already owns idempotency, abort, a bounded drain budget, LIFO hooks, and structured failures (`packages/service/src/builder/service-shutdown.ts:1-135`), semantics absent from D1's “exactly once” registry. The corpus itself says a bridge must order start, close, drain, and failure reporting (`research/adapter-mapping.md:33`). +- **Severity:** BLOCKER. +- **Suggested disposition:** Add and design a prerequisite hostable-service lifecycle contract before UR-2: an exported build/start/stop surface (or equivalent) that preserves existing hooks, startup-failure rollback, abort/drain budgets, LIFO ordering, and reports. Specify its package/export/JSR gates and reuse the existing coordinator policy rather than inventing an incompatible second lifecycle. + +## 6. [BLOCKER] The owner decision brief still contains unresolved placeholders and omits a known mandatory fork + +- **Claim:** The file the owner must ratify is not the locked combined fork sweep. It still contains literal `` and `` placeholders and instructions for Stage E to replace them. At least one known decision—#451 O-1—is absent from `plan.md`'s allegedly exhaustive F-1…F-10 list. Owner ratification of this brief therefore cannot authorize the actual design. +- **Evidence:** `design/D3-board-mechanics/decision-brief.md:51-62` leaves both placeholder blocks and explicitly orders Stage E to reconcile them. The same block names the SDK↔service dependency direction as an expected fork (`:53-55`), while `plan.md:22-38` says “none silently taken” but contains no such fork. `filing-manifest.md:3-4` and `:20-21` make in-turn ratification of this incomplete brief a precondition to filing. +- **Severity:** BLOCKER. +- **Suggested disposition:** Return the lock to Stage E. Replace every placeholder with the real cross-pack forks, restore O-1 and any provider/durability selections, renumber once, and make the decision brief and `plan.md` identical before another Stage-F/Stage-G pass. Do not present the current brief for owner ratification. + +## 7. [BLOCKER] Every implementation brief is invalid under the explicit stop-line invariant + +- **Claim:** The packs promise verbatim stop-lines in every brief but put a paste instruction in each actual brief instead. D2's shared source block is verbatim, but it is not repeated in any D2 brief. D1 neither repeats the block nor preserves the exact text in its shared approximation. This directly violates hard stop-line 4. +- **Evidence:** Each D1 brief ends with the literal `[paste stop-lines]` (`design/D1-composition-host/agent-briefs.md:43`, `:59`, `:75`, `:93`, `:108`). D1's shared block omits “(2026-07-17 in-turn)” and changes hard-line wording (`:13-22`). Each D2 brief contains only “(paste the Shared stop-lines block verbatim.)” (`design/D2-capability-matrix/agent-briefs.md:47`, `:60`, `:73`, `:84`, `:96`, `:109`, `:120`) rather than a `## Stop-lines` section. The exact invariant is recorded in `design/D3-board-mechanics/filing-manifest.md:134-144`: a sub-brief without the repeated section is invalid. +- **Severity:** BLOCKER. +- **Suggested disposition:** Materialize the exact five user-supplied stop-lines, character-for-character in substance including the date and invalid-brief sentence, inside every individual D1/D2 brief and every later D3/handoff brief. References, templates, and paste markers do not satisfy the invariant. + +## 8. [BLOCKER] The filing manifest has no deterministic body for several of its twelve issues + +- **Claim:** Stage H cannot create the proposed board without inventing content. The manifest names only an owning pack, not a canonical draft or merge transform. Five D1 drafts are compressed into four D1 slots; seven D2 drafts are compressed into six nominal D2/shared slots; D2-S5 has no destination; UR-10 has no composed D1+D2 body; and D3 supplies no actual issue-body drafts for UR-11 or UR-H. +- **Evidence:** The manifest asserts UR-1…UR-10 bodies are supplied by D1/D2 and D3 supplies UR-11/UR-H (`design/D3-board-mechanics/filing-manifest.md:9-11`, `:55-74`). D1 actually provides D1-1…D1-5 and maps none to UR handles (`design/D1-composition-host/epic-and-issues.md:141-149`); D1-5 apparently has to be merged into UR-4, but no transform says so. D2 provides D2-S1…S7, including a full task/schedule issue at `design/D2-capability-matrix/epic-and-issues.md:156-180`, but D3's slots at `design/D3-board-mechanics/proposal.md:44-55` have no task/schedule home. UR-10 is marked D1+D2 without a body source, and neither `proposal.md`, `filing-manifest.md`, nor `decision-brief.md` contains canonical bodies for UR-11/UR-H. +- **Severity:** BLOCKER. +- **Suggested disposition:** Create one canonical, final title/body/acceptance artifact per UR handle, plus an exact draft→slot map and explicit merge transforms. Carry forward every folded legacy acceptance item or mark the legacy issue KEEP. Validate the twelve bodies mechanically before Stage H; the filer must not compose prose on the fly. + +## 9. [BLOCKER] “One-shot” filing is neither atomic nor resumable and crosses an unmet PR prerequisite + +- **Claim:** The manifest offers no safe recovery if any create/edit call fails. It writes `FILING-LOG.md` only after all issue and legacy mutations, has no per-slot idempotency marker, no immediate read-after-write log, no duplicate/resume rule, and no compare-before-edit guard. A mid-run failure can leave duplicate issues or partially rewritten legacy bodies on retry. In addition, the required label-parity PR cannot be filed and treated as complete in the same operation: merging it is gated by CI and an opposite-family PASS, but the manifest neither waits for that merge nor defines a resume boundary. +- **Evidence:** The operation order is labels PR → milestones → twelve creates → five legacy edits → log (`design/D3-board-mechanics/filing-manifest.md:23-95`). Step 1 says to file the parity PR “first” and not rely on a live-only label (`:31-38`), but the next step proceeds without a merge/CI/eval checkpoint. The only durable draft→live mapping is created after every mutation (`:93-124`). Exact-title milestone preflight (`:40-46`) has no race/re-read behavior, and issue creates have no hidden stable draft ID or pre-create search. The stop-lines at `:136-137` forbid bypassing the parity PR's merge gates. +- **Severity:** BLOCKER. +- **Suggested disposition:** Split the parity PR into a completed prerequisite and resume Stage H only after its gated merge. Make board filing a resumable transaction: embed a stable run/slot marker in each body, search before create, persist each returned number immediately, read back labels/milestone/body, guard legacy edits against expected old content, and define exact retry/conflict behavior. Produce the filing log incrementally, not after the blast radius. + +## 10. [MAJOR] The filing table violates the required one-status taxonomy and silently changes pack labels + +- **Claim:** Step 4 says every issue receives full taxonomy, but no row includes a `status:` label. The prose says `status:plan`, while both draft packs say `status:triage`; there is no authoritative transformation. The manifest also loses or changes issue-type/gate labels during compression, so “labels per row” is not label parity with the approved drafts. +- **Evidence:** `.github/labels.yml:8-14` requires exactly one status on every open issue/PR. The manifest lists `status:plan` in its inventory (`design/D3-board-mechanics/filing-manifest.md:25-30`) but omits status from all twelve rows (`:61-74`). D1 declares `status:triage` as common draft taxonomy (`design/D1-composition-host/epic-and-issues.md:14-15`), as does D2 on each issue. For example, D2-S6 is `type:test` + `gate:e2e` (`design/D2-capability-matrix/epic-and-issues.md:184-205`), while the presumed UR-6 row is `type:feat` with no gate label (`filing-manifest.md:72`). +- **Severity:** MAJOR. +- **Suggested disposition:** Make the canonical per-slot artifact authoritative for an exact label set, including exactly one owner-ratified status. Reconcile every type/area/gate/wave difference explicitly and have preflight fail before mutation if any requested label is absent or any row lacks a status. + +## 11. [MAJOR] The milestone train contradicts itself, and the single UR-6 card cannot represent the chosen deferral + +- **Claim:** There is no single milestone decision for the owner to ratify. The locked plan puts D2 S1–S4 in beta.12, D3 puts essentially all core UR work in beta.13, and the filing manifest assigns all corresponding cards beta.13. Independently, F-2/OF-4 defer the tier-3 cell while F-10 keeps one UR-6 issue; a GitHub issue has one milestone and one completion state, so one card cannot both close in beta.13 and remain open for beta.14/stable. UR-H's dependency on UR-6 makes the contradiction release-blocking. +- **Evidence:** `plan.md:29` assigns S1–S4 to beta.12 and S5–S6 to beta.13; `plan.md:44-45` again says beta.12 core then beta.13 marquee. D3's normative train instead assigns UR-1…UR-5/7/9/10/11/H and most UR-6 cells to beta.13 (`design/D3-board-mechanics/proposal.md:63-75`), while the manifest assigns UR-1…UR-7/9/10/11/H beta.13 (`filing-manifest.md:63-74`). D3 simultaneously insists UR-6 is one issue (`proposal.md:57-59`), defers its isolate cell (`:73-75`), and makes UR-H depend on UR-6 (`:106`). +- **Severity:** MAJOR. +- **Suggested disposition:** Choose one train and regenerate every plan/draft/manifest reference. If a cell is genuinely deferred, split it into a separately milestoned successor or remove it from the beta.13 card's closure acceptance; do not pretend a single issue can be partly closed across milestones. + +## 12. [MAJOR] Ratifying the stated default forks would still require unplanned body rewrites + +- **Claim:** The manifest is not parameterized by fork result. Several draft acceptances encode the non-default or broader branch, so even choosing the stated defaults cannot be filed “once from the committed manifest” without an author improvising edits after ratification. +- **Evidence:** F-4 defaults WebSocket/upgrade work to post-v1 (`plan.md:31`), but D1-4 unconditionally requires a WebSocket-upgrade conformance case (`design/D1-composition-host/epic-and-issues.md:103-113`). F-7 defaults bounded-window sagas to reject-only v1 (`plan.md:34`), while D2-S2 describes externalization as the C2/C4 v1 behavior and accepts an externalization target (`design/D2-capability-matrix/epic-and-issues.md:68-90`). F-2/OF-4 defers tier 3, but D2-S6 requires all four cells green (`:190-205`). The filing manifest contains no conditional patches or branch-specific bodies. +- **Severity:** MAJOR. +- **Suggested disposition:** For every fork, provide explicit A/B body, label, milestone, DAG, and supersession deltas—or generate final canonical bodies only after the owner selects. Re-run adversarial/PLAN-EVAL on the materialized branch before filing if a selection changes acceptance or dependency structure. + +## 13. [MAJOR] The supersession map leaves live #327 as a contradictory GitHub authority + +- **Claim:** The plan says its saga rule replaces #327 D1, but the reconciliation manifest does not edit or annotate #327. Because the packs declare GitHub authoritative after filing and new issues remain children of the deployment umbrella, implementers will encounter a live parent decision saying unified mode is deferred, takes 3–5 months, and excludes sagas alongside new children saying it is beta.13 and supports preset-conditional sagas. +- **Evidence:** Live [#327](https://github.com/rickylabs/netscript/issues/327) retains D1 “WATCH / separate track—not v1” with a categorical saga exclusion; its later RFC addendum rehomes #823 but does not replace that acceptance language. Live closed [#349](https://github.com/rickylabs/netscript/issues/349) repeats the old exclusion. `plan.md:14` declares the exclusion stale and replaced, while D3 deliberately keeps `epic:deployment` ancestry (`design/D3-board-mechanics/proposal.md:134-137`). Yet the supersession actions enumerate only #451/#453/#454/#455/#349 (`filing-manifest.md:76-91`), and authority banners are added only to run docs (`:126-130`). +- **Severity:** MAJOR. +- **Suggested disposition:** Add #327 to the owner-ratified reconciliation map with an exact non-closing body addendum/edit that supersedes D1 and links the new capability rule; update #349's successor note consistently. Audit all live dependents for the old saga/timeline text before declaring GitHub authoritative. + +## 14. [MAJOR] Stage-I lanes are missing the package, public-surface, archetype, and compiler contracts they need to start + +- **Claim:** The briefs name abstractions but not a realizable repository boundary. There is no identified “unified-runtime host package,” export map, dependency graph, or doctrine archetype. The “composition compiler” is supposed to infer graph requirements, but no schema, graph metadata contract, build command, or integration point exists. An implementation lane would first have to make architecture decisions that the locked plan claims are settled. +- **Evidence:** D1-1 expects “a new composition-root module in the unified-runtime host package” without naming a path/package/export (`design/D1-composition-host/agent-briefs.md:35-40`); no such package exists in the checkout. D2-S1 says a compiler reads logical-graph requirements (`design/D2-capability-matrix/epic-and-issues.md:25-38`; `proposal.md:195-207`) but defines neither the requirement schema nor how static build tooling observes dynamically composed services/plugins. The plan's gate matrix (`plan.md:56-60`) is only the seed workflow, not the doctrine archetype/gate/public-surface matrix required for changes across service, SDK, CLI/config, database/KV/queue, and plugin runtimes. +- **Severity:** MAJOR. +- **Suggested disposition:** Before handoff, select doctrine archetype(s), exact package/file ownership, allowed import directions, public versus internal exports, machine-readable manifest/requirement types, the build/CLI invocation seam, migration policy, and per-package fitness/JSR/E2E gates. Split contracts into prerequisite issues where necessary so lanes do not reverse-engineer the architecture. + +## 15. [MAJOR] The corpus claims preserved dated evidence files that are absent from the review checkout + +- **Claim:** Five corpus files cite local dated extracts as the reproducible evidence record, but none of those extracts exists. Mutable beta documentation and the exact PR-head frame therefore cannot be audited from the seed artifact set as claimed. This is material here: following the missing/current platform evidence exposes the Deno Deploy Classic shutdown that the locked plan missed. +- **Evidence:** `research/market.md:4`, `adapter-mapping.md:3-5`, `drift-ledger.md:3-5`, `nitro-v3.md:3-4`, and `orpc-fresh.md:3-4` claim preservation under `.llm/tmp/docs/` for five named 2026-07-18 extracts. `.llm/tmp/docs/` and all five files are absent at detached HEAD `62a064e5`. The corpus includes mutable Nitro/oRPC/Fresh beta URLs and uses an exact PR #822 head SHA, making a dated snapshot more than cosmetic provenance. +- **Severity:** MAJOR. +- **Suggested disposition:** Put immutable evidence under the run's committed resources (or link immutable upstream commit blobs), with source URL, retrieval timestamp, and checksum. Re-run the load-bearing platform checks against those artifacts and amend any finding whose original snapshot cannot be reproduced. + +## 16. [MINOR] #349's planned “no state change” preserves an invalid terminal status label + +- **Claim:** #349 is closed but still carries `status:triage`; the manifest explicitly preserves that state. This violates the repository's lifecycle taxonomy and leaves the supersession reconciliation visibly inconsistent. +- **Evidence:** Live [#349](https://github.com/rickylabs/netscript/issues/349) is closed with `status:triage`. `.github/labels.yml:8-14` requires completed closures to use `status:shipped` and not-planned closures to have no status. D3 records the mismatch at `design/D3-board-mechanics/proposal.md:132` but the manifest orders “no state change” (`filing-manifest.md:88`). +- **Severity:** MINOR. +- **Suggested disposition:** Classify the existing closure as completed versus not-planned during owner ratification, then replace `status:triage` with `status:shipped` or remove the status accordingly; do not reopen/re-close the issue. + +## 17. [MINOR] The locked handle namespace says UR-1…UR-12, but the filing namespace is UR-1…UR-11 plus UR-H + +- **Claim:** The plan has two incompatible identifiers for its twelfth child. This can corrupt draft→live mappings, checklist generation, and later automation even if humans infer that UR-H is the twelfth row. +- **Evidence:** `plan.md:19` locks a “UR-1…UR-12 skeleton.” D3's slot table contains UR-1…UR-11 and UR-H (`design/D3-board-mechanics/proposal.md:42-55`), and the filing table does the same (`filing-manifest.md:61-74`). No UR-12 body or alias exists. +- **Severity:** MINOR. +- **Suggested disposition:** Choose UR-12 or UR-H as the sole canonical handle and update the plan, body artifacts, checklist template, and filing-log schema before any issue creation. diff --git a/.llm/runs/plan-unified-runtime--seed/adversarial-nitro-vs-own.md b/.llm/runs/plan-unified-runtime--seed/adversarial-nitro-vs-own.md new file mode 100644 index 000000000..03b0ea1f3 --- /dev/null +++ b/.llm/runs/plan-unified-runtime--seed/adversarial-nitro-vs-own.md @@ -0,0 +1,57 @@ +# Adversarial findings — Nitro versus own-layer analysis pair + +## 1. [BLOCKER] The AWS citation proves an HTTP sidecar and raw-event tunnel, not a native AWS provider family + +**Claim.** Rev2 flips AWS from Nitro to an “owned AWS family” because Lambda Web Adapter allegedly preserves native event/product breadth and extends naturally to SQS, DynamoDB, Step Functions, and other leaf bindings (`research/nitro-vs-own-rev2.md:37,85-93,150-161`). + +**Evidence.** The cited AWS repository's Deno example compiles the application to a single binary, runs it under the `java11` Lambda runtime for SnapStart, and explicitly has “no runtime hooks”; its non-HTTP feature merely POSTs the raw Lambda event JSON to a local `/events` HTTP endpoint. That transport does not implement SQS polling configuration, `ReportBatchItemFailures`, per-record ack/nack, visibility-timeout behavior, idempotency, resource provisioning, or any `MessageQueue`/saga port. The committed extract collapses “supports non-HTTP triggers” into “native event/product breadth” (`evidence/nitro-vs-own-rev2-live-2026-07-18.md:19-25,54-65`), while the shipped queue contract requires delivery count, async ack/nack, requeue/dead-letter metadata, long-running `listen`, graceful `stop`, concurrency, visibility timeout, and abort (`packages/queue/ports/message-queue.ts:39-77,86-132,172-205`). AWS itself requires explicit partial-batch response configuration and response shaping for SQS failures. + +**Suggested disposition.** Reject the AWS flip as unproved. Split HTTP hosting from AWS event/resource adapters, require a concrete SQS conformance design and live probe, and estimate each independently before choosing Nitro versus native tooling. + +## 2. [MAJOR] “Official Cloudflare tooling is Deno-compatible” is being mistaken for a cheap Deno-native build path + +**Claim.** Rev2 calls the Cloudflare wrapper thinner than Nitro and prices HTTP/deploy at 2–4 weeks because Wrangler can point at TypeScript and Vite/Miniflare supply build, preview, and target semantics (`research/nitro-vs-own-rev2.md:35,40-44,52-55`). + +**Evidence.** The Deno tutorial proves that a Deno project can invoke the npm Wrangler package; it does not remove Wrangler's Node/esbuild toolchain. The recommended Cloudflare Vite plugin is itself a Vite/npm integration—the same broad build family rev2 treats as a Nitro cost—and its programmatic configuration omits settings from `wrangler types` and resource CLI commands. Miniflare is explicitly a simulator supporting “most” features, not a production-fidelity oracle: remote Durable Objects and Workflows are unavailable, static assets and metadata differ locally, some platform limits are production-only, and Cloudflare recommends remote/live testing for network-specific behavior. The evidence extract only records the positive surface (`evidence/nitro-vs-own-rev2-live-2026-07-18.md:12-18`) and omits these load-bearing limitations. + +**Suggested disposition.** Recast this as “provider-owned Node tooling callable from Deno,” not Deno-native. Add toolchain/runtime dependency, unsupported-binding, remote-binding, and live-smoke costs before comparing it with Nitro's already-Vite-based emitter. + +## 3. [BLOCKER] Provider primitives do not satisfy NetScript's queue and saga contracts at the depth claimed + +**Claim.** Rev2 says Cloudflare Queues are close to `MessageQueue`, Durable Objects are plausible saga/worker primitives, and the provider-suite depth is sufficient to flip Cloudflare to an owned adapter family (`research/nitro-vs-own-rev2.md:67-81`). + +**Evidence.** A Cloudflare push consumer is an invocation-time `queue(batch)` handler, whereas `MessageQueue.listen()` is a caller-owned long-running loop with graceful drain/stop and `AbortSignal`; a pull consumer adds leases and REST acknowledgement, which is a different operational path requiring credentials and polling ownership. Batch retry also redelivers successful records unless they are individually acknowledged. Workers KV is eventually consistent and explicitly unsuitable for atomic operations/transactions; `KvStore.atomic()` is optional, but the adapter therefore cannot support CAS-dependent consumers and must be rejected by capability. Durable Object storage is private to one object instance, while `SagaStorePort` requires optimistic state saves, transition history, and a cross-instance correlation index (`packages/plugin-sagas-core/src/ports/saga-store-port.ts:22-48`), and T2 additionally reserves atomic state/outbox behavior. Rev2 acknowledges isolated guardrails but still uses the suite's breadth as the architectural flip and prices the first leaf as a small mapping exercise. + +**Suggested disposition.** Treat each provider primitive as a separate feasibility card with an explicit activation model and capability subset. Do not use product-count breadth as evidence that a provider family satisfies NetScript's ports. + +## 4. [MAJOR] The revised estimates are arithmetic assertions without a work breakdown and exclude work required by their own acceptance rule + +**Claim.** Wrapping reduces Cloudflare HTTP to 2–4 weeks, a Cloudflare leaf to 1–2 weeks, AWS HTTP to 2–4 weeks, an AWS leaf to 1.5–3 weeks, and experimental Vercel to 1–3 weeks (`research/nitro-vs-own-rev2.md:46-65`). + +**Evidence.** No estimate is tied to tasks, comparable delivery history, staffing assumptions, or uncertainty ranges for Deno/npm resolution, config/schema generation, credentials/IAM, provisioning, local-vs-live fixtures, failure recovery, and publish gates. Provider accounts and production soak are explicitly excluded at `:48-50`, yet the final decision rule requires native binding/event/config coverage and identical target conformance (`:181-187`), which cannot be established without provisioned live targets. The AWS estimate also counts Lambda Web Adapter's envelope translation as if it supplied leaf semantics (Finding 1), and the Cloudflare leaf estimate compresses the activation and durability gaps in Finding 3 into “semantic mapping.” + +**Suggested disposition.** Replace point ranges with a task-level estimate and confidence grade; include account/IaC/live-conformance work or explicitly price it as a mandatory separate lane. Until then, do not use the estimates to choose architecture. + +## 5. [MAJOR] `@netscript/deploy` is specified as both a neutral core and a cross-domain composition god-object + +**Claim.** Rev2 proposes extracting a callable deploy core while keeping leaf semantics in leaf packages and preserving a one-way dependency `leaf ports <- provider adapters <- deploy <- CLI` (`research/nitro-vs-own-rev2.md:100-146`). + +**Evidence.** Its proposed public surface makes deploy own physical topology, leaf bindings, capability requirements, artifact emission, resource resolution, provisioning, event activation routing, and adapter registration (`:130-141`). `ResourceBindingResolverPort` must understand KV/queue/database resource shapes, and `ActivationRouterPort` must retain queue/stream delivery semantics; those are exactly the leaf concerns the next paragraph says deploy must not absorb. If deploy composes leaf-owned provider adapters, it must import every leaf contract and selected provider package; if leaf packages import deploy declarations, the stated dependency direction cycles. Shipping adapters from each leaf also multiplies provider SDK/tool dependencies and JSR subpath/export gates across KV, queue, database, workers, sagas, triggers, and streams, but rev2 provides no package graph or publish-surface budget. This conflicts with doctrine's small published-surface rule and its prohibition on god interfaces/premature abstraction (`docs/architecture/doctrine/02-public-surface.md`; `docs/architecture/doctrine/09-anti-patterns-and-fitness-functions.md` AP-3/AP-9). + +**Suggested disposition.** Require an explicit package/import graph and adapter-registration ownership before accepting `@netscript/deploy`. Keep provider contributions outside the neutral core and prove that deploy can compose them without importing leaf implementations or provider SDKs. + +## 6. [BLOCKER] The UR delta table is not a filable branch and contradicts the canonical issue bodies it claims largely survive + +**Claim.** Rev2 says UR-0/UR-1/UR-3/UR-4 “survive in intent,” replaces UR-2's Nitro ownership, generalizes UR-5/UR-6, expands UR-11, and rewrites UR-12 (`research/nitro-vs-own-rev2.md:163-179`). + +**Evidence.** The canonical DAG and bodies are Nitro-specific across those supposedly surviving cards: UR-0 blocks and delegates close to the Nitro host (`design/canonical/UR-0.md:10,18-24,42-44,61-62`); UR-2 is titled “Nitro owns listener/lifecycle” and makes Nitro the sole listener (`design/canonical/UR-2.md:3,18-33`); UR-3 depends on UR-2 and assigns routing/assets to Nitro (`design/canonical/UR-3.md:9,22-24,37-41`); UR-4 gates H3 matching and Nitro error behavior (`design/canonical/UR-4.md:24-29,44-48`); UR-5 drains on Nitro close (`design/canonical/UR-5.md:34-35`); UR-6 requires pinned Nitro and names Nitro preset cells (`design/canonical/UR-6.md:22-29,41-54`); and UR-12 requires the Nitro-pinned suite (`design/canonical/UR-12.md:19-27`). Replacing UR-2 changes downstream bodies, dependencies, titles, acceptance, briefs, and the filing manifest—not just four rows. Rev2 supplies none of the exact alternate canonical artifacts, labels, DAG transforms, or an owner fork, so filing “under” this table would either file the old Nitro board or improvise a different board after ratification. + +**Suggested disposition.** Do not file from this delta table. Treat provider-native HYBRID as a new owner fork requiring a complete canonical branch (all affected bodies, DAG, labels, milestones, briefs, slot map, and manifest) plus another adversarial/PLAN-EVAL pass. + +## 7. [MINOR] The Vercel maintenance evidence supports “experimental,” but not the quoted delivery estimate + +**Claim.** Rev2 cautiously retains Nitro as the Vercel default while pricing a `vercel-deno` challenger at 1–3 weeks (`research/nitro-vs-own-rev2.md:34,58,157-158`). + +**Evidence.** The live repository is current but extremely small (20 commits, 11 stars, zero forks, no releases, no open issues/PRs at review time); its README requires a community runtime version in `vercel.json`, installs Deno separately for builds via a remote shell script, uses different Deno behavior under `vercel dev`, and positions the runtime for simple functions rather than full applications. The committed extract records most of these facts (`evidence/nitro-vs-own-rev2-live-2026-07-18.md:5-11`) but no production-scale compatibility or maintenance history supports a 1–3 week conformance challenger. + +**Suggested disposition.** Keep it research-only and remove the delivery range until a minimal NetScript build/deploy probe measures the builder and runtime gaps. diff --git a/.llm/runs/plan-unified-runtime--seed/adversarial-recheck.md b/.llm/runs/plan-unified-runtime--seed/adversarial-recheck.md new file mode 100644 index 000000000..03dbe4cb4 --- /dev/null +++ b/.llm/runs/plan-unified-runtime--seed/adversarial-recheck.md @@ -0,0 +1,81 @@ +# Stage-F adversarial recheck — f85d4919 + +## 1. PARTIALLY-RESOLVED — obsolete Deno Deploy cell + +Evidence: `design/canonical/UR-6.md:32-39` withdraws Classic/`deployctl` from v1, but `design/D2-capability-matrix/agent-briefs.md:62-66` still instructs a Stage-I lane to build-reject C2 and `:101-104` still assigns C2 writer-ownership behavior. + +## 2. RESOLVED — #451 was over-folded into UR-4 + +Evidence: `design/canonical/UR-4.md:31-40,49,53-60` limits UR-4 to the host bridge, keeps #451 open for its full SDK contract, and restores owner fork O-1 as F-7. + +## 3. RESOLVED — #453/#454 desktop realization was lost + +Evidence: `design/canonical/UR-7.md:11-12,25-38` and `design/canonical/UR-10.md:11-12,26-40` make the UR cards foundations while preserving #453/#454 as open desktop-realization issues. + +## 4. RESOLVED — #455 implementation was falsely superseded + +Evidence: `design/canonical/UR-8.md:10-11,24-38` defines only the profile/prerequisite contract and explicitly keeps #455 open for the Turso Sync engine and behavioral acceptance. + +## 5. PARTIALLY-RESOLVED — Nitro hosting bypassed shipped lifecycle semantics + +Evidence: `design/canonical/UR-0.md:26-44,55-63` adds the prerequisite hostable lifecycle contract and reuses `ServiceShutdownCoordinator`, but `design/D1-composition-host/agent-briefs.md:58-62` still directs implementation to invent and drain a disposer registry as the lifecycle contract. + +## 6. RESOLVED — owner brief had placeholders and a missing fork + +Evidence: `design/D3-board-mechanics/decision-brief.md:3-29` materializes F-1…F-17, including restored #451 O-1 as F-7, with no placeholder rows. + +## 7. RESOLVED — implementation briefs omitted mandatory stop-lines + +Evidence: `design/D1-composition-host/agent-briefs.md:64-68` and `design/D2-capability-matrix/agent-briefs.md:69-74` exemplify the exact five-line block; mechanical count finds eight complete blocks in each pack (template plus seven briefs). + +## 8. PARTIALLY-RESOLVED — filing lacked deterministic canonical bodies + +Evidence: `design/canonical/slot-map.md:5-35` maps every slot to canonical inputs, but `design/D3-board-mechanics/filing-manifest.md:81-84` tells the filer to copy an entire canonical artifact verbatim rather than extracting its `## Body` and acceptance sections. + +## 9. RESOLVED — filing was non-resumable and crossed an unmet prerequisite + +Evidence: `design/D3-board-mechanics/filing-manifest.md:16-32,36-58,74-92` supplies per-slot idempotency, immediate logging, read-after-write, compare-before-edit, recovery rules, and a merged label-parity prerequisite. + +## 10. RESOLVED — filing taxonomy had multiple statuses and label drift + +Evidence: `design/D3-board-mechanics/filing-manifest.md:96-114` gives an exact per-slot label/milestone table with exactly one `status:` label and a preflight failure rule for missing repository labels. + +## 11. RESOLVED — milestone train and deferred-cell representation conflicted + +Evidence: `design/D3-board-mechanics/decision-brief.md:21-22` fixes one beta.13 UR train, while `design/canonical/UR-6.md:32-39` and `design/canonical/DD-RESEARCH.md:3-10` represent Deno Deploy as a separately milestoned research successor. + +## 12. PARTIALLY-RESOLVED — owner fork choices still require post-ratification rewriting + +Evidence: `design/D3-board-mechanics/decision-brief.md:54-59` provides committed A/B deltas for only six body-changing forks, while F-12 at `:24` can change the number of issues and slot map without a materialized branch artifact. + +## 13. RESOLVED — #327 remained a contradictory authority + +Evidence: `design/D3-board-mechanics/filing-manifest.md:130-147` specifies a compare-before-edit, non-closing #327 addendum that supersedes the saga exclusion and links UR-5 while preserving unrelated clauses. + +## 14. RESOLVED — Stage-I lacked architecture prerequisites + +Evidence: `design/canonical/UR-11.md:18-42,49-53` makes package/export ownership, doctrine archetypes, requirement schema, and build/CLI seam an acceptance-gated prerequisite blocking UR-1/UR-4/UR-5. + +## 15. RESOLVED — cited dated evidence was absent + +Evidence: `evidence/SHA256SUMS:1-6` covers all six committed extracts and `sha256sum -c evidence/SHA256SUMS` verifies every entry, including the new-platform Deno Deploy snapshot used by `research/deno-deploy-new.md`. + +## 16. RESOLVED — #349 retained an invalid terminal status + +Evidence: `design/D3-board-mechanics/filing-manifest.md:133-136` requires owner classification followed by `status:shipped` for completed closure or removal of `status:triage` for not-planned closure. + +## 17. RESOLVED — locked and filing namespaces disagreed + +Evidence: `design/canonical/slot-map.md:5-35` and `design/D3-board-mechanics/filing-manifest.md:94-111` consistently enumerate UR-0…UR-12 plus the non-UR DD-RESEARCH successor; no legacy UR-H handle remains. + +## NEW-1. [MAJOR] Verbatim canonical-file filing would publish planning metadata and duplicate the idempotency marker + +Evidence: `design/D3-board-mechanics/filing-manifest.md:10-12,81-84` mandates whole-file verbatim copy, while `design/canonical/UR-6.md:1-17` contains the marker both at file scope and inside the intended body, with title/labels/dependency metadata between them. + +## NEW-2. [MAJOR] F-2 branch B creates a dependency cycle between UR-6 and DD-RESEARCH + +Evidence: `design/canonical/DD-RESEARCH.md:9-10` depends on UR-6, but `design/canonical/UR-6.md:63-68` requires DD-RESEARCH to complete before branch-B UR-6 can become the four-cell suite. + +## NEW-3. [MINOR] UR-6's canonical title still promises a four-cell conformance suite + +Evidence: `design/canonical/UR-6.md:3` says “four-cell conformance suite,” contradicting its three-cell v1 definition and gates at `:22-39,51-54`. diff --git a/.llm/runs/plan-unified-runtime--seed/adversarial-triage.md b/.llm/runs/plan-unified-runtime--seed/adversarial-triage.md new file mode 100644 index 000000000..96fbe6123 --- /dev/null +++ b/.llm/runs/plan-unified-runtime--seed/adversarial-triage.md @@ -0,0 +1,30 @@ +# Stage-F triage — supervisor dispositions (2026-07-18) + +Reviewer: Sol·max, unoriented, detached checkout @ 62a064e5 (session 019f724f-64e4…). 17 +findings: 9 BLOCKER / 6 MAJOR / 2 MINOR. Verdict: **plan returns to Stage E** (first of two +allowed fail cycles). Every finding ACCEPTED; dispositions: + +| F# | Disposition | +| --- | --- | +| 1 | ACCEPT. C2 (`deno_deploy`) is NOT a validated v1 cell — Deno Deploy Classic/deployctl sunset 2026-07-20. C2 leaves the v1 cell set; replaced by a research card (new-platform Nitro probe incl. queue/database bindings). New owner fork: 3-cell v1 vs re-proven C2. | +| 2 | ACCEPT. #451 KEEP as its own SDK slice; UR-4 = host-side bridge only, no `Closes #451`. O-1 (SDK↔service dependency direction) restored to the fork sweep. | +| 3 | ACCEPT. #453/#454 KEEP as desktop-realization issues; UR-7/UR-10 are foundations, no closing keywords. | +| 4 | ACCEPT. #455 KEEP; UR-8 = profile/prerequisite contract only, no `Closes #455`. | +| 5 | ACCEPT. New prerequisite card UR-0: hostable-service lifecycle contract (exported build/start/stop preserving onStartup/onShutdown, reusing ServiceShutdownCoordinator policy) BEFORE UR-2. | +| 6 | ACCEPT. Stage-E redo produces a single materialized decision brief (no placeholders), fork list renumbered once, identical to plan.md. | +| 7 | ACCEPT. Verbatim five stop-lines materialized character-for-character in every pack brief. | +| 8 | ACCEPT. One canonical title/body/acceptance artifact per UR slot + explicit draft→slot map + merge transforms; mechanically validated before Stage H. | +| 9 | ACCEPT. Label-parity PR becomes a gated PREREQUISITE (merged before filing). Filing becomes a resumable transaction: stable slot marker in each body, search-before-create, immediate per-slot log writes, compare-before-edit on legacy bodies. | +| 10 | ACCEPT. Canonical per-slot label sets incl. exactly one `status:`; preflight fails on mismatch. | +| 11 | ACCEPT. One milestone train (Stage-E decision), deferred cells split into separately milestoned successors. | +| 12 | ACCEPT. Fork-parameterized bodies: explicit A/B deltas per fork, or bodies materialized post-selection with a re-check pass. | +| 13 | ACCEPT. #327 added to the reconciliation map with a non-closing addendum superseding D1's saga exclusion; #349 successor note aligned. | +| 14 | ACCEPT. Prerequisite architecture contracts (package/exports/archetype/compiler schema/build seam) named before Stage-I handoff; split into prerequisite cards where needed. | +| 15 | ACCEPT. The five dated evidence extracts get actually fetched + committed under the run (not gitignored tmp); C2 re-research included. | +| 16 | ACCEPT. #349 status-label correction included in reconciliation. | +| 17 | ACCEPT. Handle namespace normalized (UR-0…UR-12 incl. UR-H renamed) once, everywhere. | + +Rework lanes: evidence re-fetch + C2 re-research → resumed Stage-B author thread (its own +corpus gap); pack/plan restructure → Tier-B Opus rework agent under these dispositions; +Stage-E re-lock → supervisor. Then focused Stage-F re-verification (same reviewer session +pattern, detached checkout) before Stage-G. diff --git a/.llm/runs/plan-unified-runtime--seed/design/D1-composition-host/agent-briefs.md b/.llm/runs/plan-unified-runtime--seed/design/D1-composition-host/agent-briefs.md new file mode 100644 index 000000000..369cd35ca --- /dev/null +++ b/.llm/runs/plan-unified-runtime--seed/design/D1-composition-host/agent-briefs.md @@ -0,0 +1,188 @@ +# D1 — Implementation-lane brief skeletons + +One brief per D1 sub-issue draft. These are **skeletons** for the Stage-I handoff — they are filled +with the live issue number once D3's manifest is filed at Stage H. Each brief carries `use harness` ++ a `## SKILL` chapter and the verbatim stop-lines block (an omitted stop-lines section makes a brief +invalid — seed brief rule). + +Routing note: select provider/model/effort per `.llm/harness/workflow/lane-policy.md`; do not hardcode +a model here. Framework source under `packages/` is a WSL Codex daemon-attached slice (CLAUDE.md). + +--- + +## Verbatim stop-lines (the exact block materialized in EVERY brief below) + +``` +## Stop-lines (HARD — read twice) +1. Merge requires CI green + opposite-family eval PASS on the PR. Owner granted standing beta-11 merge authorization (2026-07-17 in-turn) once that bar is met. +2. HARD STOP before any release publish (`release:cut`, JSR publish, tag push, canary or stable) — owner sign-off in-turn only; a stale or relayed approval does not count. +3. HARD STOP before closing milestone 13 — owner sign-off only. +4. These stop-lines are repeated verbatim in EVERY sub-agent brief. A sub-brief without the stop-lines section is invalid. +5. The #824 seed run is drafts-only until owner ratification; its board filing needs the owner in-turn. +``` + +--- + +## Brief D1-1 — Composition root + +**use harness** + +### SKILL +Read: `netscript-harness`, `netscript-doctrine` (composition-root archetype, layering), `netscript-service` +surface via `deno doc @netscript/service`. Frame: design pack `design/D1-composition-host/proposal.md` +§1 and epic #823. + +- **Goal:** single composition-root module wiring service + oRPC + Fresh into one logical graph; the + no-application-loopback invariant holds on every preset. +- **Contract first:** define the mount/prefix/lifecycle registry type before implementation. +- **Files (expected):** new composition-root module in the unified-runtime host package; consumes + `ServiceApp` (`packages/service/src/types.ts:13-20`) and `defineFreshApp()` results. +- **Gates:** G-ROOT (proposal.md §6); `deno task check`, targeted unit test, `gate:e2e` boot. +- **Defers to D2:** the per-preset `process` capability column — do not decide it here. + +## Stop-lines (HARD — read twice) +1. Merge requires CI green + opposite-family eval PASS on the PR. Owner granted standing beta-11 merge authorization (2026-07-17 in-turn) once that bar is met. +2. HARD STOP before any release publish (`release:cut`, JSR publish, tag push, canary or stable) — owner sign-off in-turn only; a stale or relayed approval does not count. +3. HARD STOP before closing milestone 13 — owner sign-off only. +4. These stop-lines are repeated verbatim in EVERY sub-agent brief. A sub-brief without the stop-lines section is invalid. +5. The #824 seed run is drafts-only until owner ratification; its board filing needs the owner in-turn. + +## Brief D1-2 — Nitro host bridge (listener/lifecycle/close) + +**use harness** + +### SKILL +Read: `netscript-harness`, `netscript-doctrine`, `aspire`/`deno-fresh` as applicable, and +`research/nitro-v3.md` Lifecycle row. Frame: proposal.md §2. + +- **Goal:** bind the graph into Nitro as a synchronous plugin; Nitro owns the sole listener + `error` + observation; the `close` hook invokes the **UR-0 hostable-service lifecycle contract** (which + reuses the shipped `ServiceShutdownCoordinator` policy — idempotency, bounded drain, LIFO, + structured report). Do NOT invent a bespoke disposer registry (Stage-F finding 5). +- **Contract first:** consume UR-0's exported build/start/stop surface; async construction resolved + before synchronous plugin registration. +- **Gates:** G-LISTEN, G-CLOSE (proposal.md §6) — include an idempotent double-close test. + +## Stop-lines (HARD — read twice) +1. Merge requires CI green + opposite-family eval PASS on the PR. Owner granted standing beta-11 merge authorization (2026-07-17 in-turn) once that bar is met. +2. HARD STOP before any release publish (`release:cut`, JSR publish, tag push, canary or stable) — owner sign-off in-turn only; a stale or relayed approval does not count. +3. HARD STOP before closing milestone 13 — owner sign-off only. +4. These stop-lines are repeated verbatim in EVERY sub-agent brief. A sub-brief without the stop-lines section is invalid. +5. The #824 seed run is drafts-only until owner ratification; its board filing needs the owner in-turn. + +## Brief D1-3 — Fresh mount + route/static ownership + +**use harness** + +### SKILL +Read: `netscript-harness`, `deno-fresh` (App/handler/islands), `research/orpc-fresh.md` Route/Static +rows. Frame: proposal.md §3. + +- **Goal:** mount Fresh via `app.handler()` (never `listen()`); declare disjoint route spaces and + static-asset ownership; preserve the shipped wrapper middleware/routes intact. +- **Files:** consumes `packages/fresh/src/runtime/server/define-fresh-app.ts` unchanged (no framework + edit unless a `*Namespace` export gap forces a WSL Codex slice). +- **Gates:** G-ROUTE, G-STATIC, no-nested-listen assertion. + +## Stop-lines (HARD — read twice) +1. Merge requires CI green + opposite-family eval PASS on the PR. Owner granted standing beta-11 merge authorization (2026-07-17 in-turn) once that bar is met. +2. HARD STOP before any release publish (`release:cut`, JSR publish, tag push, canary or stable) — owner sign-off in-turn only; a stale or relayed approval does not count. +3. HARD STOP before closing milestone 13 — owner sign-off only. +4. These stop-lines are repeated verbatim in EVERY sub-agent brief. A sub-brief without the stop-lines section is invalid. +5. The #824 seed run is drafts-only until owner ratification; its board filing needs the owner in-turn. + +## Brief D1-4 — In-process oRPC bridge + +**use harness** + +### SKILL +Read: `netscript-harness`, `netscript-doctrine`, service surface via `deno doc`, and +`research/orpc-fresh.md` (composition boundary + bridges) + `research/drift-ledger.md` D-07. Frame: +proposal.md §4. + +- **Goal:** in-process delegation over `ServiceApp.fetch`/oRPC `RPCHandler` — no socket loopback, no + second codec; single canonical prefix into H3 match + `handler.handle`; `toServiceContext` seam + + abort signal; RPC-domain errors as typed responses; streamed + WS-upgrade conformance cases. +- **Reuse, do not reinvent:** `packages/service/src/primitives/handlers.ts:115-143`. +- **Scope boundary:** host-side bridge ONLY — this is a **subset** of #451's public SDK transport + surface. #451 stays **OPEN and KEEP**; this PR carries **NO `Closes #451`**. The SDK↔service + dependency direction (#451 O-1) is decided by fork **F-7** before the separate #451 SDK slice starts. +- **Gates:** G-RPC, G-ERR, G-STREAM (WebSocket-upgrade case per fork F-4). + +## Stop-lines (HARD — read twice) +1. Merge requires CI green + opposite-family eval PASS on the PR. Owner granted standing beta-11 merge authorization (2026-07-17 in-turn) once that bar is met. +2. HARD STOP before any release publish (`release:cut`, JSR publish, tag push, canary or stable) — owner sign-off in-turn only; a stale or relayed approval does not count. +3. HARD STOP before closing milestone 13 — owner sign-off only. +4. These stop-lines are repeated verbatim in EVERY sub-agent brief. A sub-brief without the stop-lines section is invalid. +5. The #824 seed run is drafts-only until owner ratification; its board filing needs the owner in-turn. + +## Brief D1-5 — Version pins + H3-bridge conformance gate + +**use harness** + +### SKILL +Read: `netscript-harness`, `netscript-deno-toolchain` (pins, `deno doc`, catalogs), `.llm/tools/deps` +wrappers, `research/drift-ledger.md` D-11 + `research/nitro-v3.md` board input 1. Frame: proposal.md §5. + +- **Goal:** pin exact Nitro v3 version + compatibility date and oRPC generation; write the H3-bridge + conformance test against the pinned generation; document Nitro upgrade compatibility as a gate. +- **Toolbelt:** decide "latest" via `deno task deps:latest`, never `deno outdated --latest`. +- **Gates:** G-PIN, `gate:e2e` composed build on pinned versions. + +## Stop-lines (HARD — read twice) +1. Merge requires CI green + opposite-family eval PASS on the PR. Owner granted standing beta-11 merge authorization (2026-07-17 in-turn) once that bar is met. +2. HARD STOP before any release publish (`release:cut`, JSR publish, tag push, canary or stable) — owner sign-off in-turn only; a stale or relayed approval does not count. +3. HARD STOP before closing milestone 13 — owner sign-off only. +4. These stop-lines are repeated verbatim in EVERY sub-agent brief. A sub-brief without the stop-lines section is invalid. +5. The #824 seed run is drafts-only until owner ratification; its board filing needs the owner in-turn. + +## Brief UR-0 — Hostable-service lifecycle contract (NEW prerequisite, precedes UR-2) + +**use harness** + +### SKILL +Read: `netscript-harness`, `netscript-doctrine` (service archetype, ports/adapters), +`netscript-deno-toolchain` (`deno doc @netscript/service`). Frame: `design/canonical/UR-0.md` + +proposal.md §2.3–§2.4. + +- **Goal:** export a build/start/stop (or `[Symbol.asyncDispose]`) surface that preserves + `onStartup`/`onShutdown` behavior when a host (Nitro/desktop/tests) drives the service **without** + owning a listener; startup-failure rollback preserved. +- **Reuse, do not reinvent:** wrap the shipped `ServiceShutdownCoordinator` policy + (`packages/service/src/builder/service-shutdown.ts:1-135` — idempotency, bounded drain budget, LIFO + order, structured report). Do NOT invent a second "exactly once" lifecycle. +- **Contract first:** the exported lifecycle surface type; package/export ownership recorded against + UR-11. Framework source under `packages/service` → WSL Codex daemon-attached slice (CLAUDE.md). +- **Gates:** per `design/canonical/UR-0.md` acceptance; scoped `deno check`, unit tests incl. + double-stop idempotency + parity with `serve()` lifecycle. + +## Stop-lines (HARD — read twice) +1. Merge requires CI green + opposite-family eval PASS on the PR. Owner granted standing beta-11 merge authorization (2026-07-17 in-turn) once that bar is met. +2. HARD STOP before any release publish (`release:cut`, JSR publish, tag push, canary or stable) — owner sign-off in-turn only; a stale or relayed approval does not count. +3. HARD STOP before closing milestone 13 — owner sign-off only. +4. These stop-lines are repeated verbatim in EVERY sub-agent brief. A sub-brief without the stop-lines section is invalid. +5. The #824 seed run is drafts-only until owner ratification; its board filing needs the owner in-turn. + +## Brief UR-11 — Architecture contracts (NEW prerequisite, precedes UR-1/UR-4/UR-5) + +**use harness** + +### SKILL +Read: `netscript-harness`, `netscript-doctrine` (archetype selection, layering, public-surface rules +under `docs/architecture/doctrine/`), `netscript-deno-toolchain` (JSR export surface, `deno doc`), +`netscript-pr` (labels/milestones). Frame: `design/canonical/UR-11.md`. + +- **Goal:** name the unified-runtime host package (path/`deno.json`/export map), select the doctrine + archetype(s) + per-package fitness/JSR/E2E gate matrix, define the composition-compiler requirement + schema + build/CLI seam (consumed by UR-5), reconcile the F-7 import direction, and normalize board + + code language to `@netscript/database` (retire `@netscript/data`; facade only if F-8 selects it). +- **Contract first:** this is the architecture-decision card the other lanes consume — settle it + before UR-1/UR-4/UR-5 start. Split any oversized contract into its own prerequisite card. +- **Gates:** per `design/canonical/UR-11.md` acceptance. + +## Stop-lines (HARD — read twice) +1. Merge requires CI green + opposite-family eval PASS on the PR. Owner granted standing beta-11 merge authorization (2026-07-17 in-turn) once that bar is met. +2. HARD STOP before any release publish (`release:cut`, JSR publish, tag push, canary or stable) — owner sign-off in-turn only; a stale or relayed approval does not count. +3. HARD STOP before closing milestone 13 — owner sign-off only. +4. These stop-lines are repeated verbatim in EVERY sub-agent brief. A sub-brief without the stop-lines section is invalid. +5. The #824 seed run is drafts-only until owner ratification; its board filing needs the owner in-turn. diff --git a/.llm/runs/plan-unified-runtime--seed/design/D1-composition-host/epic-and-issues.md b/.llm/runs/plan-unified-runtime--seed/design/D1-composition-host/epic-and-issues.md new file mode 100644 index 000000000..0c7c692c5 --- /dev/null +++ b/.llm/runs/plan-unified-runtime--seed/design/D1-composition-host/epic-and-issues.md @@ -0,0 +1,158 @@ +# D1 — Sub-issue DRAFTS (draft text only — NO GitHub mutation) + +**These are DRAFTS.** Nothing here is filed. No issue is created, labelled, or milestoned until the +owner ratifies the decision brief in-turn at Stage H and the supervisor files once from the manifest +(seed-run.md Stage H). Bodies use `Part of #823` (reference only) and **never** a closing keyword — +epics/umbrellas close by hand (netscript-pr SKILL). + +Milestone suggestions below are resolved by the Stage-F rework to the **one milestone train**: all +UR-0…UR-12 land at `0.0.1-beta.13` (F-9). Live milestones `0.0.1-beta.13`/`0.0.1-beta.14` exist +(verified 2026-07-18 in D3). The old "beta.12 train mapping is an owner fork" note is superseded. + +Common labels for every card below: `type:feat`, `epic:unified-runtime`, `epic:deployment`, exactly +one `status:` (`status:plan` at filing — seed board is pre-impl), a `priority:`, a `wave:`, plus +per-card `area:` and `gate:`. The **authoritative** per-slot label sets are in +`design/canonical/UR-.md`. + +--- + +## D1-1 — Composition root: logical graph identity + no-loopback invariant + +- **Title:** Unified runtime: single logical composition root with no application-created loopback +- **Labels:** `type:feat`, `area:service`, `area:deploy`, `epic:deployment`, `priority:p1`, + `wave:v1` +- **Milestone (suggested):** `0.0.1-beta.13` (one-train, Stage-F F9/F-9) +- **Body:** + > Part of #823 + > + > Establish the composition root as the single module that wires the NetScript service, oRPC + > handler, and Fresh UI into one logical application graph. The universal invariant is **logical + > graph identity — one composition root**; physical single-OS-process execution is a per-preset + > capability (declared by the capability matrix, not here). The invariant that holds on every + > preset is **no application-created loopback**: the graph is wired by in-process Fetch delegation, + > never by opening a socket back to the host's own listener. See design pack + > `.llm/runs/plan-unified-runtime--seed/design/D1-composition-host/proposal.md` §1. + > + > Acceptance gates: + > - [ ] gate: build exposes exactly one composition root (a single mount/prefix/lifecycle registry) + > - [ ] gate: no adapter or bridge opens a loopback HTTP client to the host listener + > - [ ] gate: physical single-process asserted only for presets whose capability cell declares `process: in-process` + > - [ ] gate:e2e composed entry point boots and serves the graph through one root + +## D1-2 — Nitro host bridge: listener + lifecycle + synchronous plugins + single-shot close + +- **Title:** Unified runtime: Nitro owns listener/lifecycle; single-shot `close` disposal registry +- **Labels:** `type:feat`, `area:deploy`, `epic:deployment`, `priority:p1`, `wave:v1` +- **Milestone (suggested):** `0.0.1-beta.13` (one-train, Stage-F F9/F-9) +- **Body:** + > Part of #823 + > + > Bind the composition root into Nitro v3 as a synchronous plugin. **Nitro owns process startup, + > the single listener, top-level `error` observation, and shutdown.** Async adapter construction + > (DB pools, queue connections) happens before plugin registration; resolved handles are closed + > over so registration stays synchronous. Every adapter/worker registers a disposer; the Nitro + > `close` hook drains the registry in reverse construction order, **exactly once**, idempotent + > under double-close. The lifecycle bridge is explicit — do not assume Fresh/Hono middleware order + > matches Nitro's pipeline, and account for Nitro running static files before middleware/routes. + > See proposal.md §2 (evidence: `research/nitro-v3.md` Lifecycle row). + > + > Acceptance gates: + > - [ ] gate: no nested listen — Nitro is the sole listener owner + > - [ ] gate: `close` hook disposes every registered adapter/worker exactly once (idempotent under double-close) + > - [ ] gate: plugin registration is synchronous; async construction resolved beforehand + > - [ ] gate: only host/composition failures (not RPC-domain errors) reach Nitro's `error` hook + +## D1-3 — Fresh mount via `app.handler()`: route + static ownership + +- **Title:** Unified runtime: mount Fresh via `app.handler()` with declared route/static ownership +- **Labels:** `type:feat`, `area:fresh`, `area:deploy`, `epic:deployment`, `priority:p1`, + `wave:v1` +- **Milestone (suggested):** `0.0.1-beta.13` (one-train, Stage-F F9/F-9) +- **Body:** + > Part of #823 + > + > Mount the Fresh UI by calling `defineFreshApp()`'s `app.handler()` as an opaque Fetch delegate — + > **never `app.listen()`**. Preserve the shipped wrapper's middleware ordering and filesystem + > routes intact (`packages/fresh/src/runtime/server/define-fresh-app.ts`). Declare non-overlapping + > route spaces (RPC subtree, health/metadata, Fresh UI, static assets); Fresh is the final UI + > fallback only, mounted after Nitro matches the RPC prefix and health paths — no wildcard above + > the RPC prefix. Declare static-asset ownership per namespace (default: Fresh owns its + > island/`_fresh` assets; Nitro owns host public dir) and verify through the composed entry point. + > See proposal.md §3 (evidence: `research/orpc-fresh.md` Route/Static ownership rows). + > + > Acceptance gates: + > - [ ] gate: Fresh mounted via `app.handler()`; no `app.listen()` anywhere in the graph + > - [ ] gate: RPC / health / Fresh-UI / static route spaces declared disjoint; no catch-all above RPC prefix + > - [ ] gate: Fresh middleware chain reached for its route space through the composed entry point + > - [ ] gate: static-asset ownership declared per namespace; cache headers/fallbacks/error pages verified through composed entry point + +## D1-4 — In-process oRPC bridge over `ServiceApp.fetch` (no loopback, no second codec) + +- **Title:** Unified runtime: in-process oRPC bridge over `ServiceApp.fetch` — context, abort, error semantics +- **Labels:** `type:feat`, `area:service`, `epic:deployment`, `priority:p1`, `wave:v1` +- **Milestone (suggested):** `0.0.1-beta.13` (one-train, Stage-F F9/F-9) +- **Body:** + > Part of #823 + > + > Invoke the service in-process by delegating the Web `Request` into the shipped `ServiceApp.fetch` + > / oRPC `RPCHandler` (`packages/service/src/primitives/handlers.ts:115-143`, + > `packages/service/src/types.ts:13-20`). Transport is **invocation placement over a stable + > Fetch/RPC contract** — "no socket loopback" is the requirement; a second codec is not (supersedes + > the two-codec framing). **Host-side bridge ONLY — a subset of #451's public SDK transport surface; + > #451 stays OPEN/KEEP; this card carries NO `Closes #451` (Stage-F F2; see `design/canonical/UR-4.md`).** + > The host consumes `fetch` and does not reach into the Hono + > implementation. Carry one canonical RPC prefix into both H3 matching and + > `handler.handle(..., { prefix })`; pass request-scoped auth/telemetry context (single + > `toServiceContext` seam) and the abort signal. RPC-domain errors serialize as typed responses and + > do not reach Nitro's `error` hook. Treat ordinary, streamed, and WebSocket-upgrade responses as + > distinct conformance cases (WebSocket is opt-in via CrossWS/H3, not implied). See proposal.md §4. + > + > Acceptance gates: + > - [ ] gate: in-process delegation over `ServiceApp.fetch`/`RPCHandler`; no socket loopback + > - [ ] gate: single canonical prefix carried into H3 match and `handler.handle` + > - [ ] gate: request context (single `toServiceContext` seam) + abort signal carried into handler + > - [ ] gate: RPC match/404 preserved; RPC-domain errors returned as typed responses + > - [ ] gate: ordinary, streamed, and WebSocket-upgrade responses each exercised through composed entry point + +## D1-5 — Version pins + H3-bridge conformance gate (Nitro compat date, oRPC generation) + +- **Title:** Unified runtime: pin Nitro version/compatibility-date + oRPC generation; H3-bridge conformance gate +- **Labels:** `type:feat`, `area:deploy`, `area:service`, `epic:deployment`, `priority:p1`, + `wave:v1`, `gate:e2e` +- **Milestone (suggested):** `0.0.1-beta.13` (one-train, Stage-F F9/F-9) +- **Body:** + > Part of #823 + > + > Both substrates are moving betas. Pin an **exact Nitro v3 version and a compatibility date**, and + > make Nitro upgrade compatibility a board gate — do not describe the runtime as stable + > (`research/nitro-v3.md` board input 1). Pin the implementation lane's **oRPC generation**: the + > repo pins `^1.14.6` (`packages/service/deno.json:10-20`) while the live oRPC H3 docs carry a v2 + > public-beta banner (drift-ledger D-11). Add an **H3-bridge conformance test** asserting the + > mounted adapter's `handle(request, { prefix, context })` contract against the pinned generation, + > so a future v2 adoption is a deliberate, tested migration rather than silent drift. See + > proposal.md §5. + > + > Acceptance gates: + > - [ ] gate: exact Nitro v3 version + compatibility date pinned; upgrade compatibility is a documented gate + > - [ ] gate: oRPC generation pinned; version recorded in the composition-host manifest + > - [ ] gate: H3-bridge conformance test present and green against the pinned oRPC generation + > - [ ] gate:e2e composed runtime builds green on the pinned versions + +--- + +## Draft ID → epic map (for the Stage-H manifest, D3 owns final numbering) + +| Draft | Working title | Feeds | +| --- | --- | --- | +| D1-1 | composition root / no-loopback invariant | epic #823 | +| D1-2 | Nitro host bridge / close registry | epic #823 | +| D1-3 | Fresh mount + route/static ownership | epic #823 | +| D1-4 | in-process oRPC bridge (host-side subset of #451; #451 KEEP, no close) | epic #823 | +| D1-5 | version pins + H3 conformance gate | epic #823 | + +Cross-pack note for D3: D1-4 realizes the **host-side** in-process oRPC bridge, which is a **subset** +of **#451**'s public SDK transport surface — it does **not** fold or close #451. Per Stage-F rework, +#451 stays **OPEN/KEEP** as its own SDK slice; the SDK↔service dependency direction (#451 O-1) is +owner fork **F-7**. The full supersession map (all KEEP, zero filing-time closes) lives in +`design/canonical/slot-map.md` + `design/D3-board-mechanics/filing-manifest.md`. D1 does not file or +close anything. diff --git a/.llm/runs/plan-unified-runtime--seed/design/D1-composition-host/open-questions.md b/.llm/runs/plan-unified-runtime--seed/design/D1-composition-host/open-questions.md new file mode 100644 index 000000000..9a1963d28 --- /dev/null +++ b/.llm/runs/plan-unified-runtime--seed/design/D1-composition-host/open-questions.md @@ -0,0 +1,35 @@ +# D1 — Open questions (owner forks only) + +Only decisions the owner must pick at Stage H. Everything resolvable from the corpus is resolved in +`proposal.md`; those are **not** repeated here. Each fork below is a genuine choice with no +corpus-forced answer. + +1. **Static-asset ownership default.** proposal.md §3.3 proposes the default "Fresh owns its + island/`_fresh` namespace; Nitro owns the host public directory." The corpus establishes that + ownership *must be declared* and cannot be inferred (orpc-fresh.md "Static assets"), but does not + dictate *which* framework owns a shared public namespace. **Owner fork:** ratify the proposed + default, or assign host-level static serving to Nitro wholesale (single asset pipeline) at the + cost of routing Fresh's asset requests through the outer host. + +2. **WebSocket/upgrade scope for v1.** The corpus marks WebSocket as opt-in via CrossWS/H3 and a + distinct conformance case (orpc-fresh.md, nitro-v3.md), but does not say whether the unified + runtime must ship WS-upgrade support in the first cut or defer it behind a capability flag. + **Owner fork:** include WebSocket-upgrade conformance in v1 (`wave:v1`), or defer it to a later + wave with ordinary + streamed responses only in the first cut. + +3. **oRPC v1.14.6 pin vs v2-beta adoption timing.** The corpus mandates pinning the current + generation and adding a conformance gate (drift-ledger D-11), but the *choice of when* to adopt + the live oRPC v2 beta is a roadmap decision, not a corpus fact. **Owner fork:** hold at pinned + `^1.14.6` for the unified-runtime v1 and treat v2 as a separate tracked migration, or authorize a + v2-beta spike inside this epic. + +4. **Milestone train binding for the D1 cards.** *(RESOLVED by Stage-F rework → fork F-9: one + train.)* All UR cards (incl. the D1 cards UR-0…UR-4, UR-10) land at `0.0.1-beta.13`, which exists + live (verified 2026-07-18). No new milestone is created (F-15). The prior "beta.12 vs existing + milestone" fork is withdrawn. + +5. **`@netscript/data` facade vs shipped `@netscript/database`.** D1 normalizes board language to the + shipped `@netscript/database` name (drift-ledger D-12, synthesis §6). If the owner actually wants + a new `@netscript/data` facade, that is a separate contract card — not an assumed rename. + **Owner fork:** confirm the shipped-name normalization, or commission a `@netscript/data` facade + contract card (which would add a dependency for D1-4's context/data seam). diff --git a/.llm/runs/plan-unified-runtime--seed/design/D1-composition-host/proposal.md b/.llm/runs/plan-unified-runtime--seed/design/D1-composition-host/proposal.md new file mode 100644 index 000000000..bb0dda749 --- /dev/null +++ b/.llm/runs/plan-unified-runtime--seed/design/D1-composition-host/proposal.md @@ -0,0 +1,236 @@ +# D1 — Composition-host design pack: proposal + +Topic **D1 composition-host** of seed run `plan-unified-runtime--seed` (issue #824), feeding epic +**#823** core issues. Frame: the ratified Stage-C synthesis +(`../../synthesis.md`) and the Stage-B corpus (`../../research/nitro-v3.md`, +`../../research/orpc-fresh.md`, `../../research/drift-ledger.md`). Every load-bearing claim below +cites a corpus file or a repo path. GitHub wins on conflict after Stage H. + +## 0. Scope + +This pack designs the **composition contract** for the unified runtime: how a Nitro v3 host, the +NetScript service (oRPC over `ServiceApp.fetch`), and a Fresh 2 UI compose into one logical +application graph. It does **not** design the capability/preset matrix (that is D2) or the board +decomposition/milestone train (that is D3). Where D1 needs a capability outcome it names the D2/D3 +seam rather than deciding it. + +## 1. The universal invariant: logical composition root + +**Decision.** The universal invariant of the unified runtime is **logical graph identity — one +composition root** that wires the service, RPC handler, and Fresh UI into a single application +model. Physical one-process (one-OS-process) execution is a **per-preset capability**, not a +universal promise (synthesis §7 verdict 3; drift-ledger D-01, D-02). + +**Rationale.** RFC §3's "earn the graph" default (one process unless a constraint earns an edge) is +preserved as the *default realization*, but Nitro deploy presets can emit a Node server, +provider/serverless output, or clustered execution, so the application cannot assert OS-process +identity across presets (drift-ledger D-01, citing +[Nitro deploy](https://nitro.build/deploy)). Therefore: + +- The **composition root** is a single module that constructs the graph (service builder result + + Fresh app + host bindings) deterministically, regardless of preset. It is the one place a mount + table, prefix map, and lifecycle registry are declared. +- **"No application-created loopback"** is the invariant that survives every preset: the graph is + wired by in-process delegation over the Web Fetch contract, never by the application opening a + socket back to itself (drift-ledger D-02, D-07). +- **Physical single-process** is a capability a preset either advertises or does not. D1 owns the + logical-root contract; **D2 owns the per-preset `process: in-process | provider-managed` + column.** A preset that cannot host the graph in one process still satisfies the invariant if it + preserves logical composition and creates no application loopback (drift-ledger D-02). + +**Acceptance seam.** A conformance test asserts that a built graph exposes exactly one composition +root and that no adapter or bridge opens a loopback HTTP client to the host's own listener. The +physical-process assertion is scoped to presets whose D2 capability cell declares +`process: in-process`. + +## 2. Nitro host integration (listener / lifecycle / plugins / close) + +**Decision.** **Nitro owns process startup, the single listener, top-level error observation, and +shutdown.** The composition root registers the graph *into* Nitro; it never starts its own server +(synthesis §5; drift-ledger D-10; orpc-fresh.md "Proposed composition boundary" step 3). + +### 2.1 Listener ownership + +Exactly **one outer listener per process**, owned by Nitro. Neither the Fresh app nor the service +may call `listen()` / `Deno.serve` (orpc-fresh.md row "Fresh 2": `app.listen()` "starts its own +listener and must not be combined with another server startup"; drift-ledger D-10). Enforced by a +"no nested listen" acceptance test (§6). + +### 2.2 Lifecycle hooks and ordering + +Nitro exposes `request`, `response`, `error`, and `close` hooks; plugin registration is +**synchronous**; **static files run before middleware/routes**; request-hook errors are reported +but do **not** stop the pipeline (nitro-v3.md "Lifecycle" row, citing +[Nitro lifecycle](https://nitro.build/docs/lifecycle), +[Nitro plugins](https://nitro.build/docs/plugins)). Consequences the composition root must encode: + +- **Do not assume Fresh/Hono middleware order matches Nitro's pipeline** — define an explicit + ordering bridge rather than inheriting it (nitro-v3.md "Lifecycle" implication). +- Because static assets run before middleware, **static ownership must be declared** (see §3.3) so + Nitro's public-asset stage does not shadow an RPC or Fresh route. + +### 2.3 The `close` hook = single-shot teardown + +**The Nitro `close` hook is the one place NetScript adapters and background workers are disposed, +and it must dispose each exactly once** (orpc-fresh.md "Lifecycle" bridge row; drift-ledger D-10). +The composition root maintains a **disposal registry**: every adapter/worker constructed during +graph assembly registers a `close`/`[Symbol.asyncDispose]` callback; the Nitro `close` hook drains +the registry in reverse construction order, idempotently. Embedding Fresh must not create its own +listener whose shutdown competes with this hook (orpc-fresh.md, [Fresh App +docs](https://usefresh.dev/docs/concepts/app)). + +**Acceptance seam.** A test drives the Nitro `close` hook and asserts every registered adapter's +disposer ran exactly once (idempotent under a double-close). + +### 2.4 Plugins + +Nitro plugin registration is synchronous (nitro-v3.md "Lifecycle"). The composition root exposes +the graph to Nitro as a plugin (or plugin set) that binds routes at startup and registers the +`close` disposer. Async adapter construction (DB pools, queue connections) is performed *before* +plugin registration and the resolved handles are closed over, so registration itself stays +synchronous. + +## 3. Fresh mount via `app.handler()` + +**Decision.** The composition mounts the Fresh UI by calling **`app.handler()`** (a +Request→Response handler expressly for embedding) and **never `app.listen()`** (orpc-fresh.md rows +"Fresh 2" and "NetScript Fresh wrapper", citing [Fresh App docs](https://usefresh.dev/docs/concepts/app)). + +### 3.1 The shipped wrapper is already embeddable + +`defineFreshApp()` (`packages/fresh/src/runtime/server/define-fresh-app.ts:1-119`) creates a Fresh +`App`, installs state/security/tracing middleware, applies config, and adds filesystem routes; its +test already invokes `app.handler()` with a Web `Request` +(`packages/fresh/src/runtime/server/define-fresh-app.test.ts:55-105`). D1 reuses this wrapper +unchanged. **Its middleware ordering and filesystem routes must remain intact** when embedded +(orpc-fresh.md "NetScript Fresh wrapper" row) — the composition root mounts the handler as an opaque +Fetch delegate and does not reach inside its middleware chain. + +### 3.2 Route ownership + +Declare **non-overlapping** route spaces: RPC subtree, health/metadata, Fresh UI, static assets. +Fresh resolves middleware/routes top-to-bottom while Nitro runs its own public-assets and route +pipeline, so an **implicit catch-all can bypass Fresh middleware or shadow the RPC subtree** +(orpc-fresh.md "Route ownership" bridge row). Rule: **Fresh is mounted as the final application +fallback for the UI route space only, after the RPC prefix and health/metadata paths are matched by +Nitro.** No wildcard is registered above the RPC prefix. + +### 3.3 Static-asset ownership + +Choose per namespace whether Nitro or Fresh owns each asset space, and test cache headers, +fallbacks, and error pages **through the composed entry point** — ownership cannot be inferred from +a shared Fetch type because both frameworks have asset stages, and Nitro's runs first (orpc-fresh.md +"Static assets" bridge row; nitro-v3.md "Lifecycle"). D1 declares the default: **Fresh owns its own +`_fresh`/island asset namespace; Nitro owns any host-level public directory**, and the two +namespaces are declared disjoint in the mount table. + +## 4. In-process oRPC bridge over `ServiceApp.fetch` + +**Decision.** The service is invoked **in-process** by delegating a Web `Request` into the shipped +service Fetch surface and the oRPC Fetch `RPCHandler` — **no socket loopback, and no second codec** +(synthesis §4 verdict; drift-ledger D-07; orpc-fresh.md "Proposed composition boundary" step 1). + +### 4.1 Invocation placement, not a new protocol + +Transport is modeled as **invocation placement over a stable Fetch/RPC contract**, not a switch +between two wire protocols (drift-ledger D-07). The building blocks already exist: + +- `ServiceApp` structurally exposes `fetch(request): Promise` and `request(...)`; + `FetchHandler` exposes `handle(request): Promise` + (`packages/service/src/types.ts:13-20`, `packages/service/src/types.ts:206-212`). +- `createRPCHandler()` already constructs oRPC's Fetch `RPCHandler`, calls + `handler.handle(request, { context })`, returns the response on a match, and emits a 404 otherwise + (`packages/service/src/primitives/handlers.ts:115-143`). +- The service builder returns a **Hono-backed** app, but its public result is the structural + `ServiceApp` Fetch surface, not a Hono/H3 type + (`packages/service/src/builder/service-builder-impl.ts:423-433`, + `packages/service/src/types.ts:13-20`). **This separation is the compatibility asset: the host + consumes `fetch`, it does not reach into Hono** (orpc-fresh.md "Existing request/response seams"). + +### 4.2 Mount contract + +The composition root mounts the NetScript/oRPC `FetchHandler` under the **single canonical RPC +prefix**, carried into both H3 matching and oRPC `handler.handle(..., { prefix })` (orpc-fresh.md +"Prefix and base path" bridge row, citing [oRPC H3 adapter](https://orpc.dev/docs/adapters/h3)). +In-process delegation passes the Web `Request`, request-scoped auth/telemetry **context**, and the +**abort signal** into the handler — matching the live oRPC H3 pattern without a loopback hop +(orpc-fresh.md steps 1–2). This preserves issue #451's invariant (identical Request/Response API +paths, no loopback) without Nitro knowing the Hono implementation (orpc-fresh.md "Proposed +composition boundary"; [issue #451](https://github.com/rickylabs/netscript/issues/451)). + +### 4.3 Context bridge + +Define explicitly how **Nitro/H3 request state becomes NetScript auth, trace, and service +context**. The service handler accepts a `context` factory +(`packages/service/src/primitives/handlers.ts:119-128`); the oRPC H3 example supplies request +context at the adapter call (orpc-fresh.md "Context" bridge row). D1's contract: a single +`toServiceContext(h3Event | request)` adapter produces the context passed to `handler.handle`, and +it is the only translation seam — no per-route context assembly. + +### 4.4 Error semantics + +Preserve oRPC's **match/404 behavior** and decide which failures stay **typed RPC errors** versus +reaching Nitro's top-level `error` hook +(`packages/service/src/primitives/handlers.ts:124-142`; orpc-fresh.md "Error semantics" bridge row). +D1's rule: RPC-domain errors are serialized by the oRPC handler and returned as responses (they do +**not** propagate to Nitro's `error` hook); only host/composition failures (adapter construction, +disposal, unhandled non-RPC throws) reach the Nitro `error` hook. + +### 4.5 Streaming and upgrade paths + +Treat ordinary Fetch responses, streamed responses, and **WebSocket upgrades** as **distinct +conformance cases**. Nitro WebSocket support is opt-in via CrossWS/H3 and is **not implied** by +mounting an ordinary Fetch handler (orpc-fresh.md "Streaming and upgrade paths" row; nitro-v3.md +"WebSocket/SSE" row). D1 requires each case be exercised through the composed entry point; stream +persistence and auth semantics stay **above** the transport (nitro-v3.md "WebSocket/SSE" +implication). + +## 5. Version pins (Nitro compatibility date, oRPC generation) + +**Decision.** The implementation lane pins exact versions and treats upgrades as gated, because both +substrates are moving betas (synthesis §4, §1; drift-ledger D-11; nitro-v3.md board input 1). + +- **Nitro v3** is public beta with intentional breaking changes and a living migration guide; its + output contract uses a **compatibility date** to pin provider behavior (nitro-v3.md "Verdict", + "Cloud deploy presets", citing [v3 beta](https://nitro.build/blog/v3-beta), + [deploy](https://nitro.build/deploy)). **Pin an exact Nitro v3 version and a compatibility date; + make upgrade compatibility a board gate. Do not describe the runtime as stable** (nitro-v3.md + board input 1). +- **oRPC**: the repo pins **`^1.14.6`** while the live oRPC H3 docs carry a **v2 public-beta** + banner (`packages/service/deno.json:10-20`; drift-ledger D-11; orpc-fresh.md "Version + compatibility" row). **Pin the implementation lane's oRPC generation and add an H3-bridge + conformance test; do not plan against an unqualified live beta example.** The conformance gate + asserts the mounted adapter's `handle(request, { prefix, context })` contract against the pinned + generation, so a future v2 adoption is a deliberate, tested migration — not silent drift. + +## 6. Acceptance gates (feed epic #823 issues) + +These are the board-card gates D1 hands to the issue drafts (§ epic-and-issues.md): + +- **G-ROOT** — one logical composition root; no application-created loopback client. Physical + single-process asserted only where D2 declares `process: in-process`. +- **G-LISTEN** — "no nested listen": neither Fresh nor service starts a listener; Nitro owns the + sole listener. +- **G-CLOSE** — Nitro `close` hook disposes every registered adapter/worker exactly once, + idempotent under double-close. +- **G-ROUTE** — RPC / health / Fresh-UI / static route spaces are declared disjoint; no catch-all + above the RPC prefix; Fresh middleware reached for its route space. +- **G-STATIC** — asset ownership declared per namespace; cache headers, fallbacks, error pages + verified through the composed entry point. +- **G-RPC** — in-process delegation over `ServiceApp.fetch` / oRPC `RPCHandler`; no socket loopback; + single canonical prefix into both H3 match and `handler.handle`; context + abort signal carried. +- **G-ERR** — RPC-domain errors return as typed responses; only host failures reach Nitro `error`. +- **G-STREAM** — ordinary, streamed, and WebSocket-upgrade responses each exercised through the + composed entry point. +- **G-PIN** — exact Nitro version + compatibility date pinned; oRPC generation pinned; H3-bridge + conformance test present and green. + +## 7. What D1 explicitly defers + +- Per-preset `process`, `sagas`, KV/queue/database ownership, writer/lock, and offline-sync columns + → **D2 capability matrix** (synthesis §D2; drift-ledger D-03, D-05, D-06, D-08, D-09). +- `@netscript/data` vs shipped `@netscript/database` naming: board language normalizes to the + **shipped** `@netscript/database` name; a `@netscript/data` facade would need its own contract + card (drift-ledger D-12; synthesis §6). D1 uses `@netscript/database` where it references data. +- Epic decomposition, milestone train, supersession of #451/#453/#454/#455/#349 → **D3 + board-mechanics** (synthesis §D3). diff --git a/.llm/runs/plan-unified-runtime--seed/design/D2-capability-matrix/agent-briefs.md b/.llm/runs/plan-unified-runtime--seed/design/D2-capability-matrix/agent-briefs.md new file mode 100644 index 000000000..351638cd3 --- /dev/null +++ b/.llm/runs/plan-unified-runtime--seed/design/D2-capability-matrix/agent-briefs.md @@ -0,0 +1,172 @@ +# D2 — Implementation-lane agent briefs (DRAFT skeletons) + +DRAFT skeletons for the implementation lanes that will execute the D2 issues **after** Stage-H +filing. One brief per draft issue (`D2-S1`…`D2-S7`). Each brief is launched from **GitHub + this +design pack**, not this run's chat history (seed-run Stage-I). Every brief carries `use harness`, a +`## SKILL` chapter, and the **verbatim stop-lines** — a sub-brief without the stop-lines section is +invalid. + +Routing: select provider/model/effort per `.llm/harness/workflow/lane-policy.md`; do not restate +routes here. Implementation slices touching `packages/`/`plugins/` framework source run on the **WSL +Codex** daemon-attached lane (CLAUDE.md workflow policy). Evaluation runs in a **separate +opposite-family session**. + +--- + +## Shared stop-lines (HARD — included verbatim in every brief below) + +``` +## Stop-lines (HARD — read twice) +1. Merge requires CI green + opposite-family eval PASS on the PR. Owner granted standing beta-11 + merge authorization (2026-07-17 in-turn) once that bar is met. +2. HARD STOP before any release publish (`release:cut`, JSR publish, tag push, canary or stable) — + owner sign-off in-turn only; a stale or relayed approval does not count. +3. HARD STOP before closing milestone 13 — owner sign-off only. +4. These stop-lines are repeated verbatim in EVERY sub-agent brief. A sub-brief without the + stop-lines section is invalid. +5. The #824 seed run is drafts-only until owner ratification; its board filing needs the owner + in-turn. +``` + +--- + +## Brief D2-S1 — Preset capability manifest + build-time rejection compiler + +- **use harness.** Issue: `[unified-runtime S?] Preset capability manifest + build-time rejection compiler` (live # from FILING-LOG). +- **## SKILL:** read `netscript-doctrine` (composition root / single-composition-root rule, + `docs/architecture/doctrine/07-composition-and-extension.md`), `netscript-cli` + (scaffold/build surface), `netscript-tools` (scoped check/lint/fmt, gate evidence). Read + `design/D2-capability-matrix/proposal.md` §3–§4 as the contract. +- **Scope:** manifest schema per cell + composition compiler that reads logical-graph requirements + and fails the build on `unsupported`, warns on `partial`. Contract-first: schema → compiler → + tests. +- **Out of scope:** the port adapters themselves (S3), saga proofs (S2), listener/lifecycle bridge + (owned by D1 composition-host). +- **Validation:** scoped `deno check`/`lint`; unit tests for reject/warn/pass paths; do not run the + full `e2e:cli scaffold.runtime` per loop (reserve for eval/merge-readiness). +- **Stop-lines:** + +## Stop-lines (HARD — read twice) +1. Merge requires CI green + opposite-family eval PASS on the PR. Owner granted standing beta-11 merge authorization (2026-07-17 in-turn) once that bar is met. +2. HARD STOP before any release publish (`release:cut`, JSR publish, tag push, canary or stable) — owner sign-off in-turn only; a stale or relayed approval does not count. +3. HARD STOP before closing milestone 13 — owner sign-off only. +4. These stop-lines are repeated verbatim in EVERY sub-agent brief. A sub-brief without the stop-lines section is invalid. +5. The #824 seed run is drafts-only until owner ratification; its board filing needs the owner in-turn. + +## Brief D2-S2 — Per-preset sagas declaration & durability-tier proof + +- **use harness.** Issue: `[unified-runtime S?] Per-preset sagas capability declaration & durability-tier proof`. +- **## SKILL:** `netscript-doctrine` (runtime-state/failure doctrine + `docs/architecture/doctrine/08-runtime-state-failure.md`), `netscript-harness`. Read + `sagas-constraint.md` (full) + `proposal.md` §2.1. +- **Scope:** implement `sagas: supported | externalized | rejected` per cell; wire in-process saga + runtime shutdown to the composition root's `close` ordering (from D1); build-reject in-process + sagas on bounded-window cells absent an externalization target (v1 bounded-window cell = C4; + C2/deno_deploy is WITHDRAWN from v1 — DD-RESEARCH). Never substitute a Nitro task. +- **Out of scope:** manifest/compiler mechanics (S1, consume it); macro-service topology authoring. +- **Validation:** scoped check/lint; saga drain-on-close test; build-reject test on C4 (C2 withdrawn). +- **Stop-lines:** + +## Stop-lines (HARD — read twice) +1. Merge requires CI green + opposite-family eval PASS on the PR. Owner granted standing beta-11 merge authorization (2026-07-17 in-turn) once that bar is met. +2. HARD STOP before any release publish (`release:cut`, JSR publish, tag push, canary or stable) — owner sign-off in-turn only; a stale or relayed approval does not count. +3. HARD STOP before closing milestone 13 — owner sign-off only. +4. These stop-lines are repeated verbatim in EVERY sub-agent brief. A sub-brief without the stop-lines section is invalid. +5. The #824 seed run is drafts-only until owner ratification; its board filing needs the owner in-turn. + +## Brief D2-S3 — KV / queue / database host-binding adapters + +- **use harness.** Issue: `[unified-runtime S?] KV/queue/database Nitro host-bindings behind NetScript ports`. +- **## SKILL:** `netscript-doctrine` (ports/adapters, wrap-don't-reinvent), + `netscript-deno-toolchain` (`deno doc` the shipped `KvStore`/`MessageQueue`/`DatabaseAdapter` + surfaces before touching them). Read `adapter-mapping.md` (full) + `proposal.md` §2.2–§2.4. +- **Scope:** Nitro mounts/db0/tasks as host bindings **behind** `@netscript/kv|queue|database`; + enforce no-leak of unstorage/db0/H3/Hono to app code; keep `ocache` separate from durable KV; use + shipped `@netscript/database` naming. +- **Out of scope:** writer-lock capability (S4), task/schedule clock (S5). +- **Validation:** scoped check/lint; per-cell mapping tests (L/P/U); import-leak guard test. +- **Stop-lines:** + +## Stop-lines (HARD — read twice) +1. Merge requires CI green + opposite-family eval PASS on the PR. Owner granted standing beta-11 merge authorization (2026-07-17 in-turn) once that bar is met. +2. HARD STOP before any release publish (`release:cut`, JSR publish, tag push, canary or stable) — owner sign-off in-turn only; a stale or relayed approval does not count. +3. HARD STOP before closing milestone 13 — owner sign-off only. +4. These stop-lines are repeated verbatim in EVERY sub-agent brief. A sub-brief without the stop-lines section is invalid. +5. The #824 seed run is drafts-only until owner ratification; its board filing needs the owner in-turn. + +## Brief D2-S4 — Writer-ownership & exclusive-lock capability + +- **use harness.** Issue: `[unified-runtime S?] Writer-ownership & exclusive-lock database capability`. +- **## SKILL:** `netscript-doctrine`, `netscript-deno-toolchain` (`deno doc` `DatabaseAdapter`). + Read `drift-ledger.md` D-08 + `proposal.md` §2.5. +- **Scope:** declared exclusive-lock/writer-ownership capability; supported on C1/C3, reject/ + externalize on C4 (C2 withdrawn from v1 — DD-RESEARCH); embedded-Turso default never silently + overrides a topology constraint. +- **Out of scope:** offline sync (S7), general DB adapter wiring (S3). +- **Validation:** scoped check/lint; lock-capability build test per cell. +- **Stop-lines:** + +## Stop-lines (HARD — read twice) +1. Merge requires CI green + opposite-family eval PASS on the PR. Owner granted standing beta-11 merge authorization (2026-07-17 in-turn) once that bar is met. +2. HARD STOP before any release publish (`release:cut`, JSR publish, tag push, canary or stable) — owner sign-off in-turn only; a stale or relayed approval does not count. +3. HARD STOP before closing milestone 13 — owner sign-off only. +4. These stop-lines are repeated verbatim in EVERY sub-agent brief. A sub-brief without the stop-lines section is invalid. +5. The #824 seed run is drafts-only until owner ratification; its board filing needs the owner in-turn. + +## Brief D2-S5 — Task / schedule activation-adapter mapping + +- **use harness.** Issue: `[unified-runtime S?] Task/schedule activation-adapter mapping`. +- **## SKILL:** `netscript-doctrine`, `netscript-cli`. Read `adapter-mapping.md` Cron/One-off/ + Durable-workflow rows + `proposal.md` §2.7. +- **Scope:** Nitro croner/provider-schedule as activation clock into worker+trigger cores; guard + same-name coalescing vs declared concurrency; externalize durable workflow on bounded-window + cells. +- **Out of scope:** saga scheduling internals (S2), queue delivery (S3). +- **Validation:** scoped check/lint; cron-dispatch test per cell; coalescing-diagnostic test. +- **Stop-lines:** + +## Stop-lines (HARD — read twice) +1. Merge requires CI green + opposite-family eval PASS on the PR. Owner granted standing beta-11 merge authorization (2026-07-17 in-turn) once that bar is met. +2. HARD STOP before any release publish (`release:cut`, JSR publish, tag push, canary or stable) — owner sign-off in-turn only; a stale or relayed approval does not count. +3. HARD STOP before closing milestone 13 — owner sign-off only. +4. These stop-lines are repeated verbatim in EVERY sub-agent brief. A sub-brief without the stop-lines section is invalid. +5. The #824 seed run is drafts-only until owner ratification; its board filing needs the owner in-turn. + +## Brief D2-S6 — Three-cell (v1) capability conformance gate suite + +- **use harness.** Issue: `[unified-runtime S?] Three-cell (v1) capability conformance gate suite`. +- **## SKILL:** `netscript-tools` (gate evidence, E2E verdict source), `netscript-cli` + (`e2e:cli`), `codex-wsl-remote` (run Deno/Aspire E2E on native WSL, avoid `/mnt/c` DrvFS). + Read `nitro-v3.md` Board inputs + `proposal.md` §1, §4. +- **Scope:** conformance suite asserting each cell's manifest; Nitro version + compatibility-date + pin + upgrade drift check; the **three** v1 cells (`deno_server`, `node_server`, `cloudflare_module`) + exercised as distinct cells (`deno_deploy` withdrawn → DD-RESEARCH, Stage-F F1). +- **Out of scope:** the manifests themselves (S1); this suite consumes them. +- **Validation:** this IS the gate lane — run `deno task e2e:cli` variants at merge-readiness; native + WSL; report raw exit codes. Do not run the expensive full smoke every implementation loop. +- **Stop-lines:** + +## Stop-lines (HARD — read twice) +1. Merge requires CI green + opposite-family eval PASS on the PR. Owner granted standing beta-11 merge authorization (2026-07-17 in-turn) once that bar is met. +2. HARD STOP before any release publish (`release:cut`, JSR publish, tag push, canary or stable) — owner sign-off in-turn only; a stale or relayed approval does not count. +3. HARD STOP before closing milestone 13 — owner sign-off only. +4. These stop-lines are repeated verbatim in EVERY sub-agent brief. A sub-brief without the stop-lines section is invalid. +5. The #824 seed run is drafts-only until owner ratification; its board filing needs the owner in-turn. + +## Brief D2-S7 (defer) — Offline-sync database-target capability profile + +- **use harness.** Issue: `[unified-runtime S?] Offline-sync database-target capability profile`. +- **## SKILL:** `netscript-doctrine`. Read `drift-ledger.md` D-09 + `proposal.md` §2.6. Track-only + in v1 unless the desktop wave pulls it forward. +- **Scope:** offline sync as a database-target profile flag; cross-reference the D-04 desktop target + adapter; server/edge cells expose `profile`/`n/a` only. +- **Out of scope:** desktop distribution/rollout mechanics (D-04 adapter owns those). +- **Validation:** scoped check/lint; profile-declaration test. +- **Stop-lines:** + +## Stop-lines (HARD — read twice) +1. Merge requires CI green + opposite-family eval PASS on the PR. Owner granted standing beta-11 merge authorization (2026-07-17 in-turn) once that bar is met. +2. HARD STOP before any release publish (`release:cut`, JSR publish, tag push, canary or stable) — owner sign-off in-turn only; a stale or relayed approval does not count. +3. HARD STOP before closing milestone 13 — owner sign-off only. +4. These stop-lines are repeated verbatim in EVERY sub-agent brief. A sub-brief without the stop-lines section is invalid. +5. The #824 seed run is drafts-only until owner ratification; its board filing needs the owner in-turn. diff --git a/.llm/runs/plan-unified-runtime--seed/design/D2-capability-matrix/epic-and-issues.md b/.llm/runs/plan-unified-runtime--seed/design/D2-capability-matrix/epic-and-issues.md new file mode 100644 index 000000000..41c7a0179 --- /dev/null +++ b/.llm/runs/plan-unified-runtime--seed/design/D2-capability-matrix/epic-and-issues.md @@ -0,0 +1,233 @@ +# DRAFT TEXT ONLY — NOT FILED ON GITHUB + +**These are issue DRAFTS for Stage-E lock / Stage-H owner-ratified filing. Nothing here is filed.** +No GitHub mutation occurs from this pack (seed-run Stage-D contract: packs are drafts). Bodies carry +`Part of #823` and **never** a closing keyword (issue bodies and epics never carry `Closes/Fixes/ +Resolves` — `netscript-pr` skill + AGENTS.md). Labels, milestones, and the epic slug below are +**suggestions**; the authoritative epic decomposition, milestone train, and supersession map are +owned by pack **D3 board-mechanics** and finalized at Stage-E. Draft IDs (`D2-S1`…) map to live +issue numbers only in the Stage-H `FILING-LOG.md`. + +Assumed epic: **#823** (unified runtime / Nitro v3). Assumed epic slug for titles: `unified-runtime` +(owner/D3 fork — could be `deployment`; see open-questions Q1). Milestone suggestions follow the RFC +train (beta.12+, synthesis "Milestone anchor") and are owner forks at Stage-E. + +--- + +## D2-S1 — Preset capability manifest + build-time rejection compiler + +**Title:** `[unified-runtime S?] Preset capability manifest + build-time rejection compiler` + +**Body:** + +Part of #823. + +Define the machine-readable **capability manifest** each of the **three** v1 runtime cells ships +(`deno_server`, `node_server`, `cloudflare_module`; `deno_deploy` withdrawn → DD-RESEARCH, Stage-F +F1), and the +**composition compiler** that cross-checks the app's logical graph requirements against the selected +preset's manifest, failing the **build** (never runtime, never a silent downgrade) on an +unsupported combination. + +- Manifest encodes per-capability `lossless | partial | unsupported` + saga declaration + writer / + offline flags (see `design/D2-capability-matrix/proposal.md` §3–§4). +- Compiler reads requirements from the logical composition root (sagas mounted? long-running queue + listener? CAS-dependent trigger/idempotency store? exclusive-lock single-writer DB?). +- `unsupported` → hard build failure with a diagnostic naming capability + cell + externalize path. + `partial` → build warning with the named degraded axis, requiring explicit adapter selection. +- Preserves logical graph identity across all cells (synthesis §3); gates only physical/one-process + guarantees per cell. + +Evidence: `drift-ledger.md` D-06; `sagas-constraint.md` Board consequence 2; `adapter-mapping.md` +KV-atomics + One-off-task rows. + +**Labels:** `type:feat` · `area:cli` · `area:config` · `epic:unified-runtime` · `priority:p1` · +`wave:v1` · `status:triage` + +**Milestone (suggested):** `0.0.1-beta.13` (one-train, Stage-F F9/F-9) + +**Acceptance / gates:** +- [ ] gate: each of the three v1 cells ships a capability manifest matching proposal.md §3. +- [ ] gate: an app mounting a saga runtime under a `deno_deploy`/`cloudflare_module` build **fails + the build** with a diagnostic naming the externalize path (no runtime fallthrough). +- [ ] gate: a `partial` mapping (e.g. polling KV watch) emits a build warning naming the degraded + axis, not a hard fail. +- [ ] gate: no Nitro primitive (unstorage / db0 / Nitro-task / H3 / Hono) is reachable from + application code in any cell. + +--- + +## D2-S2 — Per-preset sagas declaration & durability-tier proof + +**Title:** `[unified-runtime S?] Per-preset sagas capability declaration & durability-tier proof` + +**Body:** + +Part of #823. Supersedes the categorical "Nitro excludes sagas" rule (#327 D1) with a per-preset +declaration. + +Implement `sagas: supported | externalized | rejected` per cell and prove each against duration, +lifecycle, connector, and `SagaDurabilityTier` gates. In-process is allowed **only through the +NetScript saga runtime** (store/transport/outbox/idempotency ports authoritative); "externalized" = +macro-service split of the **same app model**; **never** a downgrade to Nitro tasks. + +- C1 `deno_server`, C3 `node_server` → **supported** (long-lived; shutdown bound to Nitro `close`). +- C2 `deno_deploy`, C4 `cloudflare_module` → **externalized**, else **rejected** at build. + +Evidence: `sagas-constraint.md` Verdict + Board consequence 1–3; `drift-ledger.md` D-05; +`adapter-mapping.md` Saga + Startup/shutdown rows; `proposal.md` §2.1. + +**Labels:** `type:feat` · `area:plugins` · `epic:unified-runtime` · `priority:p1` · `wave:v1` · +`status:triage` + +**Milestone (suggested):** `0.0.1-beta.13` (one-train, Stage-F F9/F-9) + +**Acceptance / gates:** +- [ ] gate: supported cells run the shipped saga runtime in-process and drain on Nitro `close` + (no orphaned transitions). +- [ ] gate: bounded-window cells reject an in-process saga at build unless a macro-service + externalization target is configured. +- [ ] gate: no code path substitutes a Nitro task for a `SagaDefinition` (correlation / transitions + / compensation / retry / idempotency / outbox preserved). + +--- + +## D2-S3 — KV / queue / database host-binding adapters behind NetScript ports + +**Title:** `[unified-runtime S?] KV/queue/database Nitro host-bindings behind NetScript ports` + +**Body:** + +Part of #823. Realize the ownership mappings in `proposal.md` §2.2–§2.4: NetScript `KvStore`, +`MessageQueue`, and `DatabaseAdapter` remain authoritative; Nitro unstorage / db0 / task primitives +are host bindings **behind** the ports, never exposed to application code. Board language uses the +shipped name `@netscript/database` (not `@netscript/data`). + +- KV: map Nitro mounts behind `KvStore`; a CAS-dependent consumer on a non-CAS mount is a build + rejection (S1), not best-effort. Nitro `ocache` is a host HTTP/function cache only — never durable + KV/workflow state. +- Queue: `@netscript/queue` owns delivery/consumer/retry/DLQ; a Nitro task runner may dispatch into + it but not replace it. Long-running `listen` is externalized on bounded-window cells. +- Database: `@netscript/database` owns health/lifecycle/telemetry/transactions; a db0 bridge is + optional and provider-scoped. Durable provider-backed backing required on bounded-window cells; + volatility removed from the definition of "in-process". + +Evidence: `adapter-mapping.md` KV/Queue/SQL/Cache rows + "Adapter boundary"; `drift-ledger.md` +D-03/D-06/D-12; `nitro-v3.md` KV-storage/SQL/Cache rows. + +**Labels:** `type:feat` · `area:kv` · `area:database` · `area:service` · `epic:unified-runtime` · +`priority:p1` · `wave:v1` · `status:triage` + +**Milestone (suggested):** `0.0.1-beta.13` (one-train, Stage-F F9/F-9) + +**Acceptance / gates:** +- [ ] gate: each cell's KV/queue/database mapping matches proposal.md §3 (L/P/U per row). +- [ ] gate: application code imports only `@netscript/kv|queue|database` surfaces — no unstorage / + db0 / Nitro-task symbols leak. +- [ ] gate: Nitro response cache and durable KV are separate surfaces (no conflation test). + +--- + +## D2-S4 — Writer-ownership & exclusive-lock capability (D-08) + +**Title:** `[unified-runtime S?] Writer-ownership & exclusive-lock database capability` + +**Body:** + +Part of #823. Make writer ownership and exclusive-lock compatibility a **declared database +capability**; "default embedded" (single-writer Turso at the root) must not silently override +topology constraints. Long-lived cells (C1/C3) may hold an exclusive lock; bounded-window cells +(C2/C4) mark it `unsupported in-cell` → externalize or build-reject. + +Evidence: `drift-ledger.md` D-08 (+ RFC §3 "locks earn a graph edge"); `proposal.md` §2.5. + +**Labels:** `type:feat` · `area:database` · `epic:unified-runtime` · `priority:p2` · `wave:v1-min` · +`status:triage` + +**Milestone (suggested):** `0.0.1-beta.13` (one-train, Stage-F F9/F-9) + +**Acceptance / gates:** +- [ ] gate: exclusive-lock single-writer requirement builds on C1/C3 and build-rejects (or + externalizes) on C2/C4. +- [ ] gate: embedded-Turso default never activates where a topology constraint forbids it (no + silent override). + +--- + +## D2-S5 — Task / schedule activation-adapter mapping + +**Title:** `[unified-runtime S?] Task/schedule activation-adapter mapping` + +**Body:** + +Part of #823. Bind Nitro as a preset-aware **clock/activation adapter** while worker + trigger cores +keep definition, event record, backfill, retries, dispatch, and durable workflow. Nitro same-name +task coalescing must not silently change a worker's declared concurrency (→ build diagnostic, S1). +Cron is lossless on long-lived cells and partial (provider-native schedule generation, bounded +window) on C2/C4; durable workflow externalizes on bounded-window cells. + +Evidence: `adapter-mapping.md` Cron / One-off-task / Durable-workflow rows; `nitro-v3.md` +Tasks/schedules + Cloudflare rows; `proposal.md` §2.7. + +**Labels:** `type:feat` · `area:plugins` · `epic:unified-runtime` · `priority:p2` · `wave:v1` · +`status:triage` + +**Milestone (suggested):** `0.0.1-beta.13` + +**Acceptance / gates:** +- [ ] gate: cron activation dispatches into NetScript definitions on all three v1 cells per proposal.md + §2.7 (L/P as declared). +- [ ] gate: Nitro same-name coalescing that would alter declared worker concurrency raises a build + diagnostic, not silent acceptance. + +--- + +## D2-S6 — Three-cell (v1) capability conformance gate suite + +**Title:** `[unified-runtime S?] Three-cell (v1) capability conformance gate suite` + +**Body:** + +Part of #823. Author the conformance suite that proves each **v1** cell's manifest against real +behavior — the **three** v1 cells (Stage-F F1): `deno_server` (Node-built + `--unstable` launch, perms +audited), `node_server`, `cloudflare_module`. **`deno_deploy` is WITHDRAWN from v1** (Deno Deploy +Classic/`deployctl` sunset 2026-07-20; no queues on the new platform) and deferred to the +DD-RESEARCH successor card — it makes no v1 claim. Includes the Nitro-version / compatibility-date +pin and an upgrade-conformance gate (beta maturity). + +Evidence: `nitro-v3.md` Board inputs 1–2 + Deno-preset table; `proposal.md` §1, §4. + +**Labels:** `type:test` · `area:cli` · `area:tooling` · `epic:unified-runtime` · `gate:e2e` · +`priority:p1` · `wave:v1` · `status:triage` + +**Milestone (suggested):** `0.0.1-beta.13` + +**Acceptance / gates:** +- [ ] gate: each of the **three** v1 cells' declared L/P/U/saga manifest is asserted by an executed conformance case. +- [ ] gate: an exact Nitro v3 version + compatibility-date is pinned and an upgrade drift check runs. +- [ ] gate: `deno_deploy` produces no v1 capability claim (withdrawn-pending-research; gated behind DD-RESEARCH). + +--- + +## D2-S7 (defer) — Offline-sync database-target capability profile (D-09) + +**Title:** `[unified-runtime S?] Offline-sync database-target capability profile` + +**Body:** + +Part of #823. Model offline sync (e.g. Turso Sync, #455) as a **database-target capability/profile**, +not a unified-runtime invariant and not an assumption on every Nitro preset. Consumed by the D-04 +desktop target adapter; server/edge cells expose it as `profile` / `n/a` only. Track-only in v1 +unless the desktop wave pulls it forward. + +Evidence: `drift-ledger.md` D-09; `nitro-v3.md` SQL-database maturity; `proposal.md` §2.6. + +**Labels:** `type:feat` · `area:database` · `epic:unified-runtime` · `priority:p3` · `wave:defer` · +`status:triage` + +**Milestone (suggested):** `0.0.1-stable` (or `Backlog / Triage` if track-only) + +**Acceptance / gates:** +- [ ] gate: offline sync is declared on the database target, not inherited by every preset. +- [ ] gate: cross-reference to the D-04 desktop adapter recorded (no D2 ownership of desktop + distribution). diff --git a/.llm/runs/plan-unified-runtime--seed/design/D2-capability-matrix/open-questions.md b/.llm/runs/plan-unified-runtime--seed/design/D2-capability-matrix/open-questions.md new file mode 100644 index 000000000..08f18ac2a --- /dev/null +++ b/.llm/runs/plan-unified-runtime--seed/design/D2-capability-matrix/open-questions.md @@ -0,0 +1,41 @@ +# D2 — Open questions (owner forks only) + +Numbered owner forks surfaced by the D2 capability-matrix pack. These are decisions the supervisor +must NOT take silently; they feed the Stage-E owner-fork sweep and the Stage-H decision brief. Not +implementation TODOs — those live in the issue drafts. + +1. **Isolate/serverless representative cell.** The synthesis fixes the fourth cell as "one + isolate/serverless preset"; this pack picks `cloudflare_module` (provider page names it, + recommended, richest hook surface: scheduled/queue/tail/email — `nitro-v3.md` Cloudflare row). + Owner fork: accept `cloudflare_module` as the v1 representative, or substitute another named + isolate preset (e.g. `vercel`, `netlify_edge`, `aws_lambda`)? Choice changes S3/S6 mappings. + +2. **Epic slug + label for #823.** Titles/labels use `unified-runtime` (`epic:unified-runtime`). + The existing taxonomy example is `epic:deployment`. Owner/D3 fork: confirm the epic slug so + `epic-and-issues.md` titles and labels match the filed epic. (D3 board-mechanics owns final + decomposition; D2 defers.) + +3. **Milestone train split.** *(RESOLVED by Stage-F rework → fork F-9: one train.)* All UR-0…UR-12 + land at `0.0.1-beta.13`; deferred cells/impl (DD-RESEARCH, #455 offline-sync impl) split into + separately-milestoned successors at `0.0.1-stable`. The prior beta.12/beta.13 split is withdrawn. + +4. **`deno_deploy` / `cloudflare_module` sagas: default to `externalized` or `rejected`?** Both + bounded-window cells can either auto-externalize to a macro-service (needs a configured target) + or hard-reject at build. Owner fork: is v1 shipping the macro-service externalization path, or + is v1 **reject-only** (externalization deferred to a later wave)? This sizes S2 materially. + +5. **`@netscript/data` facade.** #823 names `@netscript/data`; the shipped surface is + `@netscript/database` (`drift-ledger.md` D-12). D2 normalizes to `@netscript/database`. Owner + fork: confirm no new `@netscript/data` facade is intended for v1 (if it is, it needs its own + contract card, out of D2 scope). + +6. **Offline-sync scheduling (S7).** Modeled as a `wave:defer` database-target profile consumed by + the D-04 desktop adapter. Owner fork: keep offline sync track-only for v1, or pull it into the + beta.13 train alongside the desktop wave? + +7. **(Stage-F F1) v1 cell set — 3-cell vs re-proven `deno_deploy`.** `deno_deploy` (C2) is withdrawn + from v1: the corpus validated Deno Deploy **Classic** + `deployctl`, both sunset **2026-07-20**; + the surviving `deno deploy` platform has a different model and no Deno queues. Owner fork + (**F-2**): ship the **3-cell** v1 (`deno_server`, `node_server`, `cloudflare_module`) with C2 + deferred to the DD-RESEARCH successor card, or gate v1 on re-proving `deno_deploy` on the new + platform first. Default: 3-cell v1; DD-RESEARCH at `0.0.1-stable`. diff --git a/.llm/runs/plan-unified-runtime--seed/design/D2-capability-matrix/proposal.md b/.llm/runs/plan-unified-runtime--seed/design/D2-capability-matrix/proposal.md new file mode 100644 index 000000000..4a1065158 --- /dev/null +++ b/.llm/runs/plan-unified-runtime--seed/design/D2-capability-matrix/proposal.md @@ -0,0 +1,242 @@ +# D2 — Preset × Capability Contract (DRAFT design pack) + +Stage-D design pack for topic **D2 capability-matrix**, seed run `plan-unified-runtime--seed` +(issue #824), feeding epic #823. **This is a DRAFT proposal — no GitHub mutation, no code.** It is +the supervisor's frame (`synthesis.md`) reduced to a concrete preset × capability contract. + +**Authority note:** GitHub wins on conflict after Stage-H filing. Milestone/issue tags below are +Stage-E/owner-fork suggestions, not filings. + +## 0. Frame (from synthesis + corpus) + +- Nitro v3 = **host/output substrate**, not an adapter replacement; NetScript ports remain the + application contracts (synthesis §1; `nitro-v3.md` Verdict + Board input 3; `adapter-mapping.md` + "Adapter boundary"). +- The universal invariant is **logical graph identity** (one composition root); **physical + one-process execution is a per-preset capability**, not a global promise (synthesis §3; + `drift-ledger.md` D-01/D-02 + Supervisor reconciliation). +- "Excludes sagas" is dead as a categorical rule; replaced by a per-preset capability declaration + `sagas: supported | externalized | rejected`, **never task substitution** (synthesis §2; + `sagas-constraint.md` Verdict + Board consequence 1–3; `drift-ledger.md` D-05). +- v1 board plans **three runtime cells** (Stage-F F1): `deno_server`, one Node server preset + (`node_server`), one isolate/serverless preset (`cloudflare_module`). `deno_deploy` is **withdrawn + pending DD-RESEARCH** (see §1 banner) — the original "four cells" framing predates the Deno Deploy + Classic/`deployctl` sunset. + +## 1. The v1 runtime cells + +> **STAGE-F REWORK BANNER (F1).** The v1 cell set is **THREE cells**: `deno_server` (C1), +> `node_server` (C3), `cloudflare_module` (C4). **`deno_deploy` (C2) is WITHDRAWN from the v1 set and +> every C2 claim in this pack is `withdrawn-pending-research`.** The corpus validated Deno Deploy +> **Classic** + `deployctl`, both of which **sunset 2026-07-20**; the surviving platform uses +> `deno deploy`, has a different build/runtime model, and does **not** support Deno queues. No corpus +> artifact proves a Nitro v3 output (or queue/database bindings) on the new platform. C2 is deferred +> to the **DD-RESEARCH** successor card (`design/canonical/DD-RESEARCH.md`, ms `0.0.1-stable`) and may +> re-enter the matrix only after a real new-platform probe passes. New owner fork **F-2**: 3-cell v1 +> vs re-proven C2 later. The C2 rows/columns below are **retained for provenance only** and carry no +> v1 capability claim. + +Each cell is a **capability-matrix column, not a global promise** (synthesis §3). The isolate cell +is fixed to `cloudflare_module` as the representative non-Deno isolate/serverless output because its +provider page names the preset and adds scheduled/queue/tail/email hooks that exercise the hardest +mapping questions (`nitro-v3.md` Cloud deploy presets table, Cloudflare row). *(The Deno-based +isolate/edge case — `deno_deploy` — is WITHDRAWN from v1 per the §1 banner and handled by +DD-RESEARCH; it is not a v1 conformance cell.)* + +| Cell | Nitro preset | Execution model | Long-lived process? | Build caveats | +| --- | --- | --- | --- | --- | +| **C1 deno_server** | `deno_server` | Bare-metal / container, long-lived | Yes | Node-built output; launched `deno run --unstable --allow-net --allow-read --allow-env`; broad perms to audit (`nitro-v3.md` Deno-preset table row 2; `drift-ledger.md` D-04) | +| ~~**C2 deno_deploy**~~ **WITHDRAWN (F1)** | `deno_deploy` | *(pending DD-RESEARCH)* | *n/a* | **Corpus targeted Deno Deploy Classic + `deployctl`, sunset 2026-07-20; new platform lacks Deno queues. All C2 claims withdrawn-pending-research → `design/canonical/DD-RESEARCH.md`** | +| **C3 node_server** | `node_server` (Nitro default) | Long-lived Node process | Yes | Default production output; no `--unstable`; no Deno-KV-native adapter (use Redis/AMQP/PostgreSQL backings) (`nitro-v3.md` Deno-preset table row 4; `adapter-mapping.md` Queue row) | +| **C4 cloudflare_module** | `cloudflare_module` | Provider isolate/serverless, bounded window | No (per-invocation) | Module preset recommended; platform adds scheduled/email/queue/tail/trace hooks (`nitro-v3.md` Cloudflare row) | + +The **long-lived vs bounded-window** axis is the load-bearing distinction: it decides sagas, durable +queue consumers, and exclusive-lock writer ownership per cell (`sagas-constraint.md` Verdict +"preset-conditional"; `nitro-v3.md` Tasks/schedules maturity: "one running invocation per task +name; `waitUntil` runtime-dependent"). + +## 2. Capability declarations per cell + +Mapping vocabulary (`drift-ledger.md` D-06 "lossless/partial/unsupported"): +- **lossless** — NetScript port's shipped guarantees hold unchanged on this cell. +- **partial** — port mounts, but a named guarantee (atomics, long-running consume, held lock) + degrades or must be negotiated; the degraded axis is stated. +- **unsupported (in-cell)** — the guarantee cannot hold in this cell; app requiring it must + externalize (macro-service split) or the build rejects (§4). + +Ownership rule for every row: **NetScript ports are authoritative; Nitro primitives are host +bindings behind them; never expose unstorage / db0 / H3 / Hono / Nitro-tasks to application code** +(`adapter-mapping.md` KV row + "Adapter boundary"; `drift-ledger.md` D-06 disposition). + +### 2.1 Sagas (`supported | externalized | rejected`) + +Rule (verbatim intent from `sagas-constraint.md` Board consequence 1–3): in-process **only through +the NetScript saga runtime** (store/transport/outbox/idempotency ports authoritative); "externalized" += macro-service split of the **same app model**; **never** a downgrade to Nitro tasks. Each preset +proves its declaration against duration, lifecycle, connector, and `SagaDurabilityTier` gates +(`sagas-constraint.md` Verdict "preset-conditional"). + +| Cell | Declaration | Why | Cite | +| --- | --- | --- | --- | +| C1 deno_server | **supported** | Long-lived process holds saga runtime; shutdown bound to Nitro `close` hook | `sagas-constraint.md` Verdict; `adapter-mapping.md` Startup/shutdown row | +| C2 deno_deploy | **externalized** (else **rejected**) | Bounded window + runtime-dependent `waitUntil` cannot guarantee durable transitions/compensation in-cell; route to a macro-service long-lived process, or reject at build if none configured | `sagas-constraint.md` Verdict "preset-conditional"; `nitro-v3.md` Tasks/schedules row | +| C3 node_server | **supported** | Same long-lived model as C1, no `--unstable` | `sagas-constraint.md` Verdict; `nitro-v3.md` deploy overview row | +| C4 cloudflare_module | **externalized** (else **rejected**) | Isolate window; platform queue/scheduled hooks are activation, not saga state/compensation/outbox | `sagas-constraint.md` Board consequence 2; `adapter-mapping.md` Saga row | + +Never-do: replacing saga execution with Nitro tasks discards correlation, persisted transitions, +compensation, retry policy, idempotency, and outbox (`sagas-constraint.md` Verdict ¶2). + +### 2.2 KV ownership mapping (`@netscript/kv` `KvStore` authoritative) + +| Cell | CRUD/TTL/list | Atomics/CAS | Watch/reactivity | Cite | +| --- | --- | --- | --- | --- | +| C1 deno_server | lossless (Deno KV / memory adapters ship) | lossless (Deno KV `atomic` CAS) | lossless→partial (native where driver permits, else polling) | `adapter-mapping.md` KV rows 1–3; `nitro-v3.md` KV/storage row | +| C2 deno_deploy | lossless (Deno KV on Deploy) | lossless (Deno KV atomics) | partial (polling where no native watch) | `adapter-mapping.md` KV atomics row; `nitro-v3.md` KV/storage row | +| C3 node_server | lossless (Redis/memory adapters) | partial→lossless (depends on backing; Redis CAS ok, memory not durable) | partial | `adapter-mapping.md` KV atomics row; `nitro-v3.md` KV/storage maturity | +| C4 cloudflare_module | partial (CF-KV via unstorage: basic CRUD/TTL only) | **unsupported** (unstorage mount gives no NetScript-style CAS) | partial/unsupported | `adapter-mapping.md` KV atomics row ("mounts without CAS cannot back saga/trigger/idempotency state"); `nitro-v3.md` KV/storage: "never infer persistence, atomics, watch… from `useStorage` alone" | + +Consequence: a CAS-dependent consumer (saga/trigger/idempotency state) on a non-CAS mount is a +**build-time rejection** (§4), not a silent best-effort (`adapter-mapping.md` KV atomics row). +Nitro `ocache` response/function cache is a Nitro-native host win and MUST NOT be conflated with +durable KV/workflow state (`adapter-mapping.md` Response/function-cache row; `nitro-v3.md` Cache +row). + +### 2.3 Queue ownership mapping (`@netscript/queue` `MessageQueue` authoritative) + +NetScript is strictly broader than Nitro tasks; a Nitro task runner MAY dispatch into the queue but +CANNOT replace delivery/consumer/retry/DLQ semantics (`adapter-mapping.md` Queue row + Retry/DLQ +row). The load-bearing axis is the **long-running listener** (`MessageQueue.listen`), which needs a +live process. + +| Cell | Enqueue/delayed | Consume (long-running listener) | Retry ledger + DLQ | Cite | +| --- | --- | --- | --- | --- | +| C1 deno_server | lossless | lossless (process hosts `listen`; Deno KV/Redis/AMQP/PostgreSQL + DLQ) | lossless | `adapter-mapping.md` Queue + Retry/DLQ rows | +| C2 deno_deploy | lossless (enqueue) | **externalized** (no long-lived consumer in-isolate) | externalized with the consumer | `adapter-mapping.md` Queue row; `nitro-v3.md` Tasks/schedules maturity | +| C3 node_server | lossless | lossless (Redis/AMQP/PostgreSQL + DLQ) | lossless | `adapter-mapping.md` Queue + Retry/DLQ rows | +| C4 cloudflare_module | partial (CF Queues platform binding behind port) | partial (event-driven consumer via platform hook, not `listen`; ack/nack/retry adapted) | partial (DLQ/attempt-ledger adapted to platform) | `adapter-mapping.md` Queue + Retry/DLQ rows; `nitro-v3.md` Cloudflare row (queue hooks) | + +### 2.4 Database ownership mapping (`@netscript/database` `DatabaseAdapter` authoritative) + +Board language normalizes to the shipped name `@netscript/database`; `@netscript/data` from #823 is +naming drift and, if intended as a new facade, needs its own contract card — out of D2 scope +(`drift-ledger.md` D-12; `adapter-mapping.md` intro ¶). NetScript owns health, lifecycle, telemetry, +Prisma-driver and transaction contracts; a Nitro db0 bridge is optional, provider-scoped, and never +authoritative (`adapter-mapping.md` SQL row; `nitro-v3.md` SQL-database row). + +| Cell | Connect/query + lifecycle | Pool/transaction/health | Backing selection | Cite | +| --- | --- | --- | --- | --- | +| C1 deno_server | lossless | lossless (process holds pool) | provider adapter (Postgres/MSSQL/MySQL) or embedded | `adapter-mapping.md` SQL row | +| C2 deno_deploy | partial (connection-per-invocation) | partial (no long-held pool; use provider-backed / serverless driver) | provider-backed durable required | `nitro-v3.md` SQL-database maturity; `drift-ledger.md` D-03 | +| C3 node_server | lossless | lossless | provider adapter or embedded | `adapter-mapping.md` SQL row | +| C4 cloudflare_module | partial (per-invocation; D1/SQLite host binding) | partial (serverless driver; no long-held pool) | provider-backed durable required | `nitro-v3.md` SQL-database maturity; Cloudflare row | + +**Volatility is removed from the definition of "in-process"**: a single process may still use +durable provider-backed KV/queue/DB; capability + durability policy selects the backing +(`drift-ledger.md` D-03). Nitro storage/DB defaults (volatile memory / dev SQLite) are NOT a preset +guarantee (`nitro-v3.md` Board input 3). + +### 2.5 Writer-ownership / lock capability (D-08) + +Writer ownership and exclusive-lock compatibility are a **declared database capability**; "default +embedded" (single-writer TursoDB at the root) must **not silently override topology constraints** +(`drift-ledger.md` D-08; RFC §3 "exclusive locks / single-writer are constraints that can earn a +graph edge"). + +| Cell | Exclusive-lock single-writer | Embedded-Turso default | Cite | +| --- | --- | --- | --- | +| C1 deno_server | supported (long-lived holder) | allowed where topology permits | `drift-ledger.md` D-08 | +| C2 deno_deploy | **unsupported in-cell** → externalize or reject | not as a hidden default | `drift-ledger.md` D-08; D-01/D-02 | +| C3 node_server | supported (long-lived holder) | allowed where topology permits | `drift-ledger.md` D-08 | +| C4 cloudflare_module | **unsupported in-cell** → externalize or reject | not as a hidden default | `drift-ledger.md` D-08 | + +### 2.6 Offline-sync capability (D-09) + +Offline sync (e.g. Turso Sync from #455) is a **database-target capability/profile, not a +unified-runtime invariant and not an assumption on every Nitro preset** (`drift-ledger.md` D-09; +`sagas-constraint`/`nitro-v3.md`: Nitro DB layer is experimental db0, no documented universal +Turso-Sync/offline replication). + +| Cell | Offline-sync | Note | +| --- | --- | --- | +| C1 deno_server | capability/profile (supported when DB target provides it) | server-side; desktop-embed is the primary consumer (`drift-ledger.md` D-04 desktop adapter) | +| C2 deno_deploy | not applicable (edge server) | profile only | +| C3 node_server | capability/profile | as C1 | +| C4 cloudflare_module | not applicable (edge server) | profile only | + +Offline sync is declared on the **database target**, cross-referenced by the D-04 desktop target +adapter — not owned by D2's runtime cells beyond the capability flag. + +### 2.7 Task / schedule mapping (worker + trigger cores authoritative) + +Nitro is a preset-aware **clock/activation adapter**; NetScript owns definition, event record, +backfill, retries, dispatch, and durable workflow (`adapter-mapping.md` Cron + One-off-task + +Durable-workflow rows). Nitro's same-name coalescing MUST NOT silently change a worker definition's +expected concurrency (`adapter-mapping.md` One-off-task row). + +| Cell | Cron activation | One-off task | Durable workflow | Cite | +| --- | --- | --- | --- | --- | +| C1 deno_server | lossless (croner clock → NetScript dispatch) | lossless (adapter reconciles name/concurrency) | supported (runtime above Nitro) | `adapter-mapping.md` Cron/One-off/Durable-workflow rows | +| C2 deno_deploy | partial (provider-native schedule generation) | partial (bounded window) | externalized | `nitro-v3.md` Tasks/schedules row; `adapter-mapping.md` Durable-workflow row | +| C3 node_server | lossless | lossless | supported | `adapter-mapping.md` Cron/One-off rows | +| C4 cloudflare_module | partial (native CF scheduled hook) | partial (bounded window) | externalized | `nitro-v3.md` Cloudflare row; `adapter-mapping.md` Durable-workflow row | + +## 3. Consolidated matrix (one glance) + +`L`=lossless · `P`=partial · `U`=unsupported-in-cell · saga = declaration. + +> **C2 column = WITHDRAWN (F1), provenance only — no v1 claim.** The v1 matrix is the three columns +> C1/C3/C4; the C2 column below is retained struck-through and must not be filed as a v1 capability. + +| Capability | C1 deno_server | ~~C2 deno_deploy~~ (WITHDRAWN) | C3 node_server | C4 cloudflare_module | +| --- | --- | --- | --- | --- | +| Sagas | supported | externalized/reject | supported | externalized/reject | +| KV CRUD/TTL | L | L | L | P | +| KV atomics/CAS | L | L | P | **U** | +| KV watch | L/P | P | P | P | +| Queue enqueue | L | L | L | P | +| Queue consume (listen) | L | externalized | L | P | +| Queue retry+DLQ | L | externalized | L | P | +| Database lifecycle | L | P | L | P | +| Writer exclusive-lock | L | **U** | L | **U** | +| Offline-sync | profile | n/a | profile | n/a | +| Cron activation | L | P | L | P | +| Durable workflow | L | externalized | L | externalized | + +## 4. Build-time rejection semantics + +**Unsupported combinations fail at BUILD time, never at runtime, and never as a silent downgrade** +(`drift-ledger.md` D-06 "Board cards must state adapter ownership and lossless/partial/unsupported +mappings"; `sagas-constraint.md` Board consequence 2 "reject at build time"). Mechanism: + +1. **Every preset ships a capability manifest** — the machine form of §3 (per-cell L/P/U + saga + declaration + writer/offline flags). +2. **The composition compiler cross-checks declared app requirements against the selected preset's + manifest.** Requirements are read from the logical graph (does the app mount a saga runtime? a + long-running queue listener? a CAS-dependent trigger/idempotency store? an exclusive-lock + single-writer DB?). +3. **On a `U` (or an unmet saga `SagaDurabilityTier`) the build FAILS** with a specific diagnostic + naming: the capability, the offending cell, and the **externalize path** (macro-service split of + the same app model). It must never coalesce to a Nitro task or a volatile mount + (`sagas-constraint.md` Board consequence 1 + 3). +4. **`partial` requires an explicit acknowledgement/adapter selection**, not a hard fail — the + degraded axis (e.g. polling watch, per-invocation DB) is surfaced as a build warning with the + named cost (`adapter-mapping.md` KV watch row "document cost/latency"). +5. **Nitro same-name task coalescing** is treated as a capability mismatch if it would change a + worker's declared concurrency → build diagnostic, not silent acceptance (`adapter-mapping.md` + One-off-task row). + +Rejection is the honest realization of synthesis §3: logical graph identity is preserved for all +the three v1 cells, while physical/one-process guarantees (sagas, held locks, long-running consumers) are +gated per cell rather than globally promised. + +## 5. Cross-pack seams (not owned here) + +- **D1 composition-host** owns the composition root, Nitro listener/lifecycle bridge, Fresh + `app.handler()` mount (no nested `listen()` — `drift-ledger.md` D-10), oRPC in-process bridge + + H3-conformance gate, and the oRPC `^1.14.6` version pin (`drift-ledger.md` D-11; synthesis §4–5). + D2 consumes the composition root and the `close`-ordered shutdown it defines. +- **D3 board-mechanics** owns epic decomposition, milestone train, and the supersession map (#451 + D-07 fold-in, #453 D-08, #454 D-02 re-scope, #455 D-09, #349 close). D2's issue drafts + (`epic-and-issues.md`) are inputs to D3's Stage-E lock, not a competing filing. +- The **D-04 desktop target adapter** consumes D2's offline-sync + writer-ownership capability flags; + D2 does not own desktop distribution/rollout mechanics. diff --git a/.llm/runs/plan-unified-runtime--seed/design/D3-board-mechanics/decision-brief.md b/.llm/runs/plan-unified-runtime--seed/design/D3-board-mechanics/decision-brief.md new file mode 100644 index 000000000..0d0d328e1 --- /dev/null +++ b/.llm/runs/plan-unified-runtime--seed/design/D3-board-mechanics/decision-brief.md @@ -0,0 +1,68 @@ +# Decision brief — owner-fork sweep (unified-runtime seed, all packs) + +> **DRAFT — owner ratifies in-turn at Stage-H.** This is the **fully materialized** consolidated +> sweep of every owner decision across the three Stage-D packs plus the Stage-F rework dispositions. +> No placeholders remain; the fork list is renumbered **once** as **F-1…F-17** and is identical to +> `plan.md`'s fork sweep. Supersession dispositions are **SC-1…SC-6**. No decision is silently taken. +> Approval does not survive compaction — re-surface, never route around. + +## A. Owner forks (F-1…F-17) — pick per fork; default stated + +| F# | Fork | Default | Source | +| --- | --- | --- | --- | +| **F-1** | Isolate/serverless representative cell: `cloudflare_module` vs `vercel`/`netlify_edge`/`aws_lambda` | keep `cloudflare_module` | D2-Q1 | +| **F-2** | v1 cell set: **3-cell** (`deno_server`,`node_server`,`cloudflare_module`) vs re-prove `deno_deploy` on the NEW platform and include it | 3-cell v1; `deno_deploy` → DD-RESEARCH at `0.0.1-stable` | Stage-F F1 | +| **F-3** | Bounded-window sagas in v1: ship `externalized` macro-service path vs reject-only | reject-only v1, externalized v1.1 | D2-Q4 | +| **F-4** | WebSocket/upgrade scope in v1 vs deferred | defer to post-v1 cell proof | D1-Q2 | +| **F-5** | Static-asset ownership: Fresh-owns-islands vs Nitro-owns-all | Fresh-owns-islands | D1-Q1 | +| **F-6** | oRPC generation: hold `^1.14.6` pin vs authorize v2-beta spike | hold pin | D1-Q3 | +| **F-7** | **SDK↔service dependency direction** for the in-process transport: import `type` from `@netscript/service` vs mirror the structural shape (restored **#451 O-1**) | import `type` (reuse shipped structural port) | #451 O-1 (restored, Stage-F F2) | +| **F-8** | `@netscript/database` normalization vs new `@netscript/data` facade card | normalize, no facade | D1-Q5 / D2-Q5 | +| **F-9** | Milestone train: **one train** — all UR-0…UR-12 at `0.0.1-beta.13`; deferred cells/impl split into separately-milestoned successors | as stated | D1-Q4 / D2-Q3 / OF-1 (Stage-F F11) | +| **F-10** | Offline-sync (#455 KEEP; UR-8 profile at beta.13): #455 **impl** milestone `0.0.1-stable` vs `Backlog / Triage` | `0.0.1-stable` | D2-Q6 / OF-5 | +| **F-11** | Epic slug/label: `epic:unified-runtime` vs `epic:deployment` | `unified-runtime` (keep `epic:deployment` too) | D2-Q2 | +| **F-12** | UR-6 granularity: single matrix card w/ per-cell acceptance vs one card per cell | single matrix card | OF-8 | +| **F-13** | `epic:unified-runtime` label-parity PR as a **gated prerequisite** (merged before filing) | yes | OF-7 | +| **F-14** | Desktop consumer boundary: UR-7/UR-10 are **foundations**; #453/#454/#455 KEEP as desktop-realization issues; consumer stays on #830 | boundary holds; KEEP legacy issues | OF-3 (Stage-F F3/F4) | +| **F-15** | Milestone inventory: create no new milestone beyond verifying `0.0.1-stable`/`beta.14` exist | create none | OF-6 | +| **F-16** | #454 non-closing acceptance **addendum** (scope physical single-process to in-process-capable presets) | yes (append, not close) | OF-9 (Stage-F F3) | +| **F-17** | #327 non-closing addendum superseding the D1 saga exclusion + #349 terminal status-label correction | yes to both | Stage-F F13/F16 | + +## B. Supersession dispositions — explicit owner confirmations (SC-1…SC-6) + +All are **KEEP with zero filing-time close**; folds land later via each legacy issue's own downstream +`Closes #N` PR. Owner confirms each (drift ID cited): + +- **SC-1 — #451 KEEP** (D-07). UR-4 is the host-side bridge (a **subset** of #451's SDK transport + surface). #451 stays open as its own SDK slice; **no `Closes #451`** on UR-4. Confirm. +- **SC-2 — #453 KEEP** (D-08). UR-7 is the writer-ownership **capability foundation**; #453's + packaged-desktop relocation/lock realization stays open (desktop consumer on #830). **No + `Closes #453`.** Confirm. +- **SC-3 — #454 KEEP + addendum** (D-02). UR-10 is the realization **foundation**; #454's generated + link-mode switch + packaged data-plane E2E stay open. The only Stage-H edit is the **non-closing + acceptance addendum** (F-16). **No `Closes #454`.** Confirm the addendum is authorized. +- **SC-4 — #455 KEEP** (D-09). UR-8 is the profile/prerequisite contract; #455's Turso Sync engine + + behavioral acceptance stay open. **No `Closes #455`.** Confirm. +- **SC-5 — #349 CONFIRM superseded** (D-01/D-04). Already closed; no reopen/re-close. Correct the + terminal status label (F-17); optional cross-link comment → #823/UR-6. Confirm. +- **SC-6 — #327 KEEP + non-closing addendum** (Stage-F F13). Append the saga-supersession addendum + (drafted in `filing-manifest.md` Step 5) linking UR-5; do **not** close or re-home #327's other + clauses. Confirm. + +## C. Notes + +- Every UR-0…UR-12 body, label set, milestone, and dependency list is materialized in + `design/canonical/UR-.md`; the draft→slot merge transforms are in `design/canonical/slot-map.md`. +- The forks that change an issue **body** (F-3, F-4, F-5, F-7, F-8, F-10) carry an explicit **A/B + delta** inline in the relevant canonical file under `## Fork deltas`, so a selection is filed from + the committed artifact without post-ratification improvisation. If a selection changes acceptance or + dependency structure, re-run adversarial/PLAN-EVAL on the materialized branch before filing. + +## Stop-lines (HARD — read twice) +1. Merge requires CI green + opposite-family eval PASS on the PR. Owner granted standing beta-11 merge authorization (2026-07-17 in-turn) once that bar is met. +2. HARD STOP before any release publish (`release:cut`, JSR publish, tag push, canary or stable) — owner sign-off in-turn only; a stale or relayed approval does not count. +3. HARD STOP before closing milestone 13 — owner sign-off only. +4. These stop-lines are repeated verbatim in EVERY sub-agent brief. A sub-brief without the stop-lines section is invalid. +5. The #824 seed run is drafts-only until owner ratification; its board filing needs the owner in-turn. + +**F-12 branch-B delta (materialized):** per-cell split = UR-6a/b/c via the same Body template (cell substituted, markers slot:UR-6a|b|c); slot-map +3 rows; UR-12 deps update. (Recheck P12.) diff --git a/.llm/runs/plan-unified-runtime--seed/design/D3-board-mechanics/filing-manifest.md b/.llm/runs/plan-unified-runtime--seed/design/D3-board-mechanics/filing-manifest.md new file mode 100644 index 000000000..dda79e91e --- /dev/null +++ b/.llm/runs/plan-unified-runtime--seed/design/D3-board-mechanics/filing-manifest.md @@ -0,0 +1,203 @@ +# D3 — Stage-H filing manifest (resumable transaction) + +> **DRAFT — executes only after owner in-turn ratification of `decision-brief.md`.** Until then this +> is planning text. The #824 seed run is drafts-only; the board (issues, epics, milestones, repo +> labels) is untouchable before Stage-H (`seed-run.md` §Stage H). Filing is a **resumable +> transaction**, not a one-shot: every step is idempotent and re-entrant, so a mid-run failure resumes +> without duplicating issues or half-rewriting legacy bodies. All GitHub ops use the **GitHub MCP** +> tools (`gh` is not on PATH); read ground-truth with direct git/API GETs. + +Canonical issue bodies for **every** slot are the files under `design/canonical/UR-.md` (+ +`DD-RESEARCH.md`); the draft→slot merge transforms are in `design/canonical/slot-map.md`. The filer +publishes each file's `## Body` section verbatim — it does not compose prose, and it never +publishes the planning metadata (label tables, dependency notes, `## Fork deltas`) that surrounds +the body. + +--- + +## Invariants (hold for the whole transaction) + +- **Stable slot marker.** Every canonical body carries an HTML comment + `` (and the `DD-RESEARCH` marker). This marker is the + idempotency key: **search before every create**; if a live issue already contains the exact marker, + that slot is already filed — record its number and skip creation. +- **Immediate per-slot logging.** `FILING-LOG.md` is appended **after each individual slot/legacy + mutation**, before the next one — never after the whole blast radius. The log is the durable + resume cursor. +- **Read-after-write verification.** After every create/edit, re-GET the issue and assert + title + every label + milestone + the slot marker are present. A mismatch STOPs the transaction. +- **Compare-before-edit on legacy bodies.** Every edit to a live issue (#451/#453/#454/#455/#327/#349) + first re-reads the current body and verifies the expected pre-edit substring is present and the + addendum is **not** already present (idempotent). If the body drifted from the snapshot, STOP and + re-surface to the owner. +- **No closing keywords anywhere at filing.** All folds land later via each legacy issue's own + downstream implementation PR (`Closes #N`). Epics never carry a closing keyword. + +--- + +## Step 0 — pre-flight verification (read-only, no mutation) + +1. Re-fetch #823, #830, #451, #453, #454, #455, #349, #327 live; confirm state matches the + `slot-map.md` legacy dispositions (esp. #349 still closed; #451/#453/#454/#455 still open + + `epic:unified-runtime`; #327 still open with its stale D1 saga-exclusion language). If any drifted, + STOP and re-surface to the owner — do not file against a stale snapshot. +2. Confirm **PLAN-EVAL = PASS** is recorded (Stage-G hard stop) and the owner has ratified the + numbered forks **in-turn** in this session (not a relayed/stale approval). +3. Confirm **Step 1's label-parity PR is MERGED** (see gated prerequisite below). If it is not merged, + STOP — filing may not begin. + +## Step 1 — GATED PREREQUISITE: `epic:unified-runtime` label-parity PR + +`epic:unified-runtime` is used on live issues but is **absent from `.github/labels.yml`** (verified +2026-07-18). Filing depends on it, so it is a **separate, completed prerequisite**, not an in-line +step: + +1. Open a one-line PR adding to `.github/labels.yml`: + `epic:unified-runtime` / color `5319e7` / "Unified single-runtime deployment epic (#823)". +2. This PR merges under the **normal gates** — CI green + opposite-family eval PASS (Stop-line 1). + Filing (Steps 2–6) does **not** begin until it is merged. The transaction has **no** step that + proceeds on an unmerged parity PR. +3. Never create a live label absent from the file; never delete an existing label. + +## Step 2 — milestones (verify; create only what is missing; exact title match) + +Verify live milestones first. Expected to already exist (referenced by live issues 2026-07-18): +`0.0.1-beta.11`, `0.0.1-beta.12`, `0.0.1-beta.13`, `0.0.1-beta.14`, `Backlog / Triage`. +`0.0.1-stable` — **verify live**; create only if absent. Title-match is exact, incl. the spacing in +`Backlog / Triage`. No new milestone is invented. Log the verification result to `FILING-LOG.md`. + +## Step 3 — epic #823 reconcile (no recreate, no close) + +#823 already exists (`type:umbrella`, `epic:unified-runtime`, ms `0.0.1-beta.13`). It is edited to add +the sub-issue checklist (UR-0…UR-12 → live numbers) **after** Step 4 creates them, mirroring the #830 +pattern. **No closing keyword on #823.** Compare-before-edit: confirm the checklist placeholder is +present and not already filled. + +## Step 4 — sub-issues (resumable create in DAG order) + +Create in dependency order (below). For **each** slot, run this idempotent per-slot transaction: + +1. **Search-before-create:** query issues for the exact slot marker + ``. If found → record the existing number, go to + step 5 (verify) — do **not** create a duplicate. +2. **Create** with the title from the canonical file's metadata table, and the body = ONLY the + canonical file's `## Body` section (which must contain `Part of #823`, exactly ONE slot marker, + and the `- [ ] gate:` boxes — planning metadata such as the label table, dependency notes, and + `## Fork deltas` is NEVER published). Preflight fails a slot whose `## Body` is missing or whose + marker count ≠ 1. Labels = the **exact label set** from the metadata table (incl. exactly one + `status:` = `status:plan`); milestone from the metadata table. +3. **Read-after-write:** re-GET the created issue; assert title, **every** label (preflight fails if + any requested label is absent from `.github/labels.yml`), the single `status:plan`, the milestone, + and the slot marker are all present. +4. **Append to `FILING-LOG.md` immediately** (handle → live #, title, milestone, labels) before the + next slot. +5. **Retry/conflict rule:** on a transient API failure, re-run step 1 (search-before-create) first — + if the marker now exists the create partially succeeded; adopt that number instead of re-creating. + On a label/milestone mismatch, STOP (do not patch silently) and re-surface. + +DAG create order (Part-of links + dependency edges resolve): + +| Order | Slot | Labels (exact — one `status:`) | Milestone | +| --- | --- | --- | --- | +| 1 | UR-11 | `type:feat` `area:deploy` `area:service` `area:sdk` `area:database` `epic:unified-runtime` `epic:deployment` `priority:p1` `wave:v1` `status:plan` | 0.0.1-beta.13 | +| 2 | UR-0 | `type:feat` `area:service` `epic:unified-runtime` `epic:deployment` `priority:p1` `wave:v1` `status:plan` | 0.0.1-beta.13 | +| 3 | UR-1 | `type:feat` `area:service` `area:deploy` `epic:unified-runtime` `epic:deployment` `priority:p1` `wave:v1` `status:plan` | 0.0.1-beta.13 | +| 4 | UR-2 | `type:feat` `area:deploy` `area:fresh` `epic:unified-runtime` `epic:deployment` `priority:p1` `wave:v1` `status:plan` | 0.0.1-beta.13 | +| 5 | UR-3 | `type:feat` `area:fresh` `area:deploy` `epic:unified-runtime` `epic:deployment` `priority:p1` `wave:v1` `status:plan` | 0.0.1-beta.13 | +| 6 | UR-4 | `type:feat` `area:service` `area:sdk` `gate:jsr` `epic:unified-runtime` `epic:deployment` `priority:p1` `wave:v1` `status:plan` | 0.0.1-beta.13 | +| 7 | UR-5 | `type:feat` `area:cli` `area:config` `area:plugins` `epic:unified-runtime` `epic:deployment` `priority:p1` `wave:v1` `status:plan` | 0.0.1-beta.13 | +| 8 | UR-9 | `type:feat` `area:kv` `area:database` `area:service` `area:deploy` `epic:unified-runtime` `epic:deployment` `priority:p2` `wave:v1` `status:plan` | 0.0.1-beta.13 | +| 9 | UR-7 | `type:feat` `area:database` `epic:unified-runtime` `epic:deployment` `priority:p1` `wave:v1` `status:plan` | 0.0.1-beta.13 | +| 10 | UR-6 | `type:test` `area:cli` `area:tooling` `area:deploy` `gate:e2e` `epic:unified-runtime` `epic:deployment` `priority:p1` `wave:v1` `status:plan` | 0.0.1-beta.13 | +| 11 | UR-10 | `type:feat` `area:deploy` `area:sdk` `epic:unified-runtime` `epic:deployment` `priority:p1` `wave:v1` `status:plan` | 0.0.1-beta.13 | +| 12 | UR-8 | `type:feat` `area:database` `epic:unified-runtime` `epic:deployment` `priority:p3` `wave:v1` `status:plan` | 0.0.1-beta.13 | +| 13 | UR-12 | `type:chore` `area:deploy` `epic:unified-runtime` `epic:deployment` `priority:p1` `wave:v1` `status:plan` | 0.0.1-beta.13 | +| 14 | DD-RESEARCH | `type:chore` `area:deploy` `epic:unified-runtime` `epic:deployment` `priority:p3` `wave:defer` `status:research` | 0.0.1-stable | + +(Every row carries exactly one `status:` label; preflight FAILS before any mutation if a row lacks a +status or names a label absent from `.github/labels.yml`.) + +## Step 5 — reconcile pre-existing issues (KEEP — zero filing-time closes) + +Each mutation is compare-before-edit (verify expected pre-edit body, verify addendum not already +present), read-after-write verified, and logged immediately. **No `close`, no closing keyword.** + +1. **#451** — append `Part of #823`; milestone `Backlog/Triage` → `0.0.1-beta.13`. **KEEP OPEN.** + No fold text — #451's full SDK transport surface is a separate open slice (UR-4 is a subset). +2. **#453** — append `Part of #823` + capability re-scope note (writer-ownership is a declared + capability; desktop realization stays on #830); milestone → `0.0.1-beta.13`. **KEEP OPEN.** +3. **#454** — append `Part of #823` + the **non-closing acceptance addendum** scoping the physical + single-process / zero-loopback guarantee to in-process-capable presets (F-16); milestone → + `0.0.1-beta.13`. **KEEP OPEN.** This addendum is the only content edit on a re-homed issue. +4. **#455** — append `Part of #823` + offline-sync-is-a-profile note; milestone per **F-10** (default + `0.0.1-stable`); keep `priority:p3`. **KEEP OPEN.** +5. **#327** — append the **non-closing addendum** (drafted below) superseding the D1 "excludes sagas / + not-v1 / 3–5 months" language with the per-preset capability rule + link to UR-5. **KEEP OPEN**, + no milestone/label change beyond the addendum. +6. **#349** — already CLOSED. **No reopen/re-close.** Correct the terminal status label (F-17): per + `.github/labels.yml`, a completed closure uses `status:shipped`; a not-planned closure has **no** + status. Classify at owner ratification, then either replace `status:triage` → `status:shipped` or + remove `status:triage`. Optional single cross-link comment → #823/UR-6 tier-3 successor. + +### #327 non-closing addendum (drafted text — appended, not replacing) + +```markdown +--- +**Addendum (unified-runtime seed #824 — non-closing supersession).** The D1 disposition on this issue +("unified mode is a separate track, not v1; ~3–5 months; excludes sagas") is **superseded** for the +saga clause by the unified-runtime capability rule: sagas run **in-process only through the NetScript +saga runtime**, and each deploy preset declares `sagas: supported | externalized | rejected` and +proves it (never Nitro-task substitution). See #823 / UR-5. This addendum does not close #327 and does +not alter #327's other clauses. +``` + +## Step 6 — FILING-LOG.md (append-as-you-go; final shape) + +`FILING-LOG.md` is written incrementally (per Step 4/5). Final shape: + +```markdown +# FILING-LOG — plan-unified-runtime--seed (Stage-H) + +Filed: · Ratified in-turn by owner: · PLAN-EVAL: PASS · Parity PR merged: <#> + +## Epic +- #823 (pre-existing) — body reconciled with UR-0…UR-12 checklist + +## Sub-issues (draft handle → live) +| Handle | Live # | Title | Milestone | Labels | Marker verified | +| --- | --- | --- | --- | --- | --- | +| UR-0 | #___ | … | 0.0.1-beta.13 | … | yes | +| … | … | … | … | … | … | + +## Successor cards +| DD-RESEARCH | #___ | … | 0.0.1-stable | … | yes | + +## Supersession reconciliation (all KEEP — zero closes) +| Issue | Disposition | Action taken | Closes via | +| --- | --- | --- | --- | +| #451 | KEEP → UR-4 subset | Part of #823 + ms beta.13; open | its own SDK-slice PR Closes #451 | +| #453 | KEEP → UR-7 foundation | Part of #823 + re-scope note + ms beta.13; open | #453 realization PR Closes #453 | +| #454 | KEEP → UR-10 foundation | Part of #823 + non-closing addendum (F-16) + ms beta.13; open | #454 realization PR Closes #454 | +| #455 | KEEP → UR-8 foundation | Part of #823 + profile note + ms per F-10; open | #455 impl PR Closes #455 | +| #327 | KEEP + addendum | non-closing saga-supersession addendum + UR-5 link; open | — | +| #349 | CONFIRM superseded | status-label corrected (F-17); cross-link comment | — | + +## Labels / milestones +- epic:unified-runtime parity PR: <#> (MERGED before filing) +- milestones created: +``` + +## Step 7 — authority banners + +Add the "GitHub wins on conflict" authority banner to this run's tag-carrying docs (`proposal.md`, +`synthesis.md`, `plan.md`) rather than retroactively rewriting milestone/issue tags. GitHub is the +single source of truth after Stage-H. + +--- + +## Stop-lines (HARD — read twice) +1. Merge requires CI green + opposite-family eval PASS on the PR. Owner granted standing beta-11 merge authorization (2026-07-17 in-turn) once that bar is met. +2. HARD STOP before any release publish (`release:cut`, JSR publish, tag push, canary or stable) — owner sign-off in-turn only; a stale or relayed approval does not count. +3. HARD STOP before closing milestone 13 — owner sign-off only. +4. These stop-lines are repeated verbatim in EVERY sub-agent brief. A sub-brief without the stop-lines section is invalid. +5. The #824 seed run is drafts-only until owner ratification; its board filing needs the owner in-turn. diff --git a/.llm/runs/plan-unified-runtime--seed/design/D3-board-mechanics/open-questions.md b/.llm/runs/plan-unified-runtime--seed/design/D3-board-mechanics/open-questions.md new file mode 100644 index 000000000..1905c51e5 --- /dev/null +++ b/.llm/runs/plan-unified-runtime--seed/design/D3-board-mechanics/open-questions.md @@ -0,0 +1,34 @@ +# D3 board-mechanics — open questions (owner forks) + +> DRAFT — Stage-D. These are D3's own numbered forks; they are folded into the consolidated sweep +> in `decision-brief.md` §A and resolved at Stage-E/H by the owner in-turn. No fork is silently +> decided; each carries a default the plan-lock will adopt only if the owner does not override. + +1. **OF-1 Milestone anchor.** Marquee UR set at `0.0.1-beta.13` (after PM #510 at beta.12)? Default: yes. +2. **OF-2 Handle namespace.** `UR-` for #823 children instead of the legacy `E-desktop` handles + carried on #451/#453/#454/#455? Default: yes. +3. **OF-3 Desktop boundary.** UR-10 (re-scoped #454) on #823; desktop consumer stays on #830 + (beta.14). D3 does not re-file desktop cards. Confirm? Default: yes. +4. **OF-4 Tier-3 cell placement.** UR-6 isolate/serverless (Vercel/CF/Netlify, old #349 scope) at + beta.13, or deferred to beta.14/stable given the still-`--unstable` preset (D-01/D-04)? Default: + defer to stable; ship deno_server + deno_deploy + Node cell at beta.13. +5. **OF-5 Offline-sync home.** #455/UR-8 at `0.0.1-stable` vs `Backlog / Triage` (p3; D-09 profile)? + Default: `0.0.1-stable`. +6. **OF-6 Milestone inventory.** Create no new milestone; verify `0.0.1-stable` exists live (create + only if absent)? Default: create none beyond a possibly-missing `0.0.1-stable`. +7. **OF-7 Label parity.** File the one-line `.github/labels.yml` parity PR adding `epic:unified-runtime` + (live but not in the file) before Stage-H relies on it? Default: yes, parity PR first. +8. **OF-8 UR-6 granularity.** UR-6 as a single matrix issue with per-cell acceptance (D3 default), + or one issue per runtime cell (four cards)? Default: single matrix issue — keeps the "one deploy + output" story to one acceptance surface. (Escalate to D2 if it prefers per-cell cards.) +9. **OF-9 #454 body edit authorization.** The re-scope (D-02) is the only Stage-H **content edit** + on a re-homed issue (all others are label/milestone/`Part of` only). Explicit owner OK to edit + #454's acceptance text at filing? Default: yes (edit, not close). + +## Cross-pack dependency notes (not forks — for Stage-E integration) + +- D3's DAG assumes D1 owns UR-1…UR-4/UR-10 text and D2 owns UR-5…UR-10 text. If either pack renames + or splits a slot, Stage-E must re-map the slot table before filing. +- The legacy live dependency chain (#451→#454, #453→#454, #454→#455) is preserved as + UR-4→UR-10, UR-7→UR-10, UR-10→UR-8; if D1/D2 propose a different ordering, the fold wiring in the + supersession map must be revisited. diff --git a/.llm/runs/plan-unified-runtime--seed/design/D3-board-mechanics/proposal.md b/.llm/runs/plan-unified-runtime--seed/design/D3-board-mechanics/proposal.md new file mode 100644 index 000000000..2a2fe2c2d --- /dev/null +++ b/.llm/runs/plan-unified-runtime--seed/design/D3-board-mechanics/proposal.md @@ -0,0 +1,177 @@ +# D3 — Board mechanics: epic decomposition, milestone train, supersession map + +> **DRAFT — no GitHub mutation.** This pack is Stage-D design text only. Nothing here files, +> edits, labels, milestones, or closes any issue. Board mutation happens once at Stage-H, from the +> committed `filing-manifest.md`, and only after the owner ratifies the decision brief in-turn +> (`seed-run.md` §Stage H). Issue drafts follow `netscript-pr`: colon taxonomy, `Part of #` +> in bodies, **never** a closing keyword in an issue body or on an epic. + +> **STAGE-F REWORK BANNER (authoritative pointers).** After the Stage-F adversarial pass, the +> canonical, machine-fileable artifacts are `design/canonical/UR-.md` (one body per slot), +> `design/canonical/slot-map.md` (draft→slot merge transforms), and `filing-manifest.md` (resumable +> transaction). Where this proposal's prose disagrees with those, **they win.** Key rework deltas +> reflected below: (a) handle namespace normalized to **UR-0…UR-12** (UR-H → UR-12; new UR-0 lifecycle +> + UR-11 architecture-contracts prerequisites); (b) **all** legacy dispositions are **KEEP with zero +> filing-time closes** — #451/#453/#454/#455 stay open, folds land via each issue's own downstream +> `Closes #N`; (c) v1 is a **3-cell** matrix (`deno_server`,`node_server`,`cloudflare_module`) — +> `deno_deploy` withdrawn to DD-RESEARCH; (d) **one milestone train** — all UR at `0.0.1-beta.13`, +> deferred cells/impl split into separately-milestoned successors; (e) **#327** added to the +> reconciliation map with a non-closing saga-supersession addendum; (f) **#349** terminal status-label +> corrected. + +Supervisor: Fable 5 beta-11 orchestrator, seed run `plan-unified-runtime--seed` (#824). This pack +consumes `synthesis.md` (accepted Stage-B verdicts + drift dispositions D-01…D-12) and the live +issue bodies of #451/#453/#454/#455/#349/#823/#830 (fetched read-only 2026-07-18). GitHub wins on +conflict after Stage-H. + +--- + +## 1. Scope boundary between the three packs + +D3 owns the **board skeleton**, not the contract text: + +- **D1 `composition-host`** authors the issue drafts for the composition spine (logical root, Nitro + host integration, Fresh mount, oRPC in-process bridge). D3 assigns those drafts to slots + **UR-1…UR-4** and places them in the milestone train + DAG. +- **D2 `capability-matrix`** authors the issue drafts for the preset × capability contract + (sagas rule, KV/queue/cache/database ownership, writer/lock, offline-sync, task/schedule + mapping, build-time rejection). D3 assigns those to slots **UR-5…UR-10** and places them. +- **D3 `board-mechanics`** (this pack) owns: the epic sub-issue **slot table + handle namespace**, + the **milestone train**, the **cross-pack dependency DAG**, and the **supersession map** for the + five re-homed/superseded issues. Where D1/D2 have not yet published their drafts, D3 defines the + slot and its acceptance intent; the pack fills the body. + +Handle namespace for epic #823 children: **`UR-`** (unified-runtime). This deliberately does not +reuse the old `E-desktop` handles (`#E1`/`#E3`/`#E4`/`#E5`) carried in the live #451/#453/#454/#455 +bodies — those handles belong to the superseded desktop pack and are remapped in §5. + +--- + +## 2. Epic decomposition — sub-issue slot table + +Epic **#823** (`type:umbrella`, `epic:unified-runtime`, `wave:v1`, `priority:p1`, milestone +`0.0.1-beta.13`). Children are real sub-issues carrying `epic:unified-runtime` + `Part of #823`. + +Namespace normalized to **UR-0…UR-12** (Stage-F F17). Canonical bodies: `design/canonical/UR-.md`. + +| Slot | Title intent | Pack | Legacy (all KEEP) | Drift | Milestone | +| --- | --- | --- | --- | --- | --- | +| **UR-0** | **Hostable-service lifecycle contract** — exported build/start/stop preserving startup/shutdown, reusing `ServiceShutdownCoordinator` (NEW, F5) | D1 | — | — | beta.13 | +| **UR-1** | Logical composition root + composition-modes contract (one root; logical graph identity is the universal invariant) | D1 | — | D-01 | beta.13 | +| **UR-2** | Nitro v3 host integration — Nitro owns listener/lifecycle/plugins/graceful-close (drains via UR-0) | D1 | — | D-04, D-10 | beta.13 | +| **UR-3** | Fresh mount via `app.handler()` — route/static ownership + **no-nested-`listen()`** acceptance tests | D1 | — | D-10 | beta.13 | +| **UR-4** | oRPC in-process **host bridge** over `ServiceApp.fetch`, no second codec; H3-bridge conformance gate; oRPC generation pin | D1 | **#451 KEEP** (subset; no close) | D-07, D-11 | beta.13 | +| **UR-5** | Preset × capability contract framework + **build-time rejection**; `sagas: supported\|externalized\|rejected` declared + proven per preset | D2 | — | D-05 | beta.13 | +| **UR-6** | Runtime-cell columns: **3 v1 cells** (`deno_server`, `node_server`, `cloudflare_module`) — each a matrix column, not a global promise; `deno_deploy` withdrawn → DD-RESEARCH | D2 | — | D-01, D-04 | beta.13 | +| **UR-7** | Database **writer-ownership + lock-compatibility** as a declared capability (default-embedded must not silently override topology) | D2 | **#453 KEEP** (no close) | D-08 | beta.13 | +| **UR-8** | Offline-sync as a database-target **capability/profile** (Turso Sync), not a runtime invariant | D2 | **#455 KEEP** (no close) | D-09 | beta.13 | +| **UR-9** | KV/queue/cache ownership + durability policy — remove volatility from the meaning of "in-process"; shipped `@netscript` ports remain the contracts | D2 | — | D-03, D-06 | beta.13 | +| **UR-10** | Single-process **realization** capability + acceptance — physical one-process guarantee scoped to in-process-capable presets | D1+D2 | **#454 KEEP + addendum** (no close) | D-02 | beta.13 | +| **UR-11** | **Architecture contracts** — package/export ownership, archetype, compiler requirement schema + build seam; absorbs `@netscript/database` naming normalization (NEW, F14) | D3 | — | D-12 | beta.13 | +| **UR-12** | Epic acceptance + reconciliation card (was **UR-H**; 3-cell matrix green; supersession reconciliation incl. #327/#349 closed out) | D3 | — | — | beta.13 | +| *DD-RESEARCH* | *(successor, NOT a UR slot)* new-platform Deno Deploy probe; re-proves withdrawn `deno_deploy` | D2 | — | D-01 | stable | + +UR-6 is deliberately one **matrix issue with per-cell acceptance**, not one-per-cell, so the "one +deploy output across cells" story has a single acceptance surface (OF-8/F-12). The **3-cell** v1 set +reflects Stage-F F1 (`deno_deploy` withdrawn); the re-proof lives in the DD-RESEARCH successor (F-2). + +--- + +## 3. Milestone train + +Live anchors (verified from issue milestones, 2026-07-18): the release train runs +`beta.11` (this seed) → `beta.12` (PM #510) → `beta.13` (#823 unified marquee) → +`beta.14` (#830 desktop). `#823` is live at **`0.0.1-beta.13`**; `#830` at `0.0.1-beta.14`. + +**One train (Stage-F F11/F-9):** all UR-0…UR-12 land at `0.0.1-beta.13`. A GitHub issue has one +milestone and one completion state, so deferred **cells/impl** are split into separately-milestoned +**successor** cards — never a single card partly closing across milestones. + +| Band | Milestone | Contents | Rationale | +| --- | --- | --- | --- | +| Seed | `0.0.1-beta.11` | #824 (this run) — planning only | seed produces the board, ships no code | +| Foundation (consumed, not filed here) | `0.0.1-beta.12` | PM #510; packaging/install/update substrate #456/#457; `.NET Aspire` packaging #825 | #823 body: "implementation marquee **after** PM (#510) ships beta.12"; desktop consumes both | +| **Marquee (whole UR set)** | `0.0.1-beta.13` | **UR-0…UR-12** — incl. UR-6's **three** v1 cells (`deno_server`, `node_server`, `cloudflare_module`) | one consistent train; delivers the "one deploy output" story on the proven presets | +| Deferred cell (successor card) | `0.0.1-stable` | **DD-RESEARCH** — re-prove `deno_deploy` on the new platform (Deno Deploy Classic/`deployctl` sunset) | not a UR slot; gates `deno_deploy` re-entry (F-2). Replaces the old tier-3 defer row | +| Deferred capability (successor issue) | `0.0.1-stable` (or `Backlog / Triage`) | **#455** offline-sync **implementation** (KEEP, downstream of UR-8) | UR-8 profile contract ships beta.13; the Turso Sync engine stays #455 (F-10) | + +The desktop in-process **consumer** of UR-10 lives on epic **#830** (beta.14), not on #823 — #830 +already carries its own SD-1…SD-H children (#831–#839). D3 does not re-file desktop cards; it only +ensures UR-10's re-scope (#454) is worded so #830 can consume it (OF-3). + +--- + +## 4. Cross-pack dependency DAG + +``` + FOUNDATION (beta.12, external — consumed, not filed here) + PM #510 ──┐ + #456/#457 packaging ──┐ + #825 Aspire packaging ─┤ + │ + PREREQS + UR-11 architecture contracts ──► (UR-1, UR-4, UR-5) + UR-0 hostable-service lifecycle ──► UR-2 + SPINE (D1) ▼ + UR-1 logical root ──┬──► UR-2 Nitro host ──► UR-3 Fresh mount + │ │ + └──► UR-4 oRPC host bridge ◄─┘ (#451 KEEP: UR-4 is a subset, no close) + │ + MATRIX (D2) │ + UR-1 ──► UR-5 preset×capability framework + ├──► UR-6 runtime cells (deno_server, node_server, cloudflare_module; deno_deploy→DD-RESEARCH) + ├──► UR-7 writer/lock capability (#453 KEEP, no close) + ├──► UR-9 KV/queue/cache + durability + └──► UR-8 offline-sync profile ◄── UR-10 (#455 KEEP, no close) + UR-4 + UR-7 ──► UR-10 single-process realization (#454 KEEP + addendum, no close) + ACCEPTANCE + UR-6 + UR-10 + supersession reconciliation ──► UR-12 epic acceptance (was UR-H) +``` + +The legacy dependency chain in the live bodies (`#451→#454`, `#453→#454`, `#454→#455`) maps onto the +UR **dependency** edges `UR-4→UR-10`, `UR-7→UR-10`, `UR-10→UR-8`. These are prerequisite edges, not +folds: each legacy issue stays open and closes via its own downstream `Closes #N`. (Board-language +normalization to `@netscript/database` is absorbed into UR-11 architecture contracts.) + +Cross-run edges: +- **vs D1**: UR-1…UR-4, UR-10 (shared) — D1 owns the contract text; D3 owns their slot + milestone. +- **vs D2**: UR-5…UR-10 — D2 owns the capability text; D3 owns their slot + milestone + the fold + wiring for #453/#455. + +--- + +## 5. Supersession map + +Disposition is **KEEP with zero filing-time closes** (Stage-F rework F2–F4/F13): every re-homed issue +stays open, carries `Part of #823`, and is closed only when its **own** downstream implementation PR +carries a closing keyword (`Closes #N`) — never at filing, never on an epic (`netscript-pr` +close-gate). A UR foundation card is NOT the close-home for the legacy issue; it is a prerequisite the +legacy issue depends on. Each disposition cites its drift ID. **Authoritative bodies + the exact +mutation list live in `filing-manifest.md` Step 5 and `design/canonical/slot-map.md`.** + +| Issue | Live state (2026-07-18) | Disposition | Drift | Stage-H action (no close at filing) | +| --- | --- | --- | --- | --- | +| **#451** in-process link-mode / SDK transport | open; `epic:unified-runtime`+`epic:deployment`; ms `Backlog/Triage` | **KEEP** (UR-4 is a host-side **subset**) | **D-07** | KEEP OPEN. Add `Part of #823`; ms `0.0.1-beta.13`. UR-4 realizes only the host bridge; #451's full SDK transport surface (transport registry, `createInProcessClientLink`, HTTP parity, W3C propagation, JSR gates, **O-1**/F-7) remains its own open SDK slice. **No `Closes #451` on UR-4.** | +| **#453** tursodb single-writer relocation | open; same labels; ms `Backlog/Triage` | **KEEP** (UR-7 = capability foundation) | **D-08** | KEEP OPEN. Add `Part of #823` + capability re-scope note; ms `0.0.1-beta.13`. Packaged-desktop relocation/lock realization stays open (desktop consumer on #830). **No `Closes #453`.** | +| **#454** true single-process mode | open; same labels; ms `Backlog/Triage` | **KEEP + non-closing addendum** (UR-10 = realization foundation) | **D-02** | KEEP OPEN. Append `Part of #823` + the **non-closing acceptance addendum** scoping physical single-process/zero-loopback to in-process-capable presets (F-16). ms `0.0.1-beta.13`. The generated link-mode switch + packaged data-plane E2E stay open. **No `Closes #454`.** | +| **#455** offline-first via Turso Sync | open; `priority:p3`; ms `Backlog/Triage` | **KEEP** (UR-8 = profile contract) | **D-09** | KEEP OPEN. Add `Part of #823` + profile note; keep `priority:p3`; ms `0.0.1-stable` (F-10 default) or `Backlog/Triage`. The Turso Sync engine + behavioral acceptance stay open. **No `Closes #455`.** | +| **#327** deployment umbrella (D1 saga exclusion) | **open**; parent umbrella | **KEEP + non-closing addendum** (F-17) | **D-05** | KEEP OPEN. Append the non-closing saga-supersession addendum (`filing-manifest.md` Step 5) superseding the D1 "excludes sagas / not-v1 / 3–5 months" language with the per-preset capability rule + UR-5 link. No other clause touched; no close. | +| **#349** RFC-14 WATCH (tier-3 serverless) | **already CLOSED**; `status:triage`; ms `Backlog/Triage` | **CONFIRM superseded + status-label fix** (F-17) | **D-01, D-04** | NO reopen/re-close. **Correct the terminal status label**: completed→`status:shipped` or not-planned→no status (classify at ratification); `status:triage` on a closed issue is invalid per `.github/labels.yml`. Optional cross-link comment → #823 + UR-6 successor (DD-RESEARCH). | + +Re-labeling note: #451/#453/#454/#455 already carry `epic:unified-runtime` (re-homed pre-seed), so +Stage-H does **not** add the epic label — it adds `Part of #823` body text, corrects the milestone, +and (for #454 only) appends the non-closing addendum. Do not strip `epic:deployment` — they remain +children of the #327 deployment umbrella as well. + +--- + +## 6. What D3 explicitly does NOT decide (handed to owner forks / other packs) + +- The exact contract text of UR-0…UR-10 (D1/D2 own it; canonical bodies in `design/canonical/`). +- Whether v1 stays 3-cell or re-proves `deno_deploy` via DD-RESEARCH (F-2). +- Whether #455 offline-sync **impl** sits at `0.0.1-stable` vs `Backlog / Triage` (F-10). +- Whether a new `0.0.1-stable`-adjacent milestone is needed, or the existing three betas + + `0.0.1-stable` + `Backlog / Triage` suffice (see `filing-manifest.md` §milestones; OF-6). + +See `open-questions.md` for the numbered D3 forks and `decision-brief.md` for the consolidated +owner sweep across all three packs. diff --git a/.llm/runs/plan-unified-runtime--seed/design/canonical/DD-RESEARCH.md b/.llm/runs/plan-unified-runtime--seed/design/canonical/DD-RESEARCH.md new file mode 100644 index 000000000..cf1b71512 --- /dev/null +++ b/.llm/runs/plan-unified-runtime--seed/design/canonical/DD-RESEARCH.md @@ -0,0 +1,46 @@ + + +# DD-RESEARCH — New-platform Deno Deploy Nitro probe (successor to withdrawn `deno_deploy` cell) + +- **Slot:** DD-RESEARCH (successor / deferred — NOT a UR slot, NOT a v1 capability cell) +- **Owning pack:** D2 capability-matrix (Stage-F F1 disposition) +- **Labels:** `type:chore`, `area:deploy`, `epic:unified-runtime`, `epic:deployment`, `priority:p3`, `wave:defer`, `status:research` +- **Milestone:** `0.0.1-stable` +- **Depends on:** UR-6 (three-cell v1 suite as the conformance harness) +- **Blocks:** re-entry of `deno_deploy` into the matrix (F-2 branch B) + +## Body + +> Part of #823 +> +> +> +> **Research card, not a capability cell.** The seed corpus validated Deno Deploy **Classic** and its +> `deployctl` flow — both sunset **2026-07-20**. The surviving Deno Deploy uses `deno deploy` with a +> different build/runtime model and does **not** support Deno queues. `deno_deploy` was therefore +> **withdrawn** from the v1 cell set (UR-6). This card holds the work required before it can re-enter: +> +> - Execute a real Nitro v3 **build + deploy + conformance probe** on the **new** Deno Deploy +> (`deno deploy`, not `deployctl`). +> - Select and prove any **external queue/database bindings** the new platform requires (Deno queues +> are unavailable; a durable provider-backed queue/DB must be chosen and validated). +> - Re-write the `deno_deploy` capability column (sagas, KV atomics, queue consume, database +> lifecycle, writer-lock, cron/durable-workflow) against the **proven** new-platform behavior, with +> dated, reproducible evidence. +> +> Only after this card passes may `deno_deploy` re-enter UR-6 as a fourth conformance cell (**F-2** +> branch B). Until then it makes **no** v1 capability claim. +> +> Evidence: Stage-F finding F1 (Deno Deploy Classic/`deployctl` sunset; new platform lacks queues). + +## Acceptance / gates + +- [ ] gate: a Nitro v3 output builds and deploys on the new Deno Deploy (`deno deploy`) with dated reproducible evidence +- [ ] gate: an external durable queue + database binding is selected and proven (no reliance on unavailable Deno queues) +- [ ] gate: the `deno_deploy` capability column is rewritten against proven new-platform behavior +- [ ] gate: re-entry into UR-6 gated on this card (no v1 claim before it passes) + +## Fork deltas + +Governed by **F-2** (3-cell v1 vs re-proven `deno_deploy`). Default keeps this card deferred at +`0.0.1-stable`. diff --git a/.llm/runs/plan-unified-runtime--seed/design/canonical/UR-0.md b/.llm/runs/plan-unified-runtime--seed/design/canonical/UR-0.md new file mode 100644 index 000000000..d4baa5e91 --- /dev/null +++ b/.llm/runs/plan-unified-runtime--seed/design/canonical/UR-0.md @@ -0,0 +1,68 @@ + + +# UR-0 — Hostable-service lifecycle contract (exported build/start/stop preserving startup/shutdown) + +- **Slot:** UR-0 (prerequisite — precedes UR-2) +- **Owning pack:** D1 composition-host (new prerequisite, Stage-F F5) +- **Labels:** `type:feat`, `area:service`, `epic:unified-runtime`, `epic:deployment`, `priority:p1`, `wave:v1`, `status:plan` +- **Milestone:** `0.0.1-beta.13` +- **Depends on:** — (foundation; UR-2 depends on UR-0) +- **Blocks:** UR-2 (Nitro host integration), UR-5/UR-6 saga drain wiring + +## Body + +> Part of #823 +> +> +> +> **Prerequisite for the Nitro host bridge (UR-2).** Today `ServiceBuilderImpl.build()` returns +> only the `ServiceApp` and neither runs nor exposes the builder's lifecycle hooks +> (`packages/service/src/builder/service-builder-impl.ts:423-432`). Startup and shutdown hooks are +> private and are honored **only** by `serve()`, the listener-owning path the unified runtime +> forbids (`packages/service/src/builder/service-builder-impl.ts:501-521`). A service that registers +> `.onStartup()` / `.onShutdown()` would therefore **silently lose lifecycle behavior** the moment it +> is hosted under Nitro instead of `serve()`. +> +> This card defines and exports a **hostable-service lifecycle contract** — a build/start/stop +> surface (or equivalent `[Symbol.asyncDispose]`-bearing handle) that a host (Nitro, desktop, tests) +> can drive **without** owning a listener: +> +> - `build()` continues to return the `ServiceApp`; a new exported surface exposes **start** +> (run startup hooks, with startup-failure rollback) and **stop** (graceful drain) decoupled from +> `serve()`'s Deno listener. +> - **Reuse the shipped `ServiceShutdownCoordinator` policy** — do not invent a second, weaker +> lifecycle. The coordinator already owns idempotency, an `AbortController`, a bounded drain-timeout +> budget, LIFO teardown-hook ordering, and structured `ShutdownReport`s +> (`packages/service/src/builder/service-shutdown.ts:1-135`, +> `DEFAULT_DRAIN_TIMEOUT_MS = 30_000`). The host contract wraps this coordinator; it must not +> re-implement "exactly once" with different semantics. +> - Preserve **startup-hook ordering and startup-failure rollback**: `serve()` runs startup hooks +> before binding the listener (`service-builder-impl.ts:501-521`); the hostable surface must run +> them at host start and roll back partial construction on failure. +> - The Nitro `close` hook (UR-2) drives this contract's **stop**; the disposal registry UR-2 +> maintains delegates drain/teardown to the coordinator rather than to a bespoke "exactly once" +> registry. +> +> Specify the **package/export/JSR gates** for the new surface (which package owns it, what is public +> vs internal, `deno doc --lint` clean) as part of UR-11 architecture contracts — this card provides +> the lifecycle behavior; UR-11 provides the export ownership. +> +> Evidence: `research/adapter-mapping.md` (a bridge must order start, close, drain, and failure +> reporting); design pack `design/D1-composition-host/proposal.md` §2.3–§2.4. + +## Acceptance / gates + +- [ ] gate: an exported hostable surface runs registered `onStartup` hooks at host start, in + registration order, with rollback on startup failure (no listener bound) +- [ ] gate: host stop drains via the shipped `ServiceShutdownCoordinator` policy — idempotent under + double-stop, LIFO hook order, bounded drain budget, structured `ShutdownReport` returned +- [ ] gate: a service using `.onStartup()` / `.onShutdown()` retains identical lifecycle behavior + when hosted (not `serve()`-launched) as it had under `serve()` +- [ ] gate: no second/incompatible lifecycle registry is introduced; the Nitro `close` path (UR-2) + delegates to this contract +- [ ] gate: package/export ownership and JSR surface for the new API recorded against UR-11 + +## Fork deltas + +None. (Dependency-direction of the exported surface vis-à-vis the SDK is decided by **F-7**, resolved +in UR-4/UR-11, not here.) diff --git a/.llm/runs/plan-unified-runtime--seed/design/canonical/UR-1.md b/.llm/runs/plan-unified-runtime--seed/design/canonical/UR-1.md new file mode 100644 index 000000000..752fe4ec7 --- /dev/null +++ b/.llm/runs/plan-unified-runtime--seed/design/canonical/UR-1.md @@ -0,0 +1,35 @@ + + +# UR-1 — Single logical composition root with no application-created loopback + +- **Slot:** UR-1 +- **Owning pack:** D1 composition-host (draft D1-1) +- **Labels:** `type:feat`, `area:service`, `area:deploy`, `epic:unified-runtime`, `epic:deployment`, `priority:p1`, `wave:v1`, `status:plan` +- **Milestone:** `0.0.1-beta.13` +- **Depends on:** UR-11 (architecture contracts — package/export boundary the root lives in) +- **Blocks:** UR-2, UR-4, UR-5, UR-10 + +## Body + +> Part of #823 +> +> +> +> Establish the composition root as the single module that wires the NetScript service, oRPC handler, +> and Fresh UI into one logical application graph. The universal invariant is **logical graph +> identity — one composition root**; physical single-OS-process execution is a per-preset capability +> (declared by the capability matrix UR-5/UR-6, not here). The invariant that holds on every preset is +> **no application-created loopback**: the graph is wired by in-process Fetch delegation, never by +> opening a socket back to the host's own listener. See design pack +> `design/D1-composition-host/proposal.md` §1. + +## Acceptance / gates + +- [ ] gate: build exposes exactly one composition root (a single mount/prefix/lifecycle registry) +- [ ] gate: no adapter or bridge opens a loopback HTTP client to the host listener +- [ ] gate: physical single-process asserted only for presets whose capability cell declares `process: in-process` +- [ ] gate:e2e composed entry point boots and serves the graph through one root + +## Fork deltas + +None. diff --git a/.llm/runs/plan-unified-runtime--seed/design/canonical/UR-10.md b/.llm/runs/plan-unified-runtime--seed/design/canonical/UR-10.md new file mode 100644 index 000000000..cf177bcbd --- /dev/null +++ b/.llm/runs/plan-unified-runtime--seed/design/canonical/UR-10.md @@ -0,0 +1,44 @@ + + +# UR-10 — Single-process realization capability + acceptance (foundation) + +- **Slot:** UR-10 +- **Owning pack:** D1 + D2 (composition-host realization + capability column) +- **Labels:** `type:feat`, `area:deploy`, `area:sdk`, `epic:unified-runtime`, `epic:deployment`, `priority:p1`, `wave:v1`, `status:plan` +- **Milestone:** `0.0.1-beta.13` +- **Depends on:** UR-4 (oRPC bridge), UR-7 (writer-ownership) +- **Blocks:** UR-8, UR-12 +- **Relationship to #454:** #454 stays **OPEN and KEEP** as the desktop realization issue — see the + supersession note. UR-10 does **not** carry `Closes #454`. + +## Body + +> Part of #823 +> +> +> +> Scope the physical **single-process realization** capability: the one-OS-process / zero-loopback +> guarantee is asserted **only for presets whose capability cell declares `process: in-process`**; +> cloud/serverless presets guarantee logical composition + no application-created loopback, not one OS +> process (drift D-02). This card provides the capability column + the realization acceptance for +> in-process-capable presets. +> +> **Scope boundary — this is the capability + realization contract, not the desktop link-mode +> switch.** UR-10 does **not** implement #454's generated web/desktop **link-mode flag**, the +> requirement that generated client code be identical apart from that flag, or the packaged-binary +> data-plane E2E. #454 stays open as the desktop realization issue; the desktop **consumer** lives on +> epic #830 (which tests both composition modes via #837). UR-10 is worded so #830 can consume it. It +> is **not** closed by this card. +> +> Evidence: `research/drift-ledger.md` D-02; `proposal.md` §1; D2 `proposal.md` §1, §3. + +## Acceptance / gates + +- [ ] gate: physical single-process/zero-loopback asserted only for presets that advertise `process: in-process` +- [ ] gate: bounded-window presets satisfy the invariant via logical composition + no app-created loopback (no OS-process claim) +- [ ] gate: UR-10's capability column is consumable by the #830 desktop realization without re-scoping +- [ ] gate: no `Closes #454` — #454's generated link-mode switch + packaged data-plane E2E remain a separate open issue + +## Fork deltas + +None (WebSocket scope governed by F-4 in UR-4). diff --git a/.llm/runs/plan-unified-runtime--seed/design/canonical/UR-11.md b/.llm/runs/plan-unified-runtime--seed/design/canonical/UR-11.md new file mode 100644 index 000000000..2d777c3fe --- /dev/null +++ b/.llm/runs/plan-unified-runtime--seed/design/canonical/UR-11.md @@ -0,0 +1,60 @@ + + +# UR-11 — Architecture contracts: package/export ownership, archetype, compiler schema + build seam + +- **Slot:** UR-11 (prerequisite — precedes all Stage-I contract lanes) +- **Owning pack:** D3 board-mechanics (new prerequisite, Stage-F F14) — absorbs the prior UR-11 board-language normalization +- **Labels:** `type:feat`, `area:deploy`, `area:service`, `area:sdk`, `area:database`, `epic:unified-runtime`, `epic:deployment`, `priority:p1`, `wave:v1`, `status:plan` +- **Milestone:** `0.0.1-beta.13` +- **Depends on:** — (architecture foundation) +- **Blocks:** UR-1, UR-4, UR-5 (they consume the package boundary, requirement schema, and build seam) + +## Body + +> Part of #823 +> +> +> +> **Prerequisite architecture contracts the Stage-I lanes need before they can start.** The other UR +> cards name abstractions ("the unified-runtime host package", "the composition compiler") that do not +> yet exist as a realizable repository boundary. This card settles those decisions so no lane has to +> reverse-engineer the architecture: +> +> 1. **Package/file ownership + export map.** Name the unified-runtime **host package** (path, +> `deno.json`, JSR export map), the composition-root module location, and which symbols are public +> vs internal. Reconcile the SDK↔service dependency direction selected in **F-7** (UR-4) into the +> allowed import graph. +> 2. **Doctrine archetype selection.** Choose the doctrine archetype(s) for the host package and the +> per-package fitness/JSR/E2E gates across the affected surfaces (service, SDK, CLI/config, +> database/KV/queue, plugin runtimes). Cite `docs/architecture/doctrine/`. +> 3. **Composition-compiler requirement schema + build seam.** Define the machine-readable +> requirement/manifest **types** (what a cell manifest and an app-requirement record look like) and +> the **build/CLI invocation seam** by which static tooling observes a dynamically composed +> services/plugins graph. UR-5's compiler consumes this schema; it does not invent it. +> 4. **Board-language / package-naming normalization** (absorbs the former UR-11 scope): board and code +> language normalize to the shipped **`@netscript/database`** name; retire `@netscript/data`. A new +> `@netscript/data` facade, if the owner commissions one (**F-8**), needs its own contract card and +> is out of scope here. +> 5. **Migration policy** for the new package/exports (JSR text-import lineage caveats per repo +> doctrine; string-constant law). +> +> Where a contract is large enough to warrant its own tracked issue, split it into a prerequisite card +> rather than bundling (Stage-F F14 disposition). +> +> Evidence: `research/drift-ledger.md` D-12; `synthesis.md` §6; Stage-F finding F14; +> `docs/architecture/doctrine/`. + +## Acceptance / gates + +- [ ] gate: unified-runtime host package named with a path, `deno.json`, and public/internal export map; allowed import directions documented (incl. F-7 resolution) +- [ ] gate: doctrine archetype(s) selected; per-package fitness/JSR/E2E gate matrix recorded for service/SDK/CLI-config/database-KV-queue/plugin surfaces +- [ ] gate: machine-readable requirement/manifest schema + the build/CLI seam are specified and consumed by UR-5 +- [ ] gate: board + code language normalized to `@netscript/database`; `@netscript/data` retired (facade deferred to F-8) +- [ ] gate: migration/JSR text-import policy for the new surface recorded + +## Fork deltas + +**F-8 (`@netscript/database` normalization vs new `@netscript/data` facade).** +- **A (default) — normalize:** use shipped `@netscript/database`; no facade. Acceptance as written. +- **B — commission facade:** a `@netscript/data` facade becomes its own contract card and a dependency + for UR-4's context/data seam; the fourth gate box changes to "facade contract card filed and linked." diff --git a/.llm/runs/plan-unified-runtime--seed/design/canonical/UR-12.md b/.llm/runs/plan-unified-runtime--seed/design/canonical/UR-12.md new file mode 100644 index 000000000..0eb987c3b --- /dev/null +++ b/.llm/runs/plan-unified-runtime--seed/design/canonical/UR-12.md @@ -0,0 +1,40 @@ + + +# UR-12 — Epic acceptance + supersession reconciliation card (was UR-H) + +- **Slot:** UR-12 (renamed from UR-H — Stage-F F17 namespace normalization) +- **Owning pack:** D3 board-mechanics +- **Labels:** `type:chore`, `area:deploy`, `epic:unified-runtime`, `epic:deployment`, `priority:p1`, `wave:v1`, `status:plan` +- **Milestone:** `0.0.1-beta.13` +- **Depends on:** UR-6 (v1 cells green), UR-10 (single-process realization), all supersession reconciliations +- **Blocks:** — (terminal acceptance card) + +## Body + +> Part of #823 +> +> +> +> Epic acceptance + reconciliation card for the unified-runtime v1: capability-matrix green across the +> **three** v1 cells (`deno_server`, `node_server`, `cloudflare_module`), and the supersession +> reconciliation closed out. This card confirms that: +> +> - The three-cell conformance suite (UR-6) is green on the pinned Nitro version. +> - Every KEEP legacy issue (#451, #453, #454, #455) is still open, carries `Part of #823`, and its +> fold lands only via its own downstream implementation PR's `Closes #N` — never at filing. +> - The #327 non-closing saga addendum and #349 status-label correction are recorded (see the +> reconciliation map in `filing-manifest.md` Step 5). +> - `deno_deploy` remains withdrawn-pending-research (DD-RESEARCH) and makes no v1 capability claim. +> +> Evidence: `filing-manifest.md` Step 5; `proposal.md` §5. + +## Acceptance / gates + +- [ ] gate: three-cell capability matrix green (UR-6 e2e) +- [ ] gate: #451/#453/#454/#455 open with `Part of #823`; no filing-time closes recorded +- [ ] gate: #327 addendum + #349 status-label correction recorded in FILING-LOG +- [ ] gate: `deno_deploy`/DD-RESEARCH deferral reflected in the epic checklist + +## Fork deltas + +None. diff --git a/.llm/runs/plan-unified-runtime--seed/design/canonical/UR-2.md b/.llm/runs/plan-unified-runtime--seed/design/canonical/UR-2.md new file mode 100644 index 000000000..f8cfdc099 --- /dev/null +++ b/.llm/runs/plan-unified-runtime--seed/design/canonical/UR-2.md @@ -0,0 +1,37 @@ + + +# UR-2 — Nitro owns listener/lifecycle; single-shot `close` disposal via the lifecycle contract + +- **Slot:** UR-2 +- **Owning pack:** D1 composition-host (draft D1-2) +- **Labels:** `type:feat`, `area:deploy`, `area:fresh`, `epic:unified-runtime`, `epic:deployment`, `priority:p1`, `wave:v1`, `status:plan` +- **Milestone:** `0.0.1-beta.13` +- **Depends on:** UR-0 (hostable-service lifecycle contract), UR-1 (composition root) +- **Blocks:** UR-3, UR-10 + +## Body + +> Part of #823 +> +> +> +> Bind the composition root into Nitro v3 as a synchronous plugin. **Nitro owns process startup, the +> single listener, top-level `error` observation, and shutdown.** Async adapter construction (DB +> pools, queue connections) happens before plugin registration; resolved handles are closed over so +> registration stays synchronous. Every adapter/worker registers a disposer; the Nitro `close` hook +> drains through the **UR-0 hostable-service lifecycle contract** (which reuses the shipped +> `ServiceShutdownCoordinator` policy — idempotency, bounded drain budget, LIFO order, structured +> report), **not** a bespoke second registry. The lifecycle bridge is explicit — do not assume +> Fresh/Hono middleware order matches Nitro's pipeline, and account for Nitro running static files +> before middleware/routes. See proposal.md §2 (evidence: `research/nitro-v3.md` Lifecycle row). + +## Acceptance / gates + +- [ ] gate: no nested listen — Nitro is the sole listener owner +- [ ] gate: `close` hook drains the UR-0 lifecycle contract exactly once (idempotent under double-close), LIFO order, bounded drain budget +- [ ] gate: plugin registration is synchronous; async construction resolved beforehand +- [ ] gate: only host/composition failures (not RPC-domain errors) reach Nitro's `error` hook + +## Fork deltas + +None. diff --git a/.llm/runs/plan-unified-runtime--seed/design/canonical/UR-3.md b/.llm/runs/plan-unified-runtime--seed/design/canonical/UR-3.md new file mode 100644 index 000000000..e79c9ddda --- /dev/null +++ b/.llm/runs/plan-unified-runtime--seed/design/canonical/UR-3.md @@ -0,0 +1,42 @@ + + +# UR-3 — Mount Fresh via `app.handler()` with declared route/static ownership + +- **Slot:** UR-3 +- **Owning pack:** D1 composition-host (draft D1-3) +- **Labels:** `type:feat`, `area:fresh`, `area:deploy`, `epic:unified-runtime`, `epic:deployment`, `priority:p1`, `wave:v1`, `status:plan` +- **Milestone:** `0.0.1-beta.13` +- **Depends on:** UR-2 (Nitro host integration) +- **Blocks:** UR-10 + +## Body + +> Part of #823 +> +> +> +> Mount the Fresh UI by calling `defineFreshApp()`'s `app.handler()` as an opaque Fetch delegate — +> **never `app.listen()`**. Preserve the shipped wrapper's middleware ordering and filesystem routes +> intact (`packages/fresh/src/runtime/server/define-fresh-app.ts`). Declare non-overlapping route +> spaces (RPC subtree, health/metadata, Fresh UI, static assets); Fresh is the final UI fallback only, +> mounted after Nitro matches the RPC prefix and health paths — no wildcard above the RPC prefix. +> Declare static-asset ownership per namespace (default per **F-5**: Fresh owns its island/`_fresh` +> assets; Nitro owns host public dir) and verify through the composed entry point. See proposal.md §3 +> (evidence: `research/orpc-fresh.md` Route/Static ownership rows). + +## Acceptance / gates + +- [ ] gate: Fresh mounted via `app.handler()`; no `app.listen()` anywhere in the graph +- [ ] gate: RPC / health / Fresh-UI / static route spaces declared disjoint; no catch-all above RPC prefix +- [ ] gate: Fresh middleware chain reached for its route space through the composed entry point +- [ ] gate: static-asset ownership declared per namespace; cache headers/fallbacks/error pages verified through composed entry point + +## Fork deltas + +**F-5 (static-asset ownership).** +- **A (default) — Fresh-owns-islands:** Fresh owns `_fresh`/island namespace; Nitro owns host public + dir; the two namespaces declared disjoint in the mount table. Acceptance as written above. +- **B — Nitro-owns-all:** host-level static serving assigned to Nitro wholesale (single asset + pipeline); Fresh asset requests route through the outer host. Under B, the fourth acceptance box + becomes "all static namespaces served by the Nitro public-asset stage; Fresh island assets + resolved through the host pipeline," and the disjoint-namespace assertion is dropped. diff --git a/.llm/runs/plan-unified-runtime--seed/design/canonical/UR-4.md b/.llm/runs/plan-unified-runtime--seed/design/canonical/UR-4.md new file mode 100644 index 000000000..8114f11ca --- /dev/null +++ b/.llm/runs/plan-unified-runtime--seed/design/canonical/UR-4.md @@ -0,0 +1,66 @@ + + +# UR-4 — In-process oRPC host bridge over `ServiceApp.fetch` (context, abort, error semantics) + +- **Slot:** UR-4 +- **Owning pack:** D1 composition-host (draft D1-4) +- **Labels:** `type:feat`, `area:service`, `area:sdk`, `gate:jsr`, `epic:unified-runtime`, `epic:deployment`, `priority:p1`, `wave:v1`, `status:plan` +- **Milestone:** `0.0.1-beta.13` +- **Depends on:** UR-1 (composition root), UR-11 (architecture contracts — SDK↔service export direction) +- **Blocks:** UR-10 +- **Relationship to #451:** #451 stays **OPEN and KEEP** — see the supersession note below. UR-4 + does **not** carry `Closes #451`. + +## Body + +> Part of #823 +> +> +> +> Invoke the service **in-process** by delegating the Web `Request` into the shipped +> `ServiceApp.fetch` / oRPC `RPCHandler` (`packages/service/src/primitives/handlers.ts:115-143`, +> `packages/service/src/types.ts:13-20`). Transport is **invocation placement over a stable Fetch/RPC +> contract** — "no socket loopback" is the requirement; a second codec is not. The host consumes +> `fetch` and does not reach into the Hono implementation. Carry one canonical RPC prefix into both H3 +> matching and `handler.handle(..., { prefix })`; pass request-scoped auth/telemetry context (single +> `toServiceContext` seam) and the abort signal. RPC-domain errors serialize as typed responses and do +> not reach Nitro's `error` hook. Treat ordinary, streamed, and WebSocket-upgrade responses as +> distinct conformance cases (WebSocket is opt-in via CrossWS/H3, not implied — see **F-4**). See +> proposal.md §4. +> +> **Scope boundary — this is the host-side bridge only.** UR-4 realizes the composition host's +> in-process invocation seam. It is **not** the full public SDK transport surface tracked by #451 +> (the transport discriminant/registry, `createInProcessClientLink`, `ServiceClientTransport`, the +> `transport` option, `createInProcessServiceClient`, HTTP-default compatibility, HTTP/in-process byte +> parity, W3C propagation, and the JSR/export gates). #451 stays open as its own SDK slice and is +> **not** closed by this card. The public dependency direction between the SDK and the service +> (#451 owner decision **O-1**, restored as **F-7**) is selected before the SDK slice starts; today +> the only transport seam that exists is the internal structural port at +> `packages/sdk/src/ports/client-link-factory.ts:17-24`, and `service-client.ts:40-61` always +> constructs `createHttpClientLink`. + +## Acceptance / gates + +- [ ] gate: in-process delegation over `ServiceApp.fetch`/`RPCHandler`; no socket loopback +- [ ] gate: single canonical prefix carried into H3 match and `handler.handle` +- [ ] gate: request context (single `toServiceContext` seam) + abort signal carried into handler +- [ ] gate: RPC match/404 preserved; RPC-domain errors returned as typed responses +- [ ] gate: ordinary and streamed responses exercised through the composed entry point (WebSocket-upgrade case per F-4) +- [ ] gate: no `Closes #451` — #451's SDK transport surface remains a separate open slice + +## Fork deltas + +**F-7 (SDK↔service dependency direction — restored #451 O-1).** +- **A (default) — import `type`:** the in-process link imports the `ServiceApp` type from + `@netscript/service` and reuses the shipped structural port (`client-link-factory.ts`). Lowest + duplication; couples SDK build-time to the service type surface. +- **B — mirror structural shape:** the SDK mirrors the `fetch(request): Promise` structural + shape locally and takes no build dependency on `@netscript/service`. Preserves SDK→service + decoupling at the cost of a maintained structural mirror. Selection changes UR-4's import graph and + #451's acceptance; it does not change UR-4's gate boxes. + +**F-4 (WebSocket/upgrade scope).** +- **A (default) — defer:** v1 exercises ordinary + streamed responses only; the WebSocket-upgrade + conformance case moves to a later cell-proof card. Fifth gate box drops "WebSocket-upgrade". +- **B — include in v1:** add "WebSocket-upgrade responses exercised through the composed entry point" + back into the fifth gate box; requires the CrossWS/H3 opt-in wired in v1. diff --git a/.llm/runs/plan-unified-runtime--seed/design/canonical/UR-5.md b/.llm/runs/plan-unified-runtime--seed/design/canonical/UR-5.md new file mode 100644 index 000000000..f65be0254 --- /dev/null +++ b/.llm/runs/plan-unified-runtime--seed/design/canonical/UR-5.md @@ -0,0 +1,56 @@ + + +# UR-5 — Preset capability manifest + build-time rejection compiler; per-preset sagas declaration + +- **Slot:** UR-5 +- **Owning pack:** D2 capability-matrix (drafts D2-S1 + D2-S2) +- **Labels:** `type:feat`, `area:cli`, `area:config`, `area:plugins`, `epic:unified-runtime`, `epic:deployment`, `priority:p1`, `wave:v1`, `status:plan` +- **Milestone:** `0.0.1-beta.13` +- **Depends on:** UR-1 (composition root — source of logical-graph requirements), UR-11 (architecture contracts — requirement schema + build seam) +- **Blocks:** UR-6, UR-7, UR-9, UR-10 + +## Body + +> Part of #823 +> +> +> +> Define the machine-readable **capability manifest** each v1 runtime cell ships, and the +> **composition compiler** that cross-checks the app's logical-graph requirements against the selected +> preset's manifest, failing the **build** (never runtime, never a silent downgrade) on an unsupported +> combination. The requirement schema and the static build/CLI seam by which the compiler observes a +> dynamically composed graph are defined in **UR-11 architecture contracts** — UR-5 consumes them. +> +> - Manifest encodes per-capability `lossless | partial | unsupported` + saga declaration + writer / +> offline flags (see `design/D2-capability-matrix/proposal.md` §3–§4). +> - Compiler reads requirements from the logical composition root (sagas mounted? long-running queue +> listener? CAS-dependent trigger/idempotency store? exclusive-lock single-writer DB?). +> - `unsupported` → hard build failure with a diagnostic naming capability + cell + externalize path. +> `partial` → build warning with the named degraded axis, requiring explicit adapter selection. +> - **Sagas rule (supersedes the categorical "#327 D1 excludes sagas"):** implement +> `sagas: supported | externalized | rejected` per cell and prove each against duration, lifecycle, +> connector, and `SagaDurabilityTier` gates. In-process is allowed **only through the NetScript saga +> runtime** (store/transport/outbox/idempotency ports authoritative); "externalized" = macro-service +> split of the **same app model**; **never** a downgrade to Nitro tasks. Supported cells drain the +> saga runtime on Nitro `close` via the UR-0 lifecycle contract. +> +> Evidence: `research/drift-ledger.md` D-05/D-06; `research/sagas-constraint.md` Board consequence +> 1–3; `research/adapter-mapping.md` KV-atomics + One-off-task + Saga rows; `proposal.md` §2.1, §4. + +## Acceptance / gates + +- [ ] gate: each v1 cell (per UR-6) ships a capability manifest matching proposal.md §3 +- [ ] gate: an app mounting a saga runtime under a bounded-window cell **fails the build** with a diagnostic naming the externalize path (no runtime fallthrough) +- [ ] gate: a `partial` mapping (e.g. polling KV watch) emits a build warning naming the degraded axis, not a hard fail +- [ ] gate: no Nitro primitive (unstorage / db0 / Nitro-task / H3 / Hono) is reachable from application code in any cell +- [ ] gate: no code path substitutes a Nitro task for a `SagaDefinition` (correlation / transitions / compensation / retry / idempotency / outbox preserved) + +## Fork deltas + +**F-3 (bounded-window sagas — externalized vs reject-only).** +- **A (default) — reject-only v1:** bounded-window cells hard-reject an in-process saga at build; the + externalized macro-service path ships v1.1. Second gate box reads "fails the build … naming the + externalize path as a v1.1 target." +- **B — ship externalization v1:** bounded-window cells auto-externalize to a configured macro-service + target; second gate box adds "or externalizes to the configured macro-service target." Requires a + configured externalization target in the manifest schema (UR-11). diff --git a/.llm/runs/plan-unified-runtime--seed/design/canonical/UR-6.md b/.llm/runs/plan-unified-runtime--seed/design/canonical/UR-6.md new file mode 100644 index 000000000..b68ad3c23 --- /dev/null +++ b/.llm/runs/plan-unified-runtime--seed/design/canonical/UR-6.md @@ -0,0 +1,70 @@ + + +# UR-6 — Runtime-cell columns: three v1 cells + three-cell conformance suite + +- **Slot:** UR-6 +- **Owning pack:** D2 capability-matrix (drafts D2-S3, D2-S5, D2-S6) +- **Labels:** `type:test`, `area:cli`, `area:tooling`, `area:deploy`, `gate:e2e`, `epic:unified-runtime`, `epic:deployment`, `priority:p1`, `wave:v1`, `status:plan` +- **Milestone:** `0.0.1-beta.13` +- **Depends on:** UR-5 (capability framework) +- **Blocks:** UR-12 (epic acceptance) +- **Successor (separately milestoned):** **DD-RESEARCH** — new-platform Deno Deploy probe (see slot-map); at `0.0.1-stable`, NOT part of the v1 beta.13 acceptance. + +## Body + +> Part of #823 +> +> +> +> One matrix issue with **per-cell acceptance** (per **F-12**), not one card per cell, so the "one +> deploy output across cells" story has a single acceptance surface. +> +> **v1 runtime cell set (three cells):** +> - **C1 `deno_server`** — bare-metal/container, long-lived; Node-built output launched +> `deno run --unstable …`; broad perms audited (`research/nitro-v3.md` Deno-preset table row 2). +> - **C3 `node_server`** — Nitro default production output, long-lived Node process; no `--unstable`; +> Redis/AMQP/PostgreSQL backings (`research/nitro-v3.md` row 4; `research/adapter-mapping.md` Queue +> row). +> - **C4 `cloudflare_module`** — isolate/serverless representative, bounded window; platform adds +> scheduled/email/queue/tail hooks (`research/nitro-v3.md` Cloudflare row). Representative choice is +> **F-1**. +> +> **`deno_deploy` (formerly C2) is WITHDRAWN from the v1 cell set.** The corpus evidence targeted Deno +> Deploy **Classic** and its `deployctl` flow (`research/nitro-v3.md`), which — with the new +> platform's `deno deploy` build/runtime model — is a shutdown target: Classic and `deployctl` sunset +> **2026-07-20**, and the new platform does **not** support Deno queues. No corpus artifact validates a +> Nitro v3 output, queue binding, or database binding on the surviving platform. `deno_deploy` is +> therefore **not** a validated v1 cell; it is deferred to the **DD-RESEARCH** successor card (a real +> new-platform Nitro build/deploy/conformance probe, including any external queue/database bindings), +> which must complete before `deno_deploy` may re-enter the matrix. This is **F-2**. +> +> Author the conformance suite proving each **v1** cell's manifest against real behavior; include the +> Nitro version + compatibility-date pin and an upgrade-drift gate (beta maturity). The long-lived vs +> bounded-window axis is load-bearing (sagas, durable queue consumers, exclusive-lock writer +> ownership). +> +> Evidence: `research/nitro-v3.md` Board inputs 1–2 + Deno-preset table; `proposal.md` §1, §3, §4; +> **C2/`deno_deploy` withdrawal**: Deno Deploy Classic/`deployctl` sunset (Stage-F finding F1). + +## Acceptance / gates + +- [ ] gate: each of the **three** v1 cells (`deno_server`, `node_server`, `cloudflare_module`) ships a manifest and an executed conformance case asserting its declared L/P/U/saga mapping +- [ ] gate: an exact Nitro v3 version + compatibility-date is pinned and an upgrade drift check runs +- [ ] gate: `deno_deploy` produces **no** v1 capability claim; its column is marked withdrawn-pending-research and gated behind DD-RESEARCH +- [ ] gate:e2e the three-cell suite is green on the pinned Nitro version + +## Fork deltas + +**F-1 (isolate representative cell).** +- **A (default):** `cloudflare_module` (provider page names it; richest hook surface). +- **B:** substitute `vercel` / `netlify_edge` / `aws_lambda`; changes the C4 mappings in UR-9 and the + conformance case here. + +**F-2 (v1 cell set — 3-cell vs re-proven `deno_deploy`).** +- **A (default) — 3-cell v1:** ship `deno_server` + `node_server` + `cloudflare_module`; `deno_deploy` + deferred to DD-RESEARCH at `0.0.1-stable`. Acceptance as written (three cells). +- **B — re-prove and include `deno_deploy` later:** DD-RESEARCH runs first (it depends on UR-6's + three-cell suite existing, never the reverse); on PASS, a SEPARATE successor extension card + (UR-6-EXT, drafted at that point) adds the fourth executed conformance case. UR-6 itself stays + three-cell in both branches — no dependency cycle, no post-ratification rewrite of this card. + Milestone impact: DD-RESEARCH may be pulled from `0.0.1-stable` into the beta.13 train. diff --git a/.llm/runs/plan-unified-runtime--seed/design/canonical/UR-7.md b/.llm/runs/plan-unified-runtime--seed/design/canonical/UR-7.md new file mode 100644 index 000000000..883a37088 --- /dev/null +++ b/.llm/runs/plan-unified-runtime--seed/design/canonical/UR-7.md @@ -0,0 +1,42 @@ + + +# UR-7 — Writer-ownership & exclusive-lock database capability (foundation) + +- **Slot:** UR-7 +- **Owning pack:** D2 capability-matrix (draft D2-S4) +- **Labels:** `type:feat`, `area:database`, `epic:unified-runtime`, `epic:deployment`, `priority:p1`, `wave:v1`, `status:plan` +- **Milestone:** `0.0.1-beta.13` +- **Depends on:** UR-5 (capability framework) +- **Blocks:** UR-10 +- **Relationship to #453:** #453 stays **OPEN and KEEP** as the desktop-realization issue — see the + supersession note below. UR-7 does **not** carry `Closes #453`. + +## Body + +> Part of #823 +> +> +> +> Make writer ownership and exclusive-lock compatibility a **declared database capability**. "Default +> embedded" (single-writer Turso at the root) must not silently override topology constraints. +> Long-lived cells (C1 `deno_server` / C3 `node_server`) may hold an exclusive lock; bounded-window +> cells (C4 `cloudflare_module`) mark it `unsupported in-cell` → externalize or build-reject. +> +> **Scope boundary — this is the capability contract, not the desktop realization.** UR-7 declares the +> writer-ownership capability at the matrix level. It does **not** implement #453's OS-specific +> per-user data-dir relocation, `DATABASE_URL` resolution, real-filesystem Prisma/Turso path, b→c +> cutover guard, sole-lock-ownership proof, or the validation inside a `deno desktop` packaged binary. +> #453 stays open as the desktop-consumer realization issue (the desktop consumer lives on epic #830) +> and is **not** closed by this card. +> +> Evidence: `research/drift-ledger.md` D-08 (+ RFC §3 "locks earn a graph edge"); `proposal.md` §2.5. + +## Acceptance / gates + +- [ ] gate: exclusive-lock single-writer requirement builds on C1/C3 and build-rejects (or externalizes) on C4 +- [ ] gate: embedded-Turso default never activates where a topology constraint forbids it (no silent override) +- [ ] gate: no `Closes #453` — #453's packaged-desktop relocation/lock realization remains a separate open issue on #830 + +## Fork deltas + +None (v1 cell set governed by F-2 in UR-6). diff --git a/.llm/runs/plan-unified-runtime--seed/design/canonical/UR-8.md b/.llm/runs/plan-unified-runtime--seed/design/canonical/UR-8.md new file mode 100644 index 000000000..aff56dcc9 --- /dev/null +++ b/.llm/runs/plan-unified-runtime--seed/design/canonical/UR-8.md @@ -0,0 +1,46 @@ + + +# UR-8 — Offline-sync as a database-target capability/profile contract (foundation) + +- **Slot:** UR-8 +- **Owning pack:** D2 capability-matrix (draft D2-S7) +- **Labels:** `type:feat`, `area:database`, `epic:unified-runtime`, `epic:deployment`, `priority:p3`, `wave:v1`, `status:plan` +- **Milestone:** `0.0.1-beta.13` +- **Depends on:** UR-7 (writer-ownership capability), UR-10 (single-process realization) +- **Relationship to #455:** #455 stays **OPEN and KEEP** as the offline-sync **implementation** issue + — see the supersession note below. UR-8 does **not** carry `Closes #455`. + +## Body + +> Part of #823 +> +> +> +> Model offline sync (e.g. Turso Sync) as a **database-target capability/profile**, not a +> unified-runtime invariant and not an assumption on every Nitro preset. Server/edge cells expose it as +> `profile` / `n/a`; the single-local-writer preset declares it `supported`. Consumed by the desktop +> target adapter on epic #830. +> +> **Scope boundary — this is the profile/prerequisite contract, not the sync engine.** UR-8 declares +> the capability flag and its cross-reference. It does **not** implement #455's Turso Sync +> `pull()`/`push()`, fully-disconnected operation, reconnect reconciliation, or the documented +> last-push-wins / custom-transform conflict policy. #455 stays open as the downstream implementation +> issue (`priority:p3`) and is **not** closed by this card. A track-only profile-declaration PR must +> never carry a closing keyword for #455. +> +> Evidence: `research/drift-ledger.md` D-09; `research/nitro-v3.md` SQL-database maturity; +> `proposal.md` §2.6. + +## Acceptance / gates + +- [ ] gate: offline sync is declared on the database target, not inherited by every preset +- [ ] gate: cross-reference to the #830 desktop adapter recorded (no v1 ownership of desktop distribution) +- [ ] gate: no `Closes #455` — the Turso Sync engine + behavioral acceptance remain a separate open issue + +## Fork deltas + +**F-10 (offline-sync #455 home).** UR-8 (the profile contract) lands at `0.0.1-beta.13`. The +**#455 implementation** issue is deferred: +- **A (default):** #455 milestone `0.0.1-stable` (`priority:p3`, D-09 profile-not-invariant). +- **B:** #455 milestone `Backlog / Triage` (track-only until the desktop wave pulls it forward). +Selection changes only #455's milestone, not UR-8's. diff --git a/.llm/runs/plan-unified-runtime--seed/design/canonical/UR-9.md b/.llm/runs/plan-unified-runtime--seed/design/canonical/UR-9.md new file mode 100644 index 000000000..563af93b0 --- /dev/null +++ b/.llm/runs/plan-unified-runtime--seed/design/canonical/UR-9.md @@ -0,0 +1,44 @@ + + +# UR-9 — KV/queue/cache ownership + durability policy behind NetScript ports + +- **Slot:** UR-9 +- **Owning pack:** D2 capability-matrix (draft D2-S3, KV/queue/cache portion) +- **Labels:** `type:feat`, `area:kv`, `area:database`, `area:service`, `area:deploy`, `epic:unified-runtime`, `epic:deployment`, `priority:p2`, `wave:v1`, `status:plan` +- **Milestone:** `0.0.1-beta.13` +- **Depends on:** UR-5 (capability framework) +- **Blocks:** UR-12 + +## Body + +> Part of #823 +> +> +> +> Realize the ownership mappings in `proposal.md` §2.2–§2.4 across the **three v1 cells**: NetScript +> `KvStore`, `MessageQueue`, and `DatabaseAdapter` remain authoritative; Nitro unstorage / db0 / task +> primitives are host bindings **behind** the ports, never exposed to application code. Board language +> uses the shipped name `@netscript/database` (per **F-8**; naming ownership recorded in UR-11). +> +> - KV: map Nitro mounts behind `KvStore`; a CAS-dependent consumer on a non-CAS mount is a build +> rejection (UR-5), not best-effort. Nitro `ocache` is a host HTTP/function cache only — never +> durable KV/workflow state. +> - Queue: `@netscript/queue` owns delivery/consumer/retry/DLQ; a Nitro task runner may dispatch into +> it but not replace it. Long-running `listen` is externalized on bounded-window cells. +> - Database: `@netscript/database` owns health/lifecycle/telemetry/transactions; a db0 bridge is +> optional and provider-scoped. Durable provider-backed backing required on bounded-window cells; +> **volatility is removed from the definition of "in-process"** — capability + durability policy +> selects the backing. +> +> Evidence: `research/adapter-mapping.md` KV/Queue/SQL/Cache rows + "Adapter boundary"; +> `research/drift-ledger.md` D-03/D-06/D-12; `research/nitro-v3.md` KV-storage/SQL/Cache rows. + +## Acceptance / gates + +- [ ] gate: each v1 cell's KV/queue/database mapping matches proposal.md §3 (L/P/U per row) +- [ ] gate: application code imports only `@netscript/kv|queue|database` surfaces — no unstorage / db0 / Nitro-task symbols leak +- [ ] gate: Nitro response cache and durable KV are separate surfaces (no conflation) + +## Fork deltas + +None (naming governed by F-8 in UR-11; cell set by F-2 in UR-6). diff --git a/.llm/runs/plan-unified-runtime--seed/design/canonical/slot-map.md b/.llm/runs/plan-unified-runtime--seed/design/canonical/slot-map.md new file mode 100644 index 000000000..4de2aaed5 --- /dev/null +++ b/.llm/runs/plan-unified-runtime--seed/design/canonical/slot-map.md @@ -0,0 +1,86 @@ + + +# Canonical slot map — draft → slot with merge transforms + +> Stage-E rework artifact (Stage-F F8/F10/F17). One canonical body per UR slot lives in +> `design/canonical/UR-.md`; this file is the authoritative **draft → slot** mapping with the exact +> merge transform for every slot, so the Stage-H filer never composes prose on the fly. Namespace is +> normalized **once** to **UR-0…UR-12** (UR-H renamed to UR-12), plus the non-slot successor +> **DD-RESEARCH**. + +## Namespace (13 UR slots + 1 successor card) + +| Slot | Canonical file | Title | Owning pack | New at Stage-E? | +| --- | --- | --- | --- | --- | +| UR-0 | `UR-0.md` | Hostable-service lifecycle contract | D1 | **NEW** (F5) | +| UR-1 | `UR-1.md` | Single logical composition root / no-loopback | D1 (D1-1) | — | +| UR-2 | `UR-2.md` | Nitro owns listener/lifecycle; single-shot close | D1 (D1-2) | — | +| UR-3 | `UR-3.md` | Fresh mount via `app.handler()` + route/static | D1 (D1-3) | — | +| UR-4 | `UR-4.md` | In-process oRPC host bridge (host-side only) | D1 (D1-4) | — | +| UR-5 | `UR-5.md` | Capability manifest + rejection compiler + sagas | D2 (D2-S1 + D2-S2) | merged | +| UR-6 | `UR-6.md` | Runtime-cell columns: 3 v1 cells + conformance | D2 (D2-S3+S5+S6) | merged | +| UR-7 | `UR-7.md` | Writer-ownership & exclusive-lock capability | D2 (D2-S4) | — | +| UR-8 | `UR-8.md` | Offline-sync profile contract | D2 (D2-S7) | — | +| UR-9 | `UR-9.md` | KV/queue/cache ownership + durability | D2 (D2-S3, KV/queue portion) | — | +| UR-10 | `UR-10.md` | Single-process realization capability | D1+D2 | — | +| UR-11 | `UR-11.md` | Architecture contracts (+ db-naming normalization) | D3 | **NEW** (F14); absorbs old UR-11 | +| UR-12 | `UR-12.md` | Epic acceptance + reconciliation (was UR-H) | D3 | renamed from UR-H (F17) | +| DD-RESEARCH | `DD-RESEARCH.md` | New-platform Deno Deploy probe (successor) | D2 | **NEW** (F1); NOT a v1 cell | + +## Merge transforms (draft → canonical slot) + +- **UR-0** ← new. Lifecycle contract from Stage-F F5 + repo citations + (`service-builder-impl.ts:423-432,501-521`, `service-shutdown.ts:1-135`). No draft predecessor. +- **UR-1** ← D1-1 verbatim scope; added `epic:deployment` label + `status:plan`; milestone → beta.13; + added dependency on UR-11. +- **UR-2** ← D1-2; **transform:** the "exactly once disposal registry" is rewritten to **delegate to + the UR-0 lifecycle contract / `ServiceShutdownCoordinator` policy** (F5), not a bespoke registry. +- **UR-3** ← D1-3 verbatim; static-ownership default tagged to **F-5**. +- **UR-4** ← D1-4; **transform:** re-scoped to **host-side bridge only**; the `folds #451` / + `Closes #451` language is **removed**; #451 KEEP note added; restored **F-7** (SDK↔service + direction, #451 O-1) as a Fork delta; WebSocket case tagged **F-4**. +- **UR-5** ← **merge of D2-S1 (manifest + compiler) and D2-S2 (per-preset sagas)** into one card + (both are the "framework + build-time rejection + saga declaration" surface). Requirement schema + + build seam delegated to UR-11. +- **UR-6** ← **merge of D2-S3 cell listing + D2-S5 (task/schedule) conformance framing + D2-S6 + (four-cell conformance suite)**; **transform:** `deno_deploy` (C2) **withdrawn** from the v1 set → + three cells (`deno_server`, `node_server`, `cloudflare_module`); C2 claims marked + withdrawn-pending-research; DD-RESEARCH successor referenced; **F-1** + **F-2** Fork deltas. +- **UR-7** ← D2-S4; **transform:** re-scoped to **capability contract only**; `folds #453` / + `Closes #453` removed; #453 KEEP note added (desktop realization stays on #830). +- **UR-8** ← D2-S7; **transform:** re-scoped to **profile/prerequisite contract only**; `folds #455` / + `Closes #455` removed; #455 KEEP note added; milestone → beta.13 (contract), #455 impl deferred via + **F-10**. +- **UR-9** ← D2-S3 (KV/queue/cache + durability portion, split from the database-naming concern which + moves to UR-11). +- **UR-10** ← D3 UR-10 slot (D1+D2); **transform:** re-scoped to **capability + realization contract**; + `re-scopes #454` / `Closes #454` removed; #454 KEEP note added; the #454 body **addendum** (scoping + physical single-process to in-process-capable presets) is a non-closing reconciliation edit filed + per **F-16**, not a fold. +- **UR-11** ← **new architecture-contracts card (F14)** that **absorbs the former UR-11** + board-language normalization (db naming is a package/export-ownership concern). Prerequisite for + UR-1/UR-4/UR-5. +- **UR-12** ← former **UR-H** epic-acceptance card, renamed (F17); three-cell acceptance; supersession + reconciliation incl. #327/#349. +- **DD-RESEARCH** ← new successor card (F1); holds the withdrawn `deno_deploy` re-proof; NOT filed as a + v1 capability cell. + +## Milestone train (one train — F9/F-9) + +All UR-0…UR-12 land at **`0.0.1-beta.13`** (the single normative train). Deferred **cells/impl** are +split into separately-milestoned successors, never a single issue closing across milestones: + +- **DD-RESEARCH** (deno_deploy re-proof) → `0.0.1-stable`. +- **#455** offline-sync **implementation** (KEEP, downstream of UR-8) → `0.0.1-stable` (default F-10-A) + or `Backlog / Triage` (F-10-B). + +## Legacy issue dispositions (all KEEP — zero filing-time closes) + +| Legacy | Slot relationship | Disposition | Closes via | +| --- | --- | --- | --- | +| #451 | UR-4 (host bridge is a subset of #451's SDK surface) | **KEEP OPEN** | its own SDK-slice PR `Closes #451` | +| #453 | UR-7 (capability foundation) | **KEEP OPEN** (desktop realization on #830) | its own realization PR `Closes #453` | +| #454 | UR-10 (realization foundation) | **KEEP OPEN** + non-closing body addendum (F-16) | its own realization PR `Closes #454` | +| #455 | UR-8 (profile foundation) | **KEEP OPEN** | its own impl PR `Closes #455` | +| #327 | UR-5 saga rule | **KEEP OPEN** + non-closing addendum superseding D1 saga exclusion (F-17) | — (epic/parent; never closed here) | +| #349 | UR-6 tier-3 successor | already CLOSED; status-label correction only (F-17) | — | diff --git a/.llm/runs/plan-unified-runtime--seed/evidence/SHA256SUMS b/.llm/runs/plan-unified-runtime--seed/evidence/SHA256SUMS new file mode 100644 index 000000000..a2a053a81 --- /dev/null +++ b/.llm/runs/plan-unified-runtime--seed/evidence/SHA256SUMS @@ -0,0 +1,8 @@ +80c90227b833a001c90b3d0e38ddb11840fb63935e56abe8e11a048d5e98003c market-frameworks-live-2026-07-18.md +d3390be1e63e4ec13e9ccbcac5839b8207b09bada37d6ae5339c819841559f2e netscript-deno-doc-2026-07-18.md +69bfe6295d783f73ffa4f262289859491a182fd1d9b28074ffb85e53a8bfe211 nitro-v3-live-2026-07-18.md +d8bc10a1cfdd8397b878e15cf355dc064ffde3f60ebf87d42026abd71b2d576d orpc-fresh-live-2026-07-18.md +68fb741b856f62d4c578f33f60539427073193518d328bfc4d8274915faf21f2 pr822-frame-2026-07-18.md +9e8b269ceb56ab6882e2b9d2cd8adbf6fc985443e5300fd2f209e2779cd3eb43 deno-deploy-new-live-2026-07-18.md +4da0023979b0546e1bde149ce5c7d9f784df827aa9d0179f1b7c3072283d12e6 nitro-vs-own-live-2026-07-18.md +691e75a12490ca1720a20faa35f669a3ec75880e2c28cbc35a057a5e1ee79acf nitro-vs-own-rev2-live-2026-07-18.md diff --git a/.llm/runs/plan-unified-runtime--seed/evidence/deno-deploy-new-live-2026-07-18.md b/.llm/runs/plan-unified-runtime--seed/evidence/deno-deploy-new-live-2026-07-18.md new file mode 100644 index 000000000..8cd63f25b --- /dev/null +++ b/.llm/runs/plan-unified-runtime--seed/evidence/deno-deploy-new-live-2026-07-18.md @@ -0,0 +1,70 @@ +# New Deno Deploy evidence extract + +Retrieved: 2026-07-18 (Europe/Zurich). This is a concise extract of the official live pages used by +`research/deno-deploy-new.md`; the linked pages remain authoritative. + +## Classic migration and removed queues + +Source: https://docs.deno.com/deploy/migration_guide/ + +- Deno Deploy Classic (`dash.deno.com`) and the subhosting v1 API shut down on 2026-07-20. +- Classic projects are not transferred automatically; the new platform uses a separate account, + organization, and application model at `console.deno.com`. +- `deployctl` is sunset. The supported CLI path is `deno deploy`. +- The new runtime requires the built-in `Deno.serve()` API; the legacy std `serve()` fails warmup. +- Deno queues (`Deno.Kv.enqueue()` and `Deno.Kv.listenQueue()`) are not supported. The official + alternatives are an external message queue or a database-backed job queue. +- Deno KV is available, but Classic data is not automatically migrated. +- `Deno.cron()` remains supported. + +## Current platform comparison + +Source: https://docs.deno.com/deploy/ + +- The new Deno Deploy is a rework of Classic using Deno 2.0 and a new execution environment. +- The current feature table marks databases and cron supported, but queues unsupported. +- The platform supports integrated builds, full Deno and Node applications, CLI/GitHub deployment, + static sites, CDN caching, logs, tracing, and metrics. + +## Application and build contract + +Sources: + +- https://docs.deno.com/deploy/getting_started/ +- https://docs.deno.com/deploy/reference/builds/ +- https://docs.deno.com/runtime/reference/cli/deploy/ + +- A Deno Deploy application is one deployed web service with one build configuration. +- GitHub monorepos are not yet supported by the getting-started flow. +- A custom dynamic app config declares an install command, build command, working directory, + JavaScript/TypeScript entrypoint, arguments, and optional static directory. +- The platform executes install/build, prepares an artifact, then sends a warmup request before + routing the revision. +- Builds can be triggered from linked GitHub commits, the UI, or `deno deploy`; `deno deploy create` + configures new applications. + +## Databases and Deno KV + +Sources: + +- https://docs.deno.com/deploy/reference/databases/ +- https://docs.deno.com/deploy/reference/deno_kv/ +- https://docs.deno.com/runtime/reference/cli/deploy/#database-management-1 + +- An application can be assigned Deno KV, a managed Prisma Postgres database, or a linked external + database. Deploy injects the appropriate database connection for each timeline/environment. +- Deno KV connects with `Deno.openKv()` after assignment and creates isolated databases per + timeline. +- The CLI can provision/assign Deno KV and link/assign an external PostgreSQL database. +- Database availability does not imply queue availability: the migration guide and platform table + explicitly exclude the Deno KV enqueue/listenQueue APIs. + +## Nitro's currently documented Deno Deploy provider + +Source: https://nitro.build/deploy/providers/deno-deploy + +- Nitro names the `deno_deploy` preset and emits `.output/server/index.ts`. +- Every documented deployment path is Classic-specific: it requests a token at `dash.deno.com`, + invokes `deployctl`, or uses `denoland/deployctl@v1` with a linked Classic project. +- The page does not document `console.deno.com`, `deno deploy`, a new-platform build configuration, + database assignment, or a queue replacement. diff --git a/.llm/runs/plan-unified-runtime--seed/evidence/market-frameworks-live-2026-07-18.md b/.llm/runs/plan-unified-runtime--seed/evidence/market-frameworks-live-2026-07-18.md new file mode 100644 index 000000000..3b3112ffe --- /dev/null +++ b/.llm/runs/plan-unified-runtime--seed/evidence/market-frameworks-live-2026-07-18.md @@ -0,0 +1,68 @@ +# Comparable deployment-framework extracts (fetched 2026-07-18) + +Concise extracts used by `research/market.md`; original URLs are the authority. + +## Nuxt / Nitro + +Source: https://nuxt.com/docs/4.x/getting-started/deployment + +- A Node deployment starts the generated `.output/server/index.mjs` entry. +- Nitro can emit a `node_cluster` preset; the guide also documents PM2 and reverse-proxy + operation. + +Source: https://nitro.build/deploy + +- Nitro compiles the same server source into deployment-specific output presets and defaults to + the Node server preset when it cannot detect a provider. + +## Next.js standalone + +Source: https://nextjs.org/docs/pages/api-reference/config/next-config-js/output + +- `output: "standalone"` creates `.next/standalone` with a minimal `server.js` and traced runtime + dependencies. +- `public` and `.next/static` are not copied automatically; monorepos may need + `outputFileTracingRoot` to include files outside the app directory. + +## React Router framework mode + +Sources: + +- https://reactrouter.com/start/framework/deploying +- https://reactrouter.com/api/other-api/adapter + +- Framework mode supports full-stack hosting, static hosting, Docker, and provider templates. +- A React Router adapter converts a host-specific request into a Web Fetch API `Request`, calls the + request handler, and converts the `Response` back; official adapter packages include Node, + Express, and Cloudflare. + +## SvelteKit + +Sources: + +- https://svelte.dev/docs/kit/adapters +- https://svelte.dev/docs/kit/adapter-node + +- Adapters are build plugins that transform the built application for a deployment target; the + docs list automatic and official provider adapters. +- `adapter-node` emits a standalone Node server started with `node build`; environment variables, + reverse proxy behavior, and graceful shutdown remain explicit operator concerns. + +## Redwood + +Sources: + +- https://docs.redwoodjs.com/docs/deploy/introduction +- https://docs.redwoodjs.com/docs/docker + +- Redwood's deployment model separates a static `web` side from API code and supports both + serverless and serverful destinations. +- Its Docker guidance builds/runs distinct web and API units with corresponding server packages. + +## Wasp + +Source: https://wasp.sh/docs/deployment/deployment-methods/overview + +- A production Wasp app consists of a Node server, static client assets, and PostgreSQL; those + components can be deployed separately. +- Wasp generates a Dockerfile for the server deployment path. diff --git a/.llm/runs/plan-unified-runtime--seed/evidence/netscript-deno-doc-2026-07-18.md b/.llm/runs/plan-unified-runtime--seed/evidence/netscript-deno-doc-2026-07-18.md new file mode 100644 index 000000000..6a7887bc8 --- /dev/null +++ b/.llm/runs/plan-unified-runtime--seed/evidence/netscript-deno-doc-2026-07-18.md @@ -0,0 +1,47 @@ +# NetScript public-surface `deno doc` extract — 2026-07-18 + +Commands ran from `/home/codex/repos/wt-g8-seed` on branch +`plan/unified-runtime`. + +- `deno doc --filter KvStore packages/kv/mod.ts`: `KvStore` exposes get, set + with TTL, delete, has, prefix/range list, optional batch get and atomic CAS, + plus close/async dispose. `WatchableKv` adds key and prefix watch. Root docs + expose Deno KV and memory; `./redis` is a separate export. +- `deno doc --filter MessageQueue packages/queue/mod.ts`: `MessageQueue` + exposes enqueue/enqueueMany, a long-running `listen`, graceful stop, delayed + enqueue options, and a `nativeRetrial` capability flag. The module documents + Deno KV, Redis, RabbitMQ, validation, retry, delayed delivery, and Aspire + discovery; the export map additionally ships PostgreSQL and DLQ adapters. +- `deno doc --filter DatabaseAdapter packages/database/mod.ts`: + `DatabaseAdapter` exposes provider, client, connect/disconnect, health/status, + and raw execution. The module documents PostgreSQL/MSSQL/MySQL/SQLite, + Prisma-driver integration, discovery, telemetry, transactions, and pooling. + The command emitted unresolved cached `@types/node` warnings; the local + symbol surface was still produced. +- `deno doc --filter FetchHandler packages/service/mod.ts`: `FetchHandler` + consumes a Web `Request` plus prefix/context and returns matched/response. + Root module docs say `build()` returns a non-listening mountable `ServiceApp`, + while `serve()` owns the Deno listener. +- `deno doc --filter createRPCHandler packages/service/mod.ts`: + `createRPCHandler` returns the structural `FetchHandler` and constructs the + real oRPC fetch `RPCHandler` internally. +- `deno doc --filter createWorkersRuntime packages/plugin-workers-core/mod.ts`: + creates an explicit start/stop runtime; root docs expose job, task, workflow, + cron, state/store, executor, shutdown, telemetry, and testing primitives. +- `deno doc --filter SagaDefinition packages/plugin-sagas-core/mod.ts`: + a frozen definition includes durability tier, initial state, correlations, + handlers, compensations, signals, queries, retry, concurrency, and schedule. +- `deno doc --filter SagaStorePort packages/plugin-sagas-core/src/ports/mod.ts`: + persistence includes state envelopes, optimistic saves, transition history, + and correlation indexes. +- `deno doc --filter SagaTransportPort .../ports/mod.ts`: start/stop, publish, + subscribe. `SagaOutboxPort` reserves atomic state/message commit work; + `SagaIdempotencyPort` reserves durable deduplication keys. +- `deno doc --filter TriggerProcessorPort packages/plugin-triggers-core/mod.ts`: + processes one unified event and drains on stop. The root surface includes + schedules, webhooks, file watch, manual/queue/stream events, retries, + idempotency, DLQ, event store/subscription, enabled state, and backfill. +- `deno doc --filter StreamProducerPort packages/plugin-streams-core/mod.ts`: + state-protocol producer supports upsert/delete/flush/close. Root docs expose + typed schemas, durable producers, service discovery, auth, and diagnostics. + diff --git a/.llm/runs/plan-unified-runtime--seed/evidence/nitro-v3-live-2026-07-18.md b/.llm/runs/plan-unified-runtime--seed/evidence/nitro-v3-live-2026-07-18.md new file mode 100644 index 000000000..515a9f07a --- /dev/null +++ b/.llm/runs/plan-unified-runtime--seed/evidence/nitro-v3-live-2026-07-18.md @@ -0,0 +1,82 @@ +# Nitro v3 live-doc extract — 2026-07-18 + +This is a concise extraction from the live Nitro v3 documentation fetched on +2026-07-18. It preserves source URLs and the facts used by the Stage-B corpus; +the linked pages remain authoritative. + +## Maturity and Deno + +- Nitro v3 is a **public beta**, built around Web Standards, Rolldown, and Vite + v8. The beta announcement also states a Node.js 20 minimum for the v3 toolchain. + Source: https://nitro.build/blog/v3-beta +- The v3 migration guide calls itself a living document for a beta and records + intentional backward-incompatible changes, including renamed/removed presets. + Source: https://nitro.build/docs/migration +- The `deno_server` page says to build the Nitro server **using Node.js**, then + launch `.output/server/index.ts` with + `deno run --unstable --allow-net --allow-read --allow-env`. + Source: https://nitro.build/deploy/runtimes/deno +- Deno Deploy is a distinct `deno_deploy` preset. The documented paths are a + Deno Deploy project linked to GitHub or a token-driven `deployctl` flow. + Source: https://nitro.build/deploy/providers/deno-deploy + +## Runtime surface + +- Database: built-in lightweight SQL via db0; SQLite is the default only for + development and Node-compatible production. The whole database layer is + experimental and requires `experimental.database`. Primary API: + `useDatabase`, `db.sql`, `db.exec`, `db.prepare`. + Source: https://nitro.build/docs/database +- KV/storage: `useStorage()` exposes unstorage-backed mounts. The default mount + is memory and therefore does not persist across restarts; drivers and dynamic + plugin mounts supply persistent backends. Source: https://nitro.build/docs/storage +- Cache: ocache-backed handler/function caching (`defineCachedHandler`, + `defineCachedFunction`) sits on the storage layer. It supports route rules, + TTL/`maxAge`, conditional responses, and request deduplication. Only GET/HEAD + handlers are cached; error/undefined responses are excluded; cached function + values must be JSON-serializable. Source: https://nitro.build/docs/cache +- Tasks: the task API is experimental and requires `experimental.tasks`. + `defineTask` and `runTask` model named one-off operations. Cron schedules are + supported through `scheduledTasks`; process presets use croner, while + Cloudflare/Vercel receive generated native schedule configuration. Each task + name has at most one concurrent invocation; same-name callers share its result. + `context.waitUntil` is optional and runtime-dependent. More native preset + integrations are explicitly planned. Source: https://nitro.build/docs/tasks +- WebSocket: opt-in `features.websocket` support is powered by CrossWS/H3 and + documented for Node, Bun, Deno, and Cloudflare. Handlers expose `upgrade`, + `open`, `message`, `close`, and `error`, plus namespaces, peers, topics, + publish/subscribe, send, close, and terminate. Source: https://nitro.build/docs/websocket +- Lifecycle: runtime hooks are `request`, `response`, `error`, and `close`. + Static assets are checked before middleware/routes; process-level unhandled + rejections and exceptions enter the error hook; `close` is the cleanup hook. + Presets may augment the hook interface. Source: https://nitro.build/docs/lifecycle +- Plugins: `definePlugin` synchronously registers runtime behavior and hooks; + hooks may themselves be async, but the plugin function returns void. + Source: https://nitro.build/docs/plugins + +## Deployment presets/providers + +- The default production output is a Node.js server; development always uses + `nitro-dev`. A preset is selected with `NITRO_PRESET`, `SERVER_PRESET`, + `--preset`, or config. Nitro auto-detects AWS Amplify, Azure, Cloudflare, + Firebase App Hosting, Netlify, StormKit, Vercel, and Zeabur. Compatibility + dates deliberately pin provider behavior and should be updated with testing. + Source: https://nitro.build/deploy +- Provider docs enumerate Vercel, Deno Deploy, Zerops, Azure, Koyeb, Cloudflare, + Zephyr, Heroku, Netlify, Genezio, Alwaysdata, Zeabur, Render, StormKit, IIS, + DigitalOcean, Cleavr, AWS Lambda, Firebase, AWS Amplify, GitHub Pages, + Platform.sh, and GitLab Pages. A provider page is not necessarily a distinct + first-class runtime preset; some are recipes around the standard server. + Source index: https://nitro.build/deploy/providers +- Exact representative preset names from provider pages: Cloudflare + `cloudflare_module`/`cloudflare_pages`; Vercel `vercel`; Netlify + `netlify`/`netlify_edge`; AWS Lambda `aws_lambda`; Azure `azure-swa`; Deno + Deploy `deno_deploy`; Genezio `genezio` (explicitly experimental). + Sources: https://nitro.build/deploy/providers/cloudflare, + https://nitro.build/deploy/providers/vercel, + https://nitro.build/deploy/providers/netlify, + https://nitro.build/deploy/providers/aws, + https://nitro.build/deploy/providers/azure, + https://nitro.build/deploy/providers/deno-deploy, + https://nitro.build/deploy/providers/genezio + diff --git a/.llm/runs/plan-unified-runtime--seed/evidence/nitro-vs-own-live-2026-07-18.md b/.llm/runs/plan-unified-runtime--seed/evidence/nitro-vs-own-live-2026-07-18.md new file mode 100644 index 000000000..3365b6f67 --- /dev/null +++ b/.llm/runs/plan-unified-runtime--seed/evidence/nitro-vs-own-live-2026-07-18.md @@ -0,0 +1,50 @@ +# Nitro versus own-layer live evidence + +Retrieved: 2026-07-18. This committed extract records the portions of live upstream documentation +used by `../research/nitro-vs-own.md`. It is a paraphrased evidence ledger; the linked pages remain +the primary sources. + +## Nitro + +- Nitro v3 is a public beta. Its beta announcement says the build moved to Rolldown and Vite 8, with + HMR, code splitting, tree shaking, minification, route compilation, and a generated `.output` + directory. H3 v2 is its Web-standards HTTP layer and Nitro can host another framework. Source: + https://nitro.build/blog/v3-beta +- Nitro produces deployment-specific output formats. The deploy guide documents a default Node + output, preset selection/auto-detection, and provider compatibility dates; Nitro recommends + testing before advancing the date because provider behavior changes. Source: + https://nitro.build/deploy +- The provider index documents roughly twenty provider families/recipes. They are not represented as + one uniform maturity tier: some are direct presets, some are auto-detected integrations, and some + deployment pages describe multiple variants. Source: https://nitro.build/deploy +- Cloudflare's `cloudflare_module` output is deployed or previewed with Wrangler. Nitro exposes + Cloudflare runtime hooks (including scheduled, queue, email, tail, and trace handlers), can emit + exports, can translate `scheduledTasks` into Cron Triggers, and can generate Pages routing + metadata. Source: https://nitro.build/deploy/providers/cloudflare +- Vercel has a `vercel` preset, route/function configuration, route rewrites, scheduled-task to Cron + generation, and queue hooks. The provider page also records an API-route caveat. Source: + https://nitro.build/deploy/providers/vercel +- AWS Lambda has an `aws_lambda` preset whose output includes `.output/server/index.mjs` as an + event/response handler. The page documents dynamic chunks, optional import inlining, and a + streaming option. Source: https://nitro.build/deploy/providers/aws + +## Provider output contracts NetScript would otherwise own + +- A Cloudflare Worker module exports a `fetch(request, env, ctx)` handler returning a `Response`; + `env` carries bindings and `ctx` supplies lifecycle methods such as `waitUntil`. Source: + https://developers.cloudflare.com/workers/runtime-apis/handlers/fetch/ +- Wrangler configuration is the deployment source of truth and declares such inputs as the worker + name, entry `main`, compatibility date, routes, environments, assets, and resource bindings. The + documentation includes KV, R2, and D1 binding/provisioning behavior and notes that bindings are + not inherited by environments. Source: + https://developers.cloudflare.com/workers/wrangler/configuration/ +- Vercel's Build Output API reserves `.vercel/output/static` for static files and represents each + function as a `.func` directory containing `.vc-config.json`; files outside the specified output + structure are ignored. Source: https://vercel.com/docs/build-output-api/primitives +- Vercel's Build Output configuration controls routing and the deployment-level output contract. + Source: https://vercel.com/docs/build-output-api/configuration +- AWS Lambda TypeScript handlers follow the exported-handler convention. TypeScript must be + transpiled, and the deployment package must contain the handler and its runtime dependencies; AWS + documents bundling as a packaging option. Sources: + https://docs.aws.amazon.com/lambda/latest/dg/typescript-handler.html and + https://docs.aws.amazon.com/lambda/latest/dg/typescript-package.html diff --git a/.llm/runs/plan-unified-runtime--seed/evidence/nitro-vs-own-rev2-live-2026-07-18.md b/.llm/runs/plan-unified-runtime--seed/evidence/nitro-vs-own-rev2-live-2026-07-18.md new file mode 100644 index 000000000..737690546 --- /dev/null +++ b/.llm/runs/plan-unified-runtime--seed/evidence/nitro-vs-own-rev2-live-2026-07-18.md @@ -0,0 +1,65 @@ +# Nitro versus own-layer rev2 — owner-linked live evidence + +Retrieved: 2026-07-18. This committed extract preserves the source facts used by +`../research/nitro-vs-own-rev2.md`. It paraphrases the linked pages; URLs are the primary sources. + +## Deno-native and provider-native deployment tools + +- `lowlighter/vercel-deno` supports Deno 2.x, local `vercel dev`, `Deno.ServeHandler`, default + `Deno.serve` exports, Deno version selection, permissions, environment variables, and asset + pre-caching. Its README describes it as a standards-aligned rewrite of an unmaintained prior + runtime and configures functions through `vercel.json`. Deno is available only during function + execution unless the build separately installs it. At retrieval it showed 20 commits, 11 stars, + and no open issues or pull requests; those are a maintenance-risk signal, not a quality verdict. + Source: https://github.com/lowlighter/vercel-deno +- Denoflare is a Deno CLI for Cloudflare Workers that avoids a Node/npm/Wrangler requirement. On + Deno 2 it bundles with esbuild plus esbuild-deno-loader. It supports R2 and advertises + experimental multi-platform output for Deno Deploy, Lambda, and Supabase. Source: + https://denoflare.dev/ +- Deno's official Wrangler tutorial points a Wrangler config directly at `src/mod.ts`, pins a + compatibility date, and adds Wrangler dev/deploy tasks to `deno.json`. This proves a Deno source + project can use Cloudflare's official deploy path without Nitro. Source: + https://docs.deno.com/examples/cloudflare_workers_wrangler_tutorial/ +- Cloudflare's Vite plugin runs Worker code in workerd for development parity, exposes runtime APIs + and bindings, builds frontend assets, supports HMR and preview, and covers standalone and + multi-Worker applications. Source: https://developers.cloudflare.com/workers/vite-plugin/ +- Miniflare accepts Worker scripts/modules, module resolution rules, compatibility dates and flags, + and local binding configuration. It is part of Cloudflare's workers-sdk. Source: + https://github.com/cloudflare/workers-sdk/tree/main/packages/miniflare +- AWS Lambda Web Adapter runs any HTTP/1.0 or HTTP/1.1 application on Lambda and supports API + Gateway REST/HTTP APIs, Function URLs, ALB, managed/custom runtimes, OCI images, graceful + shutdown, binary responses, compression, streaming, multi-tenancy and non-HTTP triggers. The same + image can run on Lambda, EC2, Fargate, and locally; the repository includes a Deno Oak zip + example. Source: https://github.com/aws/aws-lambda-web-adapter +- A January 2025 community experiment runs Deno through the AWS Node runtime processing loop with a + Lambda layer and `AWS_LAMBDA_EXEC_WRAPPER`. It reports needing `--allow-all`, unstable Node + compatibility flags, and disabling a telemetry file descriptor. This is useful proof of + feasibility but is not a sound default production contract. Source: + https://zaccharles.medium.com/run-typescript-deno-natively-in-aws-lambda-995c77221a60 + +## Cloudflare provider suite + +- Workers Cache can serve cached HTTP responses without executing Worker code; the Worker controls + it through standard HTTP cache directives. Source: + https://developers.cloudflare.com/workers/cache/ +- Cloudflare Queues documents guaranteed delivery, batching, retries, delays, dead-letter queues, + and pull consumers. Source: https://developers.cloudflare.com/queues/ +- Durable Objects combine named compute with attached, strongly consistent storage and expose + transactional/serializable storage, alarms, and WebSocket hibernation. Source: + https://developers.cloudflare.com/durable-objects/ +- Workers KV is global low-latency key-value storage accessed through a Worker binding or REST API; + the binding exposes put/get/list/delete operations and is declared in Wrangler configuration. + Source: https://developers.cloudflare.com/kv/ + +## AWS provider suite + +- Lambda event-source mappings poll SQS and invoke a function with message batches. Delivery is at + least once, duplicates can occur, idempotency is required, failed batches reappear after the + visibility timeout, and partial batch failure reporting is supported. Source: + https://docs.aws.amazon.com/lambda/latest/dg/with-sqs.html +- Lambda event-source mappings cover queues and streams including SQS, Kinesis, DynamoDB Streams, + Kafka, Amazon MQ, and DocumentDB change streams. AWS documents extended workflow handling through + durable functions and intermediary invocation. Source: + https://docs.aws.amazon.com/lambda/latest/dg/durable-invoking-esm.html +- AWS Step Functions provides more sophisticated workflow error handling than Lambda retry alone. + Source: https://docs.aws.amazon.com/lambda/latest/dg/with-step-functions.html diff --git a/.llm/runs/plan-unified-runtime--seed/evidence/orpc-fresh-live-2026-07-18.md b/.llm/runs/plan-unified-runtime--seed/evidence/orpc-fresh-live-2026-07-18.md new file mode 100644 index 000000000..e21871889 --- /dev/null +++ b/.llm/runs/plan-unified-runtime--seed/evidence/orpc-fresh-live-2026-07-18.md @@ -0,0 +1,36 @@ +# oRPC + Fresh live-doc extracts (fetched 2026-07-18) + +These extracts preserve the load-bearing parts of the live documentation used by +`research/orpc-fresh.md`. URLs are the citation authority; wording below is a concise extract, +not a verbatim archive. + +## oRPC H3 adapter + +Source: https://orpc.dev/docs/adapters/h3 + +- The page currently carries an “oRPC v2 public beta” banner. +- The H3 example imports `H3`/`serve` from `h3` and `RPCHandler` from + `@orpc/server/fetch`. +- It installs an H3 route at `/rpc/**`, passes `event.req` to + `handler.handle(..., { prefix: "/rpc", context: {} })`, and returns the adapter response when + the handler reports a match. + +## oRPC Fetch/HTTP adapter + +Source: https://orpc.dev/docs/adapters/http + +- The Fetch adapter targets Fetch-API runtimes including browsers, Bun, Deno, and Cloudflare + Workers. +- `RPCHandler` accepts a Web `Request` through `handler.handle(request, options)` and yields a + response/match result; the Deno example passes that bridge directly to `Deno.serve`. + +## Fresh App + +Source: https://usefresh.dev/docs/concepts/app + +- Fresh applies middleware and routes in registration order, from top to bottom. +- `mountApp()` composes one Fresh application into another. +- `app.handler()` converts the application into a Web `Request` → `Response` handler; the docs + explicitly identify embedding Fresh in another framework as a use case. +- `app.listen()` starts `Deno.serve`; the docs warn not to use it together with the default + Vite/`deno serve` startup because that would start a second listener. diff --git a/.llm/runs/plan-unified-runtime--seed/evidence/pr822-frame-2026-07-18.md b/.llm/runs/plan-unified-runtime--seed/evidence/pr822-frame-2026-07-18.md new file mode 100644 index 000000000..a71715d93 --- /dev/null +++ b/.llm/runs/plan-unified-runtime--seed/evidence/pr822-frame-2026-07-18.md @@ -0,0 +1,50 @@ +# PR #822 frame extracts (retrieved 2026-07-18) + +PR: https://github.com/rickylabs/netscript/pull/822 + +Files were retrieved from PR head `49bd014f11b44ae7fe8a461f936123e139016cbf` because the +requested run directory is not present in the Stage-B checkout. + +## RFC §3 + +Source: +https://github.com/rickylabs/netscript/blob/49bd014f11b44ae7fe8a461f936123e139016cbf/.llm/runs/rfc-single-deployment--orchestrator/rfc.md + +- The target is one distributable application in which logical services can run inside one + process while retaining service boundaries. +- The RFC chooses a singleton graph/window plus optional sidecars and states that a backend should + remain in-process unless a constraint earns a graph edge. +- Its product/default direction is “default to single-runtime; earn the graph.” + +## Plan §D shared contract + +Source: +https://github.com/rickylabs/netscript/blob/49bd014f11b44ae7fe8a461f936123e139016cbf/.llm/runs/rfc-single-deployment--orchestrator/plan.md + +Section D describes shared rows for client transport, discovery, data layout, packaging, updates, +provisioning, and telemetry. It identifies legitimate divergence for process supervision, +cache/queue backing, update mechanics, and health shape. In the singleton side, it describes: + +- transport switching from HTTP/loopback to in-process; +- singleton discovery through a composition root; +- shared cache/queue backing as in-memory/in-process; +- one Deno desktop packaging pipeline plus K sidecars (K may be zero); +- one update manifest/mechanism. + +## Issue frame + +- #327 D1 (2026-07-03) proposed a Deno-native Nitro v3 WATCH track and stated that its scope + excluded sagas: https://github.com/rickylabs/netscript/issues/327 +- #823 defines a runtime-agnostic Nitro v3 epic, asks for the full adapter surface, deploy + presets, macro services, and absorption of #451/#453/#454/#455: + https://github.com/rickylabs/netscript/issues/823 +- #824 asks for a unified-runtime planning board and explicitly marks the earlier D1 constraint + stale: https://github.com/rickylabs/netscript/issues/824 +- #451 expects an in-process oRPC `RPCLink`/`ServiceApp.fetch` path with the same API shape: + https://github.com/rickylabs/netscript/issues/451 +- #453 proposes `@tursodatabase/tursodb` as the single-writer embedded default at the composition + root: https://github.com/rickylabs/netscript/issues/453 +- #454 defines true single-process mode as zero loopback HTTP and zero external service processes + for mounted backends: https://github.com/rickylabs/netscript/issues/454 +- #455 narrows offline-first to the Turso Sync option: + https://github.com/rickylabs/netscript/issues/455 diff --git a/.llm/runs/plan-unified-runtime--seed/nitro-vs-own-synthesis.md b/.llm/runs/plan-unified-runtime--seed/nitro-vs-own-synthesis.md new file mode 100644 index 000000000..bbf222060 --- /dev/null +++ b/.llm/runs/plan-unified-runtime--seed/nitro-vs-own-synthesis.md @@ -0,0 +1,51 @@ +# Supervisor synthesis — build-vs-own after adversarial round 3 (2026-07-18) + +Inputs: `research/nitro-vs-own.md` (rev1, HYBRID), owner conditional steer, `nitro-vs-own-rev2.md` +(provider-native HYBRID), `adversarial-nitro-vs-own.md` (Sol·max: 3 BLOCKER / 3 MAJOR / 1 MINOR — +ALL ACCEPTED). + +## What survives all three rounds (stable ground) + +1. The owner's decision RULE is ratified as board doctrine: **per target, the provider-native + wrapper wins over a Nitro preset iff it passes the same conformance suite, exposes every + required native binding/event/config surface, and costs less to maintain.** Nitro never enters + the composition contract or leaf ports; whatever emits, emits behind the NetScript-owned + deploy/emitter port. (rev1 §5, rev2 verdict, unchallenged by the adversary.) +2. NetScript ports stay authoritative; provider primitives are capability-scoped backings at most + (adversary F3 sharpens this: CF Queues' push model ≠ `listen()` loop; KV no-CAS ⇒ capability + rejection; DO storage ≠ saga correlation index — each is a FEASIBILITY question, not a mapping + exercise). +3. Docker-image long tail (Koyeb/Sevalla/Coolify/Dokploy/Fly.io/…) = thin adapters on the existing + Aspire/Docker lane (#346 lineage) — uncontested. + +## What the adversary demolished (accepted) + +- The CF/AWS "flip to owned families" is UNPROVEN for v1: AWS evidence is an HTTP sidecar + + raw-event tunnel (F1); CF's "Deno-compatible" path is provider-owned Node tooling callable from + Deno, with Miniflare fidelity limits omitted (F2); the wrapped-native estimates are arithmetic + assertions that exclude work their own acceptance rule requires (F4); vercel-deno is + research-only (F7). +- `@netscript/deploy` as sketched is a god-object with a dependency cycle risk; it needs a real + architecture card (package/import graph, adapter-registration ownership) before adoption (F5). +- Rev2's UR delta is NOT a filable branch — the canonical bodies are Nitro-specific throughout; + adopting provider-native HYBRID for v1 means a full canonical re-branch + another + adversarial/PLAN-EVAL cycle (F6). + +## Owner fork N1 (added to the Stage-H brief) + +- **N1-A (recommended): file the locked board + feasibility cards + the rule.** File UR-0…UR-12/ + DD-RESEARCH as locked (Nitro-scoped v1 cells — honest to the evidence we HAVE), plus three new + cards: CF-PROBE (owned-adapter feasibility: Wrangler/Vite/Miniflare wrap, live-target probes, + per-primitive capability verdicts vs the port contracts), AWS-PROBE (split: HTTP hosting probe + via Lambda Web Adapter; SQS/event conformance design as its own card), DEPLOY-ARCH (the + `@netscript/deploy` package/import-graph design, folded into or beside UR-11). Encode the owner + rule in UR-6/UR-12 acceptance ("any cell's emitter is replaceable by a provider-native wrapper + that passes the same conformance"). The probes produce exactly the evidence a later flip needs; + no unproven architecture is filed. +- **N1-B: commission the full provider-native canonical branch now** (all bodies/DAG/briefs/ + manifest redone under the flip) + adversarial + PLAN-EVAL before Stage-H. Larger, delays filing, + and files an architecture whose feasibility evidence doesn't exist yet (the adversary's core + point). + +N1-A keeps every door open: if CF-PROBE/AWS-PROBE come back green, the flip lands as an evidenced +amendment; if not, the board never lied. Awaiting the owner's N1 pick alongside F-1…F-17/SC-1…SC-6. diff --git a/.llm/runs/plan-unified-runtime--seed/plan-eval-prompt.md b/.llm/runs/plan-unified-runtime--seed/plan-eval-prompt.md new file mode 100644 index 000000000..7b5e12087 --- /dev/null +++ b/.llm/runs/plan-unified-runtime--seed/plan-eval-prompt.md @@ -0,0 +1,42 @@ +use harness. You are the Stage-G PLAN-EVAL evaluator for seed run `plan-unified-runtime--seed` +(issue #824) — a SEPARATE session from every lane that authored or reviewed this plan (Fable +supervisor, Sol corpus/reviewer, Opus packs). You are an open model (qwen/qwen3.7-max) on the +`formal_evaluation` lane. + +## SKILL + +Read in order: `.llm/harness/evaluator/plan-protocol.md`, `.llm/harness/gates/plan-gate.md`, +`.llm/harness/workflow/seed-run.md` (stage contracts — this is a SEED run: the deliverable is a +board, not code). Then in `/home/codex/repos/wt-g8-seed/.llm/runs/plan-unified-runtime--seed/`: +`supervisor.md`, `research/` (7 files) + `evidence/SHA256SUMS`, `synthesis.md`, `plan.md`, +`design/canonical/` (UR-0…UR-12, DD-RESEARCH, slot-map), the three `design/D*/` packs, +`adversarial-findings.md` + `adversarial-triage.md` + `adversarial-recheck.md`. + +## Task + +Evaluate the LOCKED seed plan at board altitude: +- Plan-Gate boxes as applicable to a seed run (research current + cited; decisions locked; + owner-fork sweep complete with NOTHING silently taken; risk register; deferred scope; the + "commit slices" box maps to the canonical slot artifacts + resumable filing manifest). +- Evidence-citation gate (seed-run stage B): spot-check at least 5 load-bearing citations + including one live URL (the Deno Deploy sunset claim) and one `deno doc` claim. +- Verify the Stage-F cycle closed honestly: pick 3 of the 9 original BLOCKERs and confirm the + fix is real in the artifacts (not just claimed in the recheck). +- Verify the drafts-only boundary: zero board mutation anywhere in the manifest before owner + ratification; the label-parity PR is a gated prerequisite. + +Write `/home/codex/repos/wt-g8-seed/.llm/runs/plan-unified-runtime--seed/plan-eval.md` from +`.llm/harness/templates/plan-eval.md`. Emit `PASS` or `FAIL_PLAN` with specific unchecked +items. Do NOT commit/push/modify other files. End with the single verdict word on its own line. + +## Stop-lines (HARD — repeated verbatim) + +1. Merge requires CI green + opposite-family eval PASS on the PR. Owner granted standing beta-11 + merge authorization (2026-07-17 in-turn) once that bar is met. +2. HARD STOP before any release publish (`release:cut`, JSR publish, tag push, canary or stable) + — owner sign-off in-turn only; a stale or relayed approval does not count. +3. HARD STOP before closing milestone 13 — owner sign-off only. +4. These stop-lines are repeated verbatim in EVERY sub-agent brief. A sub-brief without the + stop-lines section is invalid. +5. The #824 seed run is drafts-only until owner ratification; its board filing needs the owner + in-turn. diff --git a/.llm/runs/plan-unified-runtime--seed/plan-eval.md b/.llm/runs/plan-unified-runtime--seed/plan-eval.md new file mode 100644 index 000000000..ef3c70a84 --- /dev/null +++ b/.llm/runs/plan-unified-runtime--seed/plan-eval.md @@ -0,0 +1,65 @@ +# PLAN-EVAL — plan-unified-runtime--seed + +- Plan evaluator session: OpenRouter `qwen/qwen3.7-max` via `claude-openrouter`, 2026-07-18 (Stage-G evaluator lane, `formal_evaluation`). +- Run: `plan-unified-runtime--seed` (#824) +- Surface / archetype: seed run (planning-only; no package publication) +- Scope overlays: cross-cutting refactor over service / SDK / CLI-config / database-KV-queue / plugin-runtime / Fresh surfaces; per-package doctrine archetype and JSR gates delegated to the UR-11 architecture-contracts prerequisite card. + +## Checklist results + +| Plan-Gate item | Result | Evidence / location | +| --------------------------------------- | ------ | ------------------- | +| Research present and current | PASS | `research/` holds 7 topic files (nitro-v3, adapter-mapping, orpc-fresh, sagas-constraint, drift-ledger, market, deno-deploy-new) dated 2026-07-18 and re-baselined against `origin/main` @ 56cf84b5 (post-#847). Every load-bearing claim cites a URL, a `deno doc` surface, or a repo path+line. The Stage-F residual concern that dated extracts were absent (finding 15) is RESOLVED per the recheck: `evidence/SHA256SUMS` covers 6 extracts and `sha256sum -c` passes all of them (`market-frameworks`, `netscript-deno-doc`, `nitro-v3-live`, `orpc-fresh-live`, `pr822-frame`, `deno-deploy-new-live`). | +| Decisions locked | PASS | 12 locked decisions (L1–L12) in `plan.md` §Locked decisions, each with rationale and canonical-file source citations. | +| Open-decision sweep | PASS | F-1…F-17 + SC-1…SC-6 in `plan.md` §Owner-fork sweep and `design/D3-board-mechanics/decision-brief.md`. Every fork is numbered, default stated, and source-attributed. Body-changing forks (F-3, F-4, F-5, F-7, F-8, F-10 plus F-1, F-2, F-16) carry explicit A/B deltas inline in the relevant `design/canonical/UR-.md` under `## Fork deltas`. F-12 branch-B delta is materialized at `decision-brief.md:68` explicitly addressing the recheck's residual concern. | +| Commit slices (< 30, gate + files each) | PASS | For a seed run the "commit slices" box maps to the canonical slot artifacts + the resumable filing manifest: 13 canonical `design/canonical/UR-0…UR-12.md` files + `DD-RESEARCH.md` + `slot-map.md` with merge transforms; 14-row DAG create order in `filing-manifest.md` Step 4 (well under 30); each row names the exact label set, milestone, and the gates it proves (`- [ ] gate:` boxes in every canonical `## Body`). The manifest at `:83-88` specifies per-slot idempotency (slot marker), search-before-create, immediate per-slot FILING-LOG append, read-after-write, and preflight failure on a missing status or a label absent from `.github/labels.yml`. | +| Risk register | PASS | 7 risks with mitigations in `plan.md` §Risk register, including Deno Deploy withdrawal, Nitro beta churn, oRPC v2 pin, preset-claim rot, lifecycle hook loss, filing duplication, and board drift — each mapped to a specific slice or rework lane. | +| Gate set selected | PASS | Seed-run gate matrix in `plan.md` §Gate matrix names Stage-F, Stage-E rework, Stage-F re-verification, Stage-G (this verdict), Stage-H ratification, label-parity prerequisite, and KEEP-only reconciliation. Per-package doctrine archetype/fitness/JSR/E2E gates are explicitly assigned to the UR-11 architecture-contracts prerequisite card (`design/canonical/UR-11.md:27-30, 50`), which blocks UR-1/UR-4/UR-5 — so no implementation lane starts without the gate matrix settled. | +| Deferred scope explicit | PASS | DD-RESEARCH successor card (deno_deploy re-proof, `0.0.1-stable`, F-2); #455 offline-sync implementation (`0.0.1-stable` or `Backlog / Triage`, F-10); `@netscript/data` facade (deferred unless owner commissions, F-8); WebSocket/upgrade scope (deferred to post-v1 cell proof, F-4); externalized sagas (v1.1, F-3). Every defer site has a named milestone or fork control. | +| jsr-audit surface scan (pkg/plugin) | N/A | This is a seed planning run with no package publication. UR-11 architecture-contracts card names package/export/JSR surface gates as an acceptance-gated prerequisite (`design/canonical/UR-11.md:49-53`) — the JSR bar is enforced before any implementation lane starts, not at the seed stage. | + +## Open-decision sweep (evaluator-run) + +No open decisions found that would force rework if deferred. Every load-bearing fork I checked either carries explicit A/B deltas in the canonical file (so a selection is filed from the committed artifact) or is a label/naming/milestone choice that the manifest's compare-before-edit guards already handle. The recheck's residual concern about F-12 branch B changing the issue count is explicitly materialized at `decision-brief.md:68` (UR-6a/b/c slot-template branch with markers and slot-map +3 rows) — that is a committed plan artifact, not improvisation after ratification. + +## Evidence-citation gate (seed-run stage B — 5 spot-checks) + +1. **Deno Deploy sunset claim (live URL).** `research/deno-deploy-new.md:10` and the committed evidence extract `deno-deploy-new-live-2026-07-18.md` both say Classic/`deployctl` sunset **2026-07-20**, sourced from `https://docs.deno.com/deploy/migration_guide/`. CONFIRMED. +2. **`deno doc` claim.** `evidence/netscript-deno-doc-2026-07-18.md` records 11 exact `deno doc --filter` commands over `packages/kv`, `queue`, `database`, `service`, `plugin-workers-core`, `plugin-sagas-core`, `plugin-triggers-core`, `plugin-streams-core` modules with the returned surface. `research/sagas-constraint.md:33` cites `deno doc --filter SagaDefinition packages/plugin-sagas-core/mod.ts` as the source of the durable-tier shape. CONFIRMED. +3. **`service-builder-impl.ts:423-432` (build returns only ServiceApp).** Repo `packages/service/src/builder/service-builder-impl.ts:427-433` confirmed — `build()` calls `installAuth`, `installDeferredRoutes`, `notFound`, `onError`, and `return this.app`. No lifecycle hooks executed. CONFIRMED. +4. **`service-builder-impl.ts:501-521` (hooks run only in serve()).** Repo lines 506-522 confirmed — `serve()` runs `startupHooks` before `build()`, wraps the app with `startServiceListener`, and passes `shutdownHooks` to it. `build()` itself does not. CONFIRMED. +5. **`service-shutdown.ts:1-135` (ServiceShutdownCoordinator).** File exists at 179 lines (the cited range is a subset); `DEFAULT_DRAIN_TIMEOUT_MS` appears 3 times. CONFIRMED. +6. **oRPC pin `^1.14.6`.** `packages/service/deno.json:21-22` pins `@orpc/server: "npm:@orpc/server@^1.14.6"` and `@orpc/openapi: "npm:@orpc/openapi@^1.14.6"`. CONFIRMED. + +## Stage-F cycle honesty (spot-check 3 of 9 BLOCKERs) + +1. **F1 — C2/`deno_deploy` withdrawal.** Adversarial finding 1 said the plan validated a platform being shut down. Triage accepted: C2 leaves v1 cell set, replaced by a research card. Verified in canonical artifacts: `UR-6.md:32-39` explicitly withdraws `deno_deploy` from v1 with dated reason (sunset 2026-07-20), gates "deno_deploy produces **no** v1 capability claim", and defers re-entry to DD-RESEARCH. `DD-RESEARCH.md` is a separately-milestoned successor (`0.0.1-stable`) with four concrete reproducible-proof gates and a dependency on UR-6 (so re-entry cannot bypass the v1 conformance harness). The recheck rates this RESOLVED. **Honest closure.** +2. **F2 — #451 over-fold into UR-4.** Adversarial finding 2 said the fold would lose the public SDK contract. Triage accepted: UR-4 = host bridge only, no `Closes #451`, O-1 restored. Verified: `UR-4.md:31-40,49,53-60` limits UR-4 to host-side bridge, removes the `Closes #451` keyword, adds a KEEP note, and restores the SDK↔service direction as fork F-7. The recheck rates this RESOLVED. **Honest closure.** +3. **F5 — hostable lifecycle bypass.** Adversarial finding 5 said D1 would silently lose `.onStartup()`/`.onShutdown()` hooks. Triage accepted: new UR-0 prerequisite. Verified: `UR-0.md:26-44` specifies build/start/stop hostable contract, explicitly reuses `ServiceShutdownCoordinator` (idempotency/abort/drain/LIFO/ShutdownReport), preserves startup-hook ordering and startup-failure rollback, and gates UR-2. `D1-2` agent brief at lines 57-62 of `D1/agent-briefs.md` directs the lane to consume UR-0's surface and forbids inventing a bespoke disposer. The recheck rated this PARTIALLY-RESOLVED citing D1-briefs.md:58-62, but the verbatim text at those lines actually reads "invokes the **UR-0 hostable-service lifecycle contract** (which reuses the shipped `ServiceShutdownCoordinator` policy — idempotency, bounded drain, LIFO, structured report). Do NOT invent a bespoke disposer registry (Stage-F finding 5)" — which is the correct fix. The residual concern is mis-read; the artifact is correct. **Honest closure.** + +## Drafts-only boundary verification + +- `design/D3-board-mechanics/decision-brief.md` H1: `DRAFT — owner ratifies in-turn at Stage-H`. +- `design/D3-board-mechanics/filing-manifest.md` H1: `DRAFT — executes only after owner in-turn ratification of decision-brief.md`. +- Manifest `§Step 0` pre-flight (`:38-47`) makes PLAN-EVAL PASS and in-turn ratification a hard gate before any mutation. +- Manifest `§Step 1` (`:49-60`) makes the `epic:unified-runtime` label-parity PR a **GATED PREREQUISITE** — filing explicitly may not begin until it is merged (CI green + opposite-family eval PASS per Stop-line 1). The transaction has **no** step that proceeds on an unmerged parity PR. +- Manifest `§Step 5` (`:122-152`) reconciliation is KEEP-only with a drafted #327 non-closing addendum text. Zero filing-time closes. +- No issue, epic, milestone, or label has been mutated by this run. The run's own draft PR is the only writable GitHub surface (per `supervisor.md:29-31` and the seed-run doctrine). + +## Notes + +The Stage-F recheck at `f85d4919` rated 13/17 findings RESOLVED, 4 PARTIALLY-RESOLVED, and raised 3 NEW findings (2 MAJOR, 1 MINOR). None rise to plan-level failure: + +- **NEW-1 (duplicate idempotency marker).** The recheck claimed whole-file publishing would duplicate the marker. The manifest at `:10-14` and `:83-88` is explicit: publish ONLY the `## Body` section, never the metadata header. The file-scope marker in `UR-6.md:1` lives outside `## Body` (it is above the H1 at line 3); the body-scope marker at line 17 is the only instance in the publishable region. This finding is a mis-read of the manifest, not a plan defect. +- **NEW-2 (F-2 branch B dependency cycle).** UR-6's fork delta F-2 at `UR-6.md:63-69` addresses this explicitly: branch B keeps UR-6 at three cells in both branches and creates a SEPARATE UR-6-EXT successor extension card after DD-RESEARCH passes. No cycle. The plan is consistent. +- **NEW-3 (UR-6 title says "four-cell" vs three-cell v1).** Real minor wording inconsistency at `UR-6.md:3`. The acceptance gates at `:51-54` correctly say three v1 cells. The title could be adjusted at Stage-H filing or in a trivial canonical edit — not a blocker. + +The PARTIALLY-RESOLVED recheck concerns (F1, F5, F8, F12) were all re-verified above and either the residual concern is a mis-read or the manifest already addresses it. + +Overall: a well-defended, evidence-cited, adversarially-tested seed plan. The decision brief is fully materialized, the canonical slot artifacts are deterministic, the filing manifest is resumable, and the drafts-only boundary is preserved. Implementation may begin after owner ratification in-turn at Stage-H. + +## Verdict + +`PASS` + +PASS diff --git a/.llm/runs/plan-unified-runtime--seed/plan.md b/.llm/runs/plan-unified-runtime--seed/plan.md new file mode 100644 index 000000000..7d2b6b47f --- /dev/null +++ b/.llm/runs/plan-unified-runtime--seed/plan.md @@ -0,0 +1,80 @@ +# Plan (Stage E lock — Stage-F rework applied) — plan-unified-runtime--seed (#824) + +Integrated from `synthesis.md` + the three Stage-D packs and the **Stage-F rework** (17 accepted +findings; dispositions in `adversarial-triage.md`). Authoritative issue bodies are +`design/canonical/UR-.md` + `design/canonical/DD-RESEARCH.md`; draft→slot transforms in +`design/canonical/slot-map.md`; the resumable filer in `design/D3-board-mechanics/filing-manifest.md`. +Authority: GitHub + owner ratification win on conflict. DRAFTS-ONLY until Stage H. + +## Locked decisions + +| ID | Decision | Source | +| --- | --- | --- | +| L1 | Logical composition root is the universal invariant; physical one-process execution is a per-preset capability; the surviving cross-preset rule is "no application-created loopback". | synthesis §1/3; D1 proposal; drift D-01/D-02 | +| L2 | Nitro owns the sole listener/lifecycle; Fresh mounts via `app.handler()` (never `listen()`); disposal drains once via the Nitro `close` hook **through the UR-0 hostable-service lifecycle contract**, which reuses the shipped `ServiceShutdownCoordinator` policy (idempotency, bounded drain, LIFO, structured report) — not a bespoke second registry. | D1 proposal; drift D-10; Stage-F F5 | +| L3 | oRPC bridge = in-process delegation over `ServiceApp.fetch` — invocation placement, no second codec; H3-bridge conformance gate; oRPC generation pinned (shipped ^1.14.6). **UR-4 is the host-side bridge only — a subset of #451's SDK transport surface.** | D1 proposal; drift D-07/D-11; Stage-F F2 | +| L4 | Sagas capability rule replaces the stale #327-D1 exclusion: in-process only via the NetScript saga runtime; per-preset `supported \| externalized \| rejected`; externalized = macro-service split, never Nitro-task substitution. **#327 gets a non-closing addendum recording this.** | sagas-constraint.md; D2 proposal; Stage-F F13 | +| L5 | **Three** v1 runtime cells: `deno_server`, `node_server`, `cloudflare_module` (isolate representative — owner may swap, F-1). **`deno_deploy` is WITHDRAWN from v1** (Deno Deploy Classic/`deployctl` sunset 2026-07-20; new platform lacks Deno queues) → deferred to the **DD-RESEARCH** successor card; re-entry is fork **F-2**. | D2 proposal; nitro-v3.md; Stage-F F1 | +| L6 | NetScript ports stay authoritative; Nitro primitives are host bindings with L/P/U mappings; build-time hard-fail on `unsupported`, warn on `partial`, never silent downgrade. | D2 proposal; drift D-03/D-06 | +| L7 | Writer-ownership/locks (D-08) and offline sync (D-09) are declared database capabilities/profiles, not runtime invariants. | D2 proposal | +| L8 | Board + code language normalizes to shipped `@netscript/database`; no `@netscript/data` facade in v1 unless the owner commissions one (F-8). Naming ownership is recorded in the **UR-11 architecture-contracts** card. | adapter-mapping.md; drift D-12; Stage-F F14 | +| L9 | Epic #823 decomposes into the **UR-0…UR-12** skeleton (namespace normalized; UR-H → UR-12; new UR-0 lifecycle + UR-11 architecture-contracts prerequisites) with the D3 DAG. **Supersession: all KEEP, zero filing-time closes** — #451 KEEP (UR-4 subset), #453 KEEP (UR-7 foundation), #454 KEEP + non-closing addendum (UR-10 foundation), #455 KEEP (UR-8 foundation), #327 KEEP + non-closing addendum, #349 confirm-superseded + status-label fix. Folds land only via each issue's own downstream `Closes #N` PR. | D3 proposal; canonical/slot-map.md; Stage-F F2/F3/F4/F13/F16/F17 | +| L10 | Filing is a **resumable transaction** from `filing-manifest.md`: the `epic:unified-runtime` label-parity PR is a **gated prerequisite merged before filing**; each slot uses a stable marker + search-before-create, immediate per-slot FILING-LOG append, read-after-write verification, and compare-before-edit guards on legacy bodies. | D3 manifest; Stage-F F9/F10 | +| L11 | **One milestone train:** all UR-0…UR-12 at `0.0.1-beta.13`; deferred cells/impl (DD-RESEARCH, #455 offline-sync impl) split into separately-milestoned successors at `0.0.1-stable`. | D3 proposal §3; Stage-F F11 | +| L12 | Stage-I lanes get the **UR-11 architecture-contracts** prerequisite (package/export ownership, doctrine archetype + gate matrix, composition-compiler requirement schema + build seam) before starting. | Stage-F F14 | + +## Owner-fork sweep (renumbered once — identical to `design/D3-board-mechanics/decision-brief.md`) + +Defaults stated; every fork awaits the owner in-turn. Forks that change an issue **body** carry an +explicit A/B delta in the relevant `design/canonical/UR-.md` under `## Fork deltas`. + +| F# | Fork | Default | +| --- | --- | --- | +| F-1 | Isolate representative cell: `cloudflare_module` vs vercel/netlify_edge/aws_lambda | keep cloudflare_module | +| F-2 | v1 cell set: 3-cell vs re-proven `deno_deploy` (via DD-RESEARCH) later | 3-cell v1; DD-RESEARCH at stable | +| F-3 | Bounded-window sagas: ship `externalized` macro-service path vs reject-only | reject-only v1, externalized v1.1 | +| F-4 | WebSocket/upgrade scope in v1 vs deferred | defer to post-v1 cell proof | +| F-5 | Static-asset ownership (Fresh-owns-islands vs Nitro-owns-all) | Fresh-owns-islands | +| F-6 | oRPC: hold ^1.14.x pin vs authorize v2-beta spike | hold pin | +| F-7 | SDK↔service dependency direction (import `type` vs mirror structural shape) — restored #451 O-1 | import `type` (reuse shipped port) | +| F-8 | `@netscript/database` normalization vs new `@netscript/data` facade card | normalize, no facade | +| F-9 | One milestone train — all UR at beta.13; deferred cells/impl → separately-milestoned successors | as stated | +| F-10 | Offline-sync #455 **impl** home: `0.0.1-stable` vs `Backlog / Triage` (UR-8 profile ships beta.13) | `0.0.1-stable` | +| F-11 | Epic slug/label: `epic:unified-runtime` vs `epic:deployment` | unified-runtime (keep epic:deployment too) | +| F-12 | UR-6 granularity: single matrix card w/ per-cell acceptance vs one-per-cell | single matrix card | +| F-13 | `epic:unified-runtime` label-parity PR as a gated prerequisite (merged before filing) | yes | +| F-14 | Desktop consumer boundary: UR-7/UR-10 foundations; #453/#454/#455 KEEP; consumer on #830 | boundary holds; KEEP legacy issues | +| F-15 | Milestone inventory: create none beyond verifying 0.0.1-stable/beta.14 exist | create none | +| F-16 | #454 non-closing acceptance addendum (scope single-process to in-process-capable presets) | yes (append, not close) | +| F-17 | #327 non-closing saga-supersession addendum + #349 terminal status-label correction | yes to both | +| SC-1..6 | Supersession confirmations (#451/#453/#454/#455/#349/#327 — all KEEP, zero closes) | confirm | + +## Cross-epic DAG & milestone train + +`design/canonical/slot-map.md` + D3 proposal §4 are normative. Prerequisites: **UR-11** (architecture +contracts) precedes UR-1/UR-4/UR-5; **UR-0** (lifecycle) precedes UR-2. Spine (D1): UR-1→UR-2→UR-3; +UR-4 joins. Matrix (D2): UR-5→{UR-6, UR-7, UR-9}; UR-4+UR-7→UR-10→UR-8. Acceptance: UR-6+UR-10 + the +KEEP reconciliation → UR-12. The legacy dependency chain (#451→#454, #453→#454, #454→#455) maps to +the prerequisite edges UR-4→UR-10, UR-7→UR-10, UR-10→UR-8 (edges, not folds). **One train:** all +UR-0…UR-12 at `0.0.1-beta.13`; DD-RESEARCH and #455 offline-sync impl at `0.0.1-stable`. + +## Risk register + +| Risk | Mitigation | +| --- | --- | +| Nitro v3 beta churn invalidates cards | version + compatibility-date pin card (UR-6 gate); corpus evidence re-fetched + committed (Stage-F F15 lane) | +| Deno Deploy new-platform reality (Classic/`deployctl` sunset) | `deno_deploy` withdrawn from v1; DD-RESEARCH re-proves before re-entry (F-2) | +| oRPC v2 lands mid-train | F-6 pin + H3 conformance gate isolates | +| Preset capability claims rot | per-cell conformance gates executed per preset, not asserted | +| Hosted service silently loses lifecycle hooks | UR-0 lifecycle contract precedes UR-2; reuses `ServiceShutdownCoordinator` | +| Filing leaves duplicates/half-edits on failure | resumable transaction: slot markers, search-before-create, per-slot log, read-after-write, compare-before-edit (L10) | +| Board drift vs live issues | Stage-H manifest pre-flight re-verifies every live body; authority banners after filing | + +## Gate matrix (seed run) + +Stage-F adversarial review (distinct model, unoriented) → **Stage-E rework** (this lock) → focused +Stage-F re-verification → Stage-G PLAN-EVAL (open-model, separate session, hard stop) → Stage-H owner +ratification in-turn → resumable filing (label-parity PR merged first) → FILING-LOG + KEEP-only +reconciliation edits → Stage-I handoff briefs from GitHub + packs. Per-package doctrine +archetype/fitness/JSR/E2E gates for the implementation lanes are defined in the UR-11 +architecture-contracts card (Stage-F F14), not this seed-workflow matrix. diff --git a/.llm/runs/plan-unified-runtime--seed/research/adapter-mapping.md b/.llm/runs/plan-unified-runtime--seed/research/adapter-mapping.md new file mode 100644 index 000000000..1e87b5adb --- /dev/null +++ b/.llm/runs/plan-unified-runtime--seed/research/adapter-mapping.md @@ -0,0 +1,42 @@ +# Nitro ↔ shipped NetScript adapter mapping + +Evidence date: 2026-07-18. `deno doc` command extracts are preserved at +`../evidence/netscript-deno-doc-2026-07-18.md`; Nitro live-doc extracts are at +`../evidence/nitro-v3-live-2026-07-18.md`. + +The task's “data” package is not a shipped package name. The shipped manifest is +`@netscript/database`, with database ports and PostgreSQL/MSSQL/MySQL adapter exports +(`packages/database/deno.json:2-13`). The mapping therefore uses `@netscript/database` and records +the naming drift rather than inventing an `@netscript/data` surface. + +## Capability matrix + +Every row cites both sides. A `deno doc` command is a public-surface citation, not a claim inferred +from implementation internals. + +| Capability | Nitro surface | Shipped NetScript surface | Fit / gap | +| ---------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| SQL connection/query | Experimental db0 `useDatabase`; SQLite default for dev/Node-compatible production; connector override. ([Nitro database](https://nitro.build/docs/database)) | `@netscript/database` `DatabaseAdapter`: connect/disconnect, health/status, raw query; provider adapters in its export map. (`deno doc --filter DatabaseAdapter packages/database/mod.ts`; `packages/database/deno.json:5-13`) | **Partial fit.** Nitro can supply a host/provider connection, but NetScript owns health, lifecycle, telemetry, Prisma-driver and transaction contracts. A bridge must be explicit per connector. | +| KV CRUD/TTL/list | unstorage `useStorage` over driver mounts; volatile memory default. ([Nitro storage](https://nitro.build/docs/storage)) | `KvStore`: get/set(TTL)/delete/has/list/batch/close. (`deno doc --filter KvStore packages/kv/mod.ts`) | **Good structural fit** for basic operations. Add a `nitro` adapter behind `KvStore`; never expose unstorage directly to application code. | +| KV atomics/consistency | Driver-dependent storage abstraction; live page does not promise NetScript-style CAS or consistency on every mount. ([Nitro storage](https://nitro.build/docs/storage)) | `KvStore.atomic` supports version checks/mutations; list carries strong/eventual consistency; Deno KV and memory implementations ship. (`deno doc --filter KvStore packages/kv/mod.ts`; `packages/kv/deno.json:5-10`) | **Gap.** Capability negotiation is required; mounts without CAS cannot back saga/trigger/idempotency state that requires it. | +| KV watch/reactivity | Storage page documents watch but driver behavior varies. ([Nitro storage](https://nitro.build/docs/storage)) | `WatchableKv` has fixed-key and prefix watch; the root package documents native vs polling behavior. (`deno doc --filter WatchableKv packages/kv/mod.ts`) | **Partial.** Bridge only where the chosen driver supplies a sound watch; otherwise use an explicit polling adapter and document cost/latency. | +| Response/function cache | ocache `defineCachedHandler`/`defineCachedFunction`, route rules, TTL, conditional responses and dedupe. ([Nitro cache](https://nitro.build/docs/cache)) | NetScript has general KV and package-specific state stores, not a shipped HTTP-response-cache facade (`deno doc packages/kv/mod.ts`; `packages/kv/deno.json:5-10`). | **Nitro-native win.** Use Nitro cache for host HTTP/function caching; do not conflate it with durable KV/workflow state. | +| Queue enqueue/consume | Nitro tasks can be invoked/scheduled but are named operations, not a documented message-queue contract. ([Nitro tasks](https://nitro.build/docs/tasks)) | `MessageQueue`: enqueue/batch, delayed options, long-running listen, graceful stop, native retry flag; Deno KV, Redis, AMQP, PostgreSQL and DLQ exports ship. (`deno doc --filter MessageQueue packages/queue/mod.ts`; `packages/queue/deno.json:5-19`) | **NetScript strictly broader.** Keep `@netscript/queue`; a Nitro task runner may dispatch into it but cannot replace delivery/consumer semantics. | +| Retry and DLQ | Task errors propagate to callers; live task docs do not define attempt ledgers, backoff, ack/nack, or DLQ. ([Nitro tasks](https://nitro.build/docs/tasks)) | Queue ports expose native-retry capability plus DLQ stores; trigger core exposes retry, DLQ, idempotency, event status/store. (`deno doc packages/queue/mod.ts`; `deno doc packages/plugin-triggers-core/mod.ts`) | **Gap.** Nitro is execution plumbing; NetScript remains the durability/control plane. | +| Cron scheduling | `scheduledTasks` maps cron expressions to tasks; croner on process presets and native Cloudflare/Vercel generation. ([Nitro tasks](https://nitro.build/docs/tasks)) | Worker core exposes cron/job/task/workflow definitions; trigger core exposes scheduled triggers, scheduler port, next-fire calculation, backfill and enabled-state contracts. (`deno doc packages/plugin-workers-core/mod.ts`; `deno doc packages/plugin-triggers-core/mod.ts`) | **Complementary.** Nitro is a preset-aware clock/activation adapter; NetScript owns definition, event record, backfill, retries and dispatch. | +| One-off task execution | `defineTask`/`runTask` with payload/context/result; one active call per task name. ([Nitro tasks](https://nitro.build/docs/tasks)) | Worker core exposes `defineTask` plus an explicit start/stop workers runtime. (`deno doc packages/plugin-workers-core/mod.ts`; `deno doc --filter createWorkersRuntime packages/plugin-workers-core/mod.ts`) | **Good bridge candidate**, but naming/concurrency semantics need an adapter and conformance tests. Nitro's same-name coalescing must not silently change a worker definition's expected concurrency. | +| Durable workflow | No durable transition/history/store contract is stated by Nitro tasks. ([Nitro tasks](https://nitro.build/docs/tasks)) | Worker core exports workflow/state/store/executor/shutdown primitives. (`deno doc packages/plugin-workers-core/mod.ts`; `packages/plugin-workers-core/deno.json:5-22`) | **Gap.** Keep workflow runtime above Nitro. | +| Saga state machine | No saga/correlation/compensation/outbox semantics in Nitro tasks. ([Nitro tasks](https://nitro.build/docs/tasks)) | `SagaDefinition` includes durability, correlations, handlers, compensations, signals, queries, retry, concurrency and schedule; store/transport/idempotency/outbox ports ship. (`deno doc --filter SagaDefinition packages/plugin-sagas-core/mod.ts`; `deno doc --filter SagaStorePort packages/plugin-sagas-core/src/ports/mod.ts`; `deno doc --filter SagaTransportPort packages/plugin-sagas-core/src/ports/mod.ts`) | **No direct fit; composition fit is viable.** Run sagas inside the Nitro process with NetScript state/transport adapters. Nitro tasks may wake or call them, not replace them. | +| Trigger ingestion/processing | Nitro routes, lifecycle hooks, schedules, WebSockets and provider hooks provide ingress/activation points. ([lifecycle](https://nitro.build/docs/lifecycle), [tasks](https://nitro.build/docs/tasks), [WebSocket](https://nitro.build/docs/websocket)) | Trigger core ships webhook/file/manual/queue/stream/scheduled definitions, processor/scheduler, ingress, verifier, retry, DLQ, idempotency, event store/subscription and backfill. (`deno doc packages/plugin-triggers-core/mod.ts`; `deno doc --filter TriggerProcessorPort packages/plugin-triggers-core/mod.ts`) | **Adapter fit.** Nitro supplies ingress clocks/transports; NetScript owns normalized events and durable processing. | +| Realtime WebSocket/pub-sub | CrossWS/H3 WebSockets across Node/Bun/Deno/Cloudflare; namespaces, topics, peers and lifecycle hooks. ([Nitro WebSocket](https://nitro.build/docs/websocket)) | Stream core is a durable State Protocol producer with schema, upsert/delete/flush/close, service discovery and auth. (`deno doc --filter StreamProducerPort packages/plugin-streams-core/mod.ts`; `deno doc packages/plugin-streams-core/mod.ts`) | **Transport overlap, semantic gap.** Nitro pub/sub is connection-scoped; NetScript streams are durable state/event publication. Bridge delivery without downgrading persistence. | +| Request/RPC hosting | H3 routes/lifecycle; Nitro server entry and renderer are Fetch/Web-standard oriented. ([lifecycle](https://nitro.build/docs/lifecycle)) | `@netscript/service` builds a mountable `ServiceApp.fetch(Request)` and returns oRPC `FetchHandler`; today the builder uses Hono internally. (`deno doc --filter FetchHandler packages/service/mod.ts`; `packages/service/src/types.ts:13-20`; `packages/service/src/primitives/handlers.ts:115-143`) | **Strong seam, host mismatch.** Mount the existing fetch/oRPC handler into Nitro/H3. Avoid exposing H3 or Hono in the application contract. | +| Startup/shutdown | Plugins register `request`/`response`/`error`/`close`; presets can augment hooks. ([Nitro lifecycle](https://nitro.build/docs/lifecycle), [plugins](https://nitro.build/docs/plugins)) | Service, workers, saga transport, trigger processor and stream producer all expose explicit stop/close/drain surfaces. (`deno doc packages/service/mod.ts`; `deno doc --filter createWorkersRuntime packages/plugin-workers-core/mod.ts`; `deno doc --filter SagaTransportPort packages/plugin-sagas-core/src/ports/mod.ts`; `deno doc --filter TriggerProcessorPort packages/plugin-triggers-core/mod.ts`; `deno doc --filter StreamProducerPort packages/plugin-streams-core/mod.ts`) | **Bridge required.** One composition root must order start, close, drain and failure reporting. Nitro's single `close` hook is the host trigger, not the ownership model. | + +## Adapter boundary recommended by the evidence + +Nitro should sit in the **adapter/presentation host layer**. NetScript package contracts remain the +application-facing ports, consistent with the doctrine's single composition-root rule +(`docs/architecture/doctrine/07-composition-and-extension.md:15-37`) and named lifecycle/failure +requirements (`docs/architecture/doctrine/08-runtime-state-failure.md:17-25`). This is not an +implementation plan; it is the smallest mapping that preserves the shipped public guarantees cited +above. diff --git a/.llm/runs/plan-unified-runtime--seed/research/deno-deploy-new.md b/.llm/runs/plan-unified-runtime--seed/research/deno-deploy-new.md new file mode 100644 index 000000000..77236f3ac --- /dev/null +++ b/.llm/runs/plan-unified-runtime--seed/research/deno-deploy-new.md @@ -0,0 +1,121 @@ +# New Deno Deploy and the C2 runtime cell + +Research date: 2026-07-18. The committed evidence snapshot is +`../evidence/deno-deploy-new-live-2026-07-18.md`; original URLs remain authoritative. This responds +to Stage-F adversarial finding 1 and disposition 1. (`../adversarial-findings.md:3-8`, +`../adversarial-triage.md:9-9`) + +## The platform identity changed + +The Nitro `deno_deploy` provider page validates Deno Deploy Classic, not the surviving platform. It +directs users to `dash.deno.com`, obtains a Classic token, runs `deployctl`, and offers the +`denoland/deployctl@v1` action. +([Nitro Deno Deploy provider](https://nitro.build/deploy/providers/deno-deploy)) Official Deno +documentation says Classic shuts down on **2026-07-20**, Classic projects are not transferred, and +`deployctl` is sunset in favor of `deno deploy` on the new `console.deno.com` platform. +([migration guide](https://docs.deno.com/deploy/migration_guide/)) + +The new Deno Deploy is a new Deno 2.0 execution environment and application/build model, not a +renamed Classic dashboard. Its unit is one deployed web service with one build configuration, and +its build pipeline runs install/build, prepares an artifact, warms the dynamic entrypoint, and then +routes the revision. ([platform overview](https://docs.deno.com/deploy/), +[getting started](https://docs.deno.com/deploy/getting_started/), +[build reference](https://docs.deno.com/deploy/reference/builds/)) + +## What a Nitro v3 output would need + +No official page currently demonstrates Nitro's `deno_deploy` output on the new platform. The +minimum candidate configuration below is therefore a **probe specification**, not a validated +deployment recipe. The new platform documents custom install/build commands and a dynamic +JavaScript/TypeScript entrypoint; Nitro documents a Node-driven build that emits +`.output/server/index.ts`. +([Deno Deploy getting started](https://docs.deno.com/deploy/getting_started/), +[Nitro Deno Deploy provider](https://nitro.build/deploy/providers/deno-deploy)) + +| Requirement | Candidate new-platform realization | Proof still required | +| ------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| App/build mode | Create a dynamic app with no assumed first-class Nitro preset; configure an install command and `NITRO_PRESET=deno_deploy` build command. The platform supports custom install/build configuration. ([getting started](https://docs.deno.com/deploy/getting_started/)) | Prove the integrated builder has the exact Node/package-manager/toolchain versions required by Nitro v3 and that the monorepo can be staged. GitHub monorepos are currently documented as unsupported. ([getting started](https://docs.deno.com/deploy/getting_started/)) | +| Entrypoint | Point the dynamic entrypoint at Nitro's emitted `.output/server/index.ts`. Nitro names that output; Deno Deploy accepts a relative JS/TS dynamic entrypoint. ([Nitro provider](https://nitro.build/deploy/providers/deno-deploy), [getting started](https://docs.deno.com/deploy/getting_started/)) | Prove the emitted entrypoint uses the built-in `Deno.serve()` path and survives the platform warmup. The migration guide says legacy std `serve()` times out during warmup. ([migration guide](https://docs.deno.com/deploy/migration_guide/)) | +| Artifact and assets | Preserve `.output/server` plus Nitro public assets in the prepared deployment artifact; Deno Deploy's build stage prepares an artifact and its app config has a static-directory field. ([build reference](https://docs.deno.com/deploy/reference/builds/), [getting started](https://docs.deno.com/deploy/getting_started/)) | Prove Nitro's routing/static behavior from the dynamic entrypoint rather than assuming the platform static directory can replace Nitro's asset pipeline. | +| CLI/CI | Replace every `deployctl`/Classic action instruction with `deno deploy` or a linked new-platform build. Deno documents both triggers. ([migration guide](https://docs.deno.com/deploy/migration_guide/), [build reference](https://docs.deno.com/deploy/reference/builds/)) | Prove a repeatable create/configure/deploy command sequence, preview/production timeline selection, rollback, and read-after-deploy health check. | +| Runtime surface | Exercise HTTP, streaming, errors, shutdown/lifecycle expectations, WebSocket upgrades if retained, scheduled tasks, and telemetry in the new Deno 2.0 environment. The platform advertises Deno/Node apps, cron, logs, traces, and metrics. ([platform overview](https://docs.deno.com/deploy/)) | Nitro's provider page contains no new-platform conformance result, and Nitro task docs do not name a native Deno Deploy scheduler integration. ([Nitro provider](https://nitro.build/deploy/providers/deno-deploy), [Nitro tasks](https://nitro.build/docs/tasks)) | + +The repository is a monorepo, while the current GitHub onboarding docs say monorepos are not yet +supported. (`deno.json:1-40`, +[Deno Deploy getting started](https://docs.deno.com/deploy/getting_started/)) A probe must therefore +test a supported local-source/CLI staging flow or a deliberately extracted artifact repository; it +cannot claim the documented GitHub path works for this checkout. +([`deno deploy` CLI](https://docs.deno.com/runtime/reference/cli/deploy/)) + +## Queue verdict: native C2 is lossy + +The new platform explicitly marks queues unsupported, and the migration guide states that both +`Deno.Kv.enqueue()` and `Deno.Kv.listenQueue()` are unavailable. It directs queue users to an +external message service or database-backed job queue. +([platform comparison](https://docs.deno.com/deploy/), +[migration guide](https://docs.deno.com/deploy/migration_guide/)) + +That cannot satisfy the shipped `MessageQueue` contract natively: NetScript requires enqueue, +delayed options, long-running consumption, acknowledgements/negative acknowledgements, retry +capability, and graceful stop. (`packages/queue/ports/message-queue.ts:39-133`) C2 can only recover +that surface by selecting and proving an external adapter such as the shipped Redis, AMQP, or +PostgreSQL exports; no such binding has been deployed or conformance-tested on the new platform. +(`packages/queue/deno.json:5-19`) + +**Finding:** any matrix row that marks C2 queue enqueue/consume “lossless” from Deno KV is false for +the new platform. The database-backed alternative is a new architecture choice and test burden, not +a rename of the removed queue API. +([migration guide](https://docs.deno.com/deploy/migration_guide/), +`packages/queue/ports/message-queue.ts:39-133`) + +## Database and KV availability + +The new platform does support databases. It documents assigned Deno KV, managed Prisma Postgres, and +linked external databases; its CLI can provision/assign KV and link/assign PostgreSQL. +([database reference](https://docs.deno.com/deploy/reference/databases/), +[`deno deploy` database commands](https://docs.deno.com/runtime/reference/cli/deploy/#database-management-1)) +Deno KV connects through `Deno.openKv()` and receives per-timeline isolation after assignment. +([Deno KV reference](https://docs.deno.com/deploy/reference/deno_kv/)) + +These are viable inputs to future NetScript database/KV adapter probes, but they do not validate +Nitro db0 configuration or NetScript's complete database/KV contracts automatically. Nitro's +database layer is experimental, while NetScript requires database lifecycle/health/raw-query +semantics and KV atomic/list/disposal semantics. +([Nitro database](https://nitro.build/docs/database), +`packages/database/ports/database-client.ts:80-127`, `packages/kv/types/kv-store.ts:19-194`) + +| Capability | Current platform evidence | C2 status | +| ------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- | +| Deno KV CRUD/atomic/list | Deno KV is assignable per app/timeline and opened with `Deno.openKv()`. ([Deno KV reference](https://docs.deno.com/deploy/reference/deno_kv/)) | **Candidate, unproved:** run the NetScript KV conformance suite against an assigned new-platform database. | +| SQL/Postgres | Managed Prisma Postgres and linked external databases are documented, with injected connection details. ([database reference](https://docs.deno.com/deploy/reference/databases/)) | **Candidate, unproved:** select an adapter/driver, migration path, pooling assumptions, and run database conformance. | +| Queue over Deno KV | Enqueue/listenQueue are explicitly unsupported. ([migration guide](https://docs.deno.com/deploy/migration_guide/)) | **Rejected.** It cannot be a native C2 queue cell. | +| External queue | Deno recommends an external message queue or database-backed job queue when migrating. ([migration guide](https://docs.deno.com/deploy/migration_guide/)) | **Research required:** select a shipped NetScript adapter and prove connectivity, delivery, retry/DLQ, lifecycle, and preview/production isolation. | + +## C2 verdict + +**C2 is not provable for v1 from current evidence and must leave the validated v1 cell set.** The +only Nitro deployment instructions target a platform and CLI that sunset on 2026-07-20; the new +platform has no official Nitro recipe, currently blocks the documented GitHub-monorepo path, and +does not support queues. ([Nitro provider](https://nitro.build/deploy/providers/deno-deploy), +[migration guide](https://docs.deno.com/deploy/migration_guide/), +[getting started](https://docs.deno.com/deploy/getting_started/)) + +Replace C2 with a planning research card: **“Prove Nitro v3 on new Deno Deploy.”** It must produce a +real new-platform deployment and record: + +1. supported source/staging path for this monorepo, exact app/build/entrypoint configuration, and + `deno deploy`/GitHub lifecycle; +2. warmup plus HTTP/static/stream/error/lifecycle/telemetry conformance; +3. explicit KV and SQL selections with NetScript conformance results; +4. an external queue selection with enqueue/consume/retry/DLQ/drain proof, because native queues are + unavailable; +5. cron/task behavior and preview/production isolation; and +6. artifact/rollback/health evidence with exact tool and platform versions. + +Those requirements follow from the new platform's build, database, queue, and migration contracts. +([build reference](https://docs.deno.com/deploy/reference/builds/), +[database reference](https://docs.deno.com/deploy/reference/databases/), +[platform overview](https://docs.deno.com/deploy/), +[migration guide](https://docs.deno.com/deploy/migration_guide/)) Until that card passes, the owner +fork is the triaged one: ship a three-cell v1 matrix, or re-admit C2 only after this proof—not by +assuming the Classic preset survived. (`../adversarial-triage.md:9-9`) diff --git a/.llm/runs/plan-unified-runtime--seed/research/drift-ledger.md b/.llm/runs/plan-unified-runtime--seed/research/drift-ledger.md new file mode 100644 index 000000000..8ed1ef7de --- /dev/null +++ b/.llm/runs/plan-unified-runtime--seed/research/drift-ledger.md @@ -0,0 +1,39 @@ +# Unified-runtime drift ledger + +Research date: 2026-07-18. This ledger compares current evidence with PR #822 RFC §3/plan §D and the +issue corpus. The PR files were retrieved from head `49bd014f11b44ae7fe8a461f936123e139016cbf`; a +provenance extract is preserved at `../evidence/pr822-frame-2026-07-18.md`. + +“Drift” here means a candidate the supervisor must resolve in the planning board. It does not by +itself declare the older text wrong. + +| ID | Earlier frame | Live reality | Drift candidate / supervisor disposition | +| ---- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| D-01 | RFC §3 uses “single-runtime” to mean logical services inside one process, with sidecars only when a constraint earns an edge. ([PR #822 RFC §3](https://github.com/rickylabs/netscript/blob/49bd014f11b44ae7fe8a461f936123e139016cbf/.llm/runs/rfc-single-deployment--orchestrator/rfc.md)) | Nitro deploy presets can produce a Node server, provider/serverless output, or clustered execution, and native scheduled-task integration is preset-dependent. ([Nitro deploy](https://nitro.build/deploy), [Nitro tasks](https://nitro.build/guide/tasks)) | Split the invariant into **one logical composition root** and an optional **one-process realization**. Do not promise physical process identity across cloud presets. | +| D-02 | Issue #454 defines true single-process mode as zero loopback HTTP and zero external service processes for mounted backends. ([issue #454](https://github.com/rickylabs/netscript/issues/454)) | A Nitro provider may execute routes/functions or schedules in provider-managed units; the application cannot assert their OS-process identity. ([Nitro deploy](https://nitro.build/deploy), [Nitro tasks](https://nitro.build/guide/tasks)) | Scope #454's physical guarantee to presets that advertise an in-process capability; cloud/serverless presets should guarantee logical composition and no application-created loopback, not one provider process. | +| D-03 | Plan §D describes singleton cache/queue backing as “in-memory/in-process.” ([PR #822 plan §D](https://github.com/rickylabs/netscript/blob/49bd014f11b44ae7fe8a461f936123e139016cbf/.llm/runs/rfc-single-deployment--orchestrator/plan.md)) | NetScript ships backend-neutral KV and queue contracts with atomic/disposal and ack/nack/retry/listener semantics; Nitro storage defaults to memory and Nitro tasks are one-off task execution, not a message-queue contract. (`packages/kv/types/kv-store.ts:19-98`, `packages/queue/ports/message-queue.ts:39-133`, [Nitro storage](https://nitro.build/guide/storage), [Nitro tasks](https://nitro.build/guide/tasks)) | Remove volatility from the definition of “in-process.” A single process may still use durable provider-backed KV/queue; capability and durability policy must select the backing. | +| D-04 | Plan §D describes one Deno desktop packaging pipeline with K sidecars and one update manifest/mechanism. ([PR #822 plan §D](https://github.com/rickylabs/netscript/blob/49bd014f11b44ae7fe8a461f936123e139016cbf/.llm/runs/rfc-single-deployment--orchestrator/plan.md)) | Issue #823 expands the target to runtime-agnostic cloud deploy presets, while Nitro compiles provider-specific output and the Deno server preset is built with Node before being launched with Deno. ([issue #823](https://github.com/rickylabs/netscript/issues/823), [Nitro deploy](https://nitro.build/deploy), [Nitro Deno preset](https://nitro.build/deploy/runtimes/deno)) | Treat desktop update/install mechanics as one target adapter, not a shared invariant. The shared contract should be an artifact/topology manifest; each preset owns distribution and rollout mechanics. | +| D-05 | #327 D1 categorically says the Nitro v3 track excludes sagas. ([issue #327](https://github.com/rickylabs/netscript/issues/327)) | Nitro v3 has experimental tasks, scheduled tasks, preset-native schedulers, and same-name concurrency coalescing, but it does not document durable saga state, compensation, transactional outbox, idempotency reservations, or queue delivery semantics. ([Nitro tasks](https://nitro.build/guide/tasks), `packages/plugin-sagas-core/src/ports/saga-store-port.ts:1-49`, `packages/plugin-sagas-core/src/domain/saga-definition.ts:1-57`) | Replace “excludes sagas” with a capability rule: sagas may run under Nitro when NetScript's durable store/transport/outbox/idempotency ports are supplied; Nitro tasks alone do not satisfy them. See `sagas-constraint.md`. | +| D-06 | Issue #823 asks for Nitro's “full adapter surface,” alongside NetScript service/data/plugin integration. ([issue #823](https://github.com/rickylabs/netscript/issues/823)) | Nitro database and tasks are experimental; Nitro storage defaults to memory; its task API is not NetScript's shipped queue/worker/saga contract. ([Nitro database](https://nitro.build/guide/database), [Nitro storage](https://nitro.build/guide/storage), [Nitro tasks](https://nitro.build/guide/tasks), `packages/queue/ports/message-queue.ts:80-133`) | Define “full surface” as host bindings and capability mappings, not replacement of shipped ports. Board cards must state adapter ownership and lossless/partial/unsupported mappings. | +| D-07 | Plan §D frames client transport as a switch between loopback HTTP and an in-process transport; #451 proposes in-process oRPC `RPCLink` over `ServiceApp.fetch`. ([PR #822 plan §D](https://github.com/rickylabs/netscript/blob/49bd014f11b44ae7fe8a461f936123e139016cbf/.llm/runs/rfc-single-deployment--orchestrator/plan.md), [issue #451](https://github.com/rickylabs/netscript/issues/451)) | The shipped service already exposes Web `fetch`, and oRPC's H3 adapter forwards the H3 request into its Fetch `RPCHandler`; this is in-memory delegation while preserving HTTP Request/Response semantics. (`packages/service/src/types.ts:13-20`, [oRPC H3 adapter](https://orpc.dev/docs/adapters/h3)) | Model transport as invocation placement plus a stable Fetch/RPC contract, not necessarily two codecs. Require “no socket loopback” without inventing a second protocol path. | +| D-08 | #453 assumes the embedded single-writer TursoDB default lives at the composition root. ([issue #453](https://github.com/rickylabs/netscript/issues/453)) | RFC §3 itself says exclusive locks and single-writer databases are constraints that can earn a graph edge; Nitro's development database defaults to local SQLite and documents provider bindings separately. ([PR #822 RFC §3](https://github.com/rickylabs/netscript/blob/49bd014f11b44ae7fe8a461f936123e139016cbf/.llm/runs/rfc-single-deployment--orchestrator/rfc.md), [Nitro database](https://nitro.build/guide/database)) | Make writer ownership and lock compatibility a declared database capability. “Default embedded” must not silently override topology constraints. | +| D-09 | #455 selects Turso Sync as the offline-first direction and #823 absorbs it into the broader Nitro epic. ([issue #455](https://github.com/rickylabs/netscript/issues/455), [issue #823](https://github.com/rickylabs/netscript/issues/823)) | Nitro's database layer is experimental and based on db0, with local SQLite as a development/default-node-compatible path; it does not document Turso Sync/offline replication as a universal preset feature. ([Nitro database](https://nitro.build/guide/database)) | Keep offline sync as a database-target capability/profile, not a unified-runtime invariant or an assumption attached to every Nitro preset. | +| D-10 | The RFC's one-process picture implies a single HTTP owner, while #823 combines Fresh UI and Nitro hosting. ([PR #822 RFC §3](https://github.com/rickylabs/netscript/blob/49bd014f11b44ae7fe8a461f936123e139016cbf/.llm/runs/rfc-single-deployment--orchestrator/rfc.md), [issue #823](https://github.com/rickylabs/netscript/issues/823)) | Fresh `app.handler()` supports embedding in another framework, but `app.listen()` starts `Deno.serve` and must not be used alongside another startup path. ([Fresh App docs](https://usefresh.dev/docs/concepts/app)) | State explicitly that Nitro owns the listener/lifecycle and mounts the Fresh handler. Add route/static ownership and “no nested listen” acceptance tests. | +| D-11 | #823 names oRPC + Fresh integration without a version qualification. ([issue #823](https://github.com/rickylabs/netscript/issues/823)) | NetScript pins oRPC `^1.14.6`, while the live oRPC H3 documentation currently carries a v2 public-beta banner. (`packages/service/deno.json:10-20`, [oRPC H3 adapter](https://orpc.dev/docs/adapters/h3)) | Pin the implementation lane's oRPC generation and add an H3 bridge conformance test; do not plan directly against an unqualified live beta example. | +| D-12 | #823 calls the data integration `@netscript/data`. ([issue #823](https://github.com/rickylabs/netscript/issues/823)) | The shipped workspace package and documented public surface are `@netscript/database`, with `DatabaseAdapter` in `packages/database/ports/database-client.ts`. (`packages/database/deno.json:1-20`, `packages/database/ports/database-client.ts:80-127`) | Normalize board language and dependencies to shipped package names; if `@netscript/data` is intended as a new facade, it requires an explicit contract card rather than an assumed mapping. | + +## Supervisor-level reconciliation + +The load-bearing correction is to make **logical graph identity** the universal invariant and make +**physical one-process execution** a preset capability. That preserves RFC §3's “earn the graph” +default while remaining honest about Nitro's provider-specific builds and native scheduled-task +execution. +([PR #822 RFC §3](https://github.com/rickylabs/netscript/blob/49bd014f11b44ae7fe8a461f936123e139016cbf/.llm/runs/rfc-single-deployment--orchestrator/rfc.md), +[Nitro deploy](https://nitro.build/deploy), [Nitro tasks](https://nitro.build/guide/tasks)) + +The second correction is to keep Nitro as host/integration infrastructure and NetScript ports as the +application contracts. The live Nitro facilities do not erase the richer shipped semantics for queue +delivery, durable saga state, database lifecycle, or KV atomicity. +(`packages/queue/ports/message-queue.ts:39-133`, +`packages/plugin-sagas-core/src/ports/saga-store-port.ts:1-49`, +`packages/database/ports/database-client.ts:80-127`, `packages/kv/types/kv-store.ts:19-180`) diff --git a/.llm/runs/plan-unified-runtime--seed/research/market.md b/.llm/runs/plan-unified-runtime--seed/research/market.md new file mode 100644 index 000000000..567c74fb0 --- /dev/null +++ b/.llm/runs/plan-unified-runtime--seed/research/market.md @@ -0,0 +1,68 @@ +# Market patterns for unified deployment + +Research date: 2026-07-18. This is the mandatory external leg of Stage B. Fetch extracts are saved +at `../evidence/market-frameworks-live-2026-07-18.md`; original URLs remain the authority. + +## Comparable models + +| Framework | Single/decomposed deployment model | What NetScript can steal | What NetScript must beat | +| ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Nuxt / Nitro | A conventional Node output starts one generated `.output/server/index.mjs`; Nitro can alternatively emit `node_cluster`, PM2-oriented, serverless, and provider-specific output. ([Nuxt deployment](https://nuxt.com/docs/4.x/getting-started/deployment), [Nitro deploy](https://nitro.build/deploy)) | One application model compiled through named presets, with a boring default server artifact and an explicit cluster escape hatch. ([Nuxt deployment](https://nuxt.com/docs/4.x/getting-started/deployment)) | Nitro's preset changes packaging and hosting, but NetScript also has to preserve durable KV/queue/database and background-execution semantics across those targets; Nitro marks database and tasks experimental. ([Nitro database](https://nitro.build/guide/database), [Nitro tasks](https://nitro.build/guide/tasks)) | +| Next.js standalone | `output: "standalone"` emits a minimal server plus output-file-traced dependencies; static/public files require deliberate copying, and monorepos may need an expanded tracing root. ([Next.js output docs](https://nextjs.org/docs/pages/api-reference/config/next-config-js/output)) | Produce a self-describing, minimal deploy artifact from dependency tracing rather than copying the whole workspace. ([Next.js output docs](https://nextjs.org/docs/pages/api-reference/config/next-config-js/output)) | Make assets, migrations, plugin registries, native binaries, and sidecar requirements explicit in the artifact contract; Next's documented static-file and monorepo caveats show why “standalone” alone is not enough. ([Next.js output docs](https://nextjs.org/docs/pages/api-reference/config/next-config-js/output)) | +| React Router 7 framework mode | Deployment may be full-stack, static, Docker, or a provider template. Its adapter contract translates a host request to a Web Fetch `Request`, calls the framework handler, and translates the `Response` back; official targets include Node, Express, and Cloudflare. ([RR deployment](https://reactrouter.com/start/framework/deploying), [RR adapter API](https://reactrouter.com/api/other-api/adapter)) | Standardize the Web Request/Response seam and make host adapters thin, independently testable translations. ([RR adapter API](https://reactrouter.com/api/other-api/adapter)) | Cover background resources and service-to-service composition in the same contract; React Router's published adapter boundary is request-handler focused. ([RR adapter API](https://reactrouter.com/api/other-api/adapter)) | +| SvelteKit | Small build adapters transform one app for automatic providers, official targets, or community targets. `adapter-node` emits `node build`, while environment, proxy trust, and graceful shutdown are documented operator inputs. ([SvelteKit adapters](https://svelte.dev/docs/kit/adapters), [adapter-node](https://svelte.dev/docs/kit/adapter-node)) | Keep provider selection at the build boundary and publish a clear generic-server fallback. ([SvelteKit adapters](https://svelte.dev/docs/kit/adapters)) | Include lifecycle and operator metadata in NetScript's contract—shutdown, trust boundaries, env, health, telemetry—rather than treating a successful build as deployment completeness. ([adapter-node](https://svelte.dev/docs/kit/adapter-node)) | +| Redwood | Redwood separates a static `web` side from API code and supports serverless or serverful deployment; its Docker path runs web and API as distinct units. ([Redwood deployment](https://docs.redwoodjs.com/docs/deploy/introduction), [Redwood Docker](https://docs.redwoodjs.com/docs/docker)) | Preserve one developer project while allowing target-specific web/API artifacts and independently scalable units. ([Redwood deployment](https://docs.redwoodjs.com/docs/deploy/introduction)) | Avoid making the web/API split the only topology. The unified contract should allow true in-process mounting when capabilities permit and deliberate decomposition when they do not. Redwood's documented Docker topology is distinct web/API units. ([Redwood Docker](https://docs.redwoodjs.com/docs/docker)) | +| Wasp | Production is described as three components—a Node server, static client, and PostgreSQL—which may be deployed separately; Wasp generates a server Dockerfile. ([Wasp deployment](https://wasp.sh/docs/deployment/deployment-methods/overview)) | Generate topology-aware deployment artifacts from a higher-level application definition. ([Wasp deployment](https://wasp.sh/docs/deployment/deployment-methods/overview)) | Generalize beyond a fixed client/server/Postgres triplet: NetScript ships database, KV, queue, worker, saga, trigger, and stream contracts whose capability needs vary by target. (`packages/database/ports/database-client.ts:80-127`, `packages/kv/types/kv-store.ts:19-98`, `packages/queue/ports/message-queue.ts:80-133`, `packages/plugin-sagas-core/src/domain/saga-definition.ts:1-57`) | + +## Cross-market contract + +The repeated external pattern is **one source/application model, multiple target adapters, and a +generated artifact whose topology may differ by target**. Nitro, React Router, and SvelteKit all put +target translation at an adapter/preset boundary rather than in application routes. +([Nitro deploy](https://nitro.build/deploy), +[RR adapter API](https://reactrouter.com/api/other-api/adapter), +[SvelteKit adapters](https://svelte.dev/docs/kit/adapters)) Next and Wasp additionally demonstrate +that generated artifacts need explicit dependency/component inventories, not merely an entry file. +([Next.js output docs](https://nextjs.org/docs/pages/api-reference/config/next-config-js/output), +[Wasp deployment](https://wasp.sh/docs/deployment/deployment-methods/overview)) + +The board can therefore steal four concrete rules: + +1. Define a stable Fetch handler boundary for HTTP composition, following React Router's host + translation contract and the shipped NetScript `FetchHandler` surface. + ([RR adapter API](https://reactrouter.com/api/other-api/adapter), + `packages/service/src/types.ts:206-212`) +2. Make target presets pure declarations of capabilities, artifact shape, and operational + requirements; Nitro and SvelteKit make the build adapter the target boundary. + ([Nitro deploy](https://nitro.build/deploy), + [SvelteKit adapters](https://svelte.dev/docs/kit/adapters)) +3. Emit a manifest that lists server entry points, assets, traced dependencies, migrations, durable + resources, schedules, sidecars, and shutdown/health behavior. Next documents the failure modes of + implicit assets and monorepo tracing, while SvelteKit documents runtime operator knobs. + ([Next.js output docs](https://nextjs.org/docs/pages/api-reference/config/next-config-js/output), + [adapter-node](https://svelte.dev/docs/kit/adapter-node)) +4. Treat “single” and “multi” as two realizations of one logical graph, not as separate product + models. Redwood and Wasp keep one project while permitting decomposed deployment, and Nuxt/Nitro + can emit one server or clustered/provider output. + ([Redwood deployment](https://docs.redwoodjs.com/docs/deploy/introduction), + [Wasp deployment](https://wasp.sh/docs/deployment/deployment-methods/overview), + [Nuxt deployment](https://nuxt.com/docs/4.x/getting-started/deployment)) + +## Competitive bar for NetScript + +NetScript should not define “unified” as merely producing one server bundle. Its differentiator is a +**capability-checked composition graph** that can mount HTTP services in-process while retaining the +same logical resource contracts when a database, queue, scheduler, worker, saga, trigger, or stream +must become provider-backed or separately supervised. The need follows from the shipped adapter +surfaces (`packages/database/ports/database-client.ts:80-127`, +`packages/kv/types/kv-store.ts:19-98`, `packages/queue/ports/message-queue.ts:80-133`) and Nitro's +experimental/target-dependent data and task facilities. +([Nitro database](https://nitro.build/guide/database), +[Nitro tasks](https://nitro.build/guide/tasks)) + +The acceptance bar should consequently require the same application graph to either (a) produce a +one-listener local/server artifact when all capabilities fit or (b) reject that preset with a +specific reason and emit a declared multi-unit/provider topology. That is stricter than the +request-only adapter contracts documented by React Router and the fixed component decomposition +documented by Wasp. ([RR adapter API](https://reactrouter.com/api/other-api/adapter), +[Wasp deployment](https://wasp.sh/docs/deployment/deployment-methods/overview)) diff --git a/.llm/runs/plan-unified-runtime--seed/research/nitro-v3.md b/.llm/runs/plan-unified-runtime--seed/research/nitro-v3.md new file mode 100644 index 000000000..45ef37c3e --- /dev/null +++ b/.llm/runs/plan-unified-runtime--seed/research/nitro-v3.md @@ -0,0 +1,74 @@ +# Nitro v3 live validation + +Evidence date: 2026-07-18. The fetched live-doc digest is preserved at +`../evidence/nitro-v3-live-2026-07-18.md`. + +## Verdict + +Nitro v3 is a credible **host/output substrate**, but not yet a production-grade replacement for +NetScript's durable adapters. The v3 line is still public beta; its Deno server path requires a +Node-built output and an `--unstable` Deno launch, while database and tasks are separately +experimental. Those are board-level acceptance risks, not reasons to reject Nitro outright. +([v3 beta](https://nitro.build/blog/v3-beta), +[Deno runtime](https://nitro.build/deploy/runtimes/deno), +[database](https://nitro.build/docs/database), [tasks](https://nitro.build/docs/tasks)) + +## Deno preset maturity and limitations + +| Finding | Consequence for Unified | Evidence | +| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | +| v3 is a public beta with intentional breaking changes; the migration guide is a living beta document. | Pin an exact Nitro v3 version and make upgrade compatibility a board gate. Do not describe the runtime as stable. | [beta announcement](https://nitro.build/blog/v3-beta), [migration guide](https://nitro.build/docs/migration) | +| `deno_server` is built using Node.js and launched with `deno run --unstable --allow-net --allow-read --allow-env .output/server/index.ts`. | “Deno preset” does not mean a Deno-only build pipeline or stable-API-only artifact. CI needs Node for the build and must audit the broad runtime permissions. | [Deno runtime page](https://nitro.build/deploy/runtimes/deno) | +| `deno_deploy` is a separate provider preset and flow, not the same thing as `deno_server`; its documented `dash.deno.com`/`deployctl` flow targets Classic, which shuts down on 2026-07-20. | Do not treat it as a validated new-platform cell; replace C2 with the probe specified in `deno-deploy-new.md`. | [Nitro Deno Deploy page](https://nitro.build/deploy/providers/deno-deploy), [Deno migration guide](https://docs.deno.com/deploy/migration_guide/) | +| Default production output remains Node server; `nitro-dev` is always Node/ESM in an isolated worker. | A Deno target must be selected and tested explicitly; local dev does not prove Deno production compatibility. | [deploy overview](https://nitro.build/deploy) | + +## Full adapter/runtime surface + +| Surface | Live v3 capability | Maturity/limit | Unified implication | Evidence | +| --------------- | --------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------- | +| SQL database | db0-backed `useDatabase`; SQLite default; `sql`, `exec`, `prepare`; configurable connectors. | Entire database layer is experimental. Default SQLite is documented for development and Node-compatible production, not as a universal preset guarantee. | Keep `@netscript/database` as the application contract; a Nitro database bridge is optional and provider-scoped. | [database](https://nitro.build/docs/database) | +| KV/storage | unstorage-backed `useStorage`; named mounts, many drivers, dynamic plugin mounts, watch support where driver permits. | Default storage is in-memory and loses data on restart. Driver semantics vary. | Map Nitro mounts behind `KvStore`; never infer persistence, atomics, watch, or consistency from `useStorage` alone. | [KV storage](https://nitro.build/docs/storage) | +| Cache | `defineCachedHandler`, `defineCachedFunction`, route-rule caching, TTL, conditional responses, deduplication. | GET/HEAD only for handlers; errors/undefined excluded; cached function values JSON-serializable; request headers require `varies`. | Useful host cache, but distinct from general KV and durable workflow state. | [cache](https://nitro.build/docs/cache) | +| Tasks/schedules | `defineTask`, `runTask`, cron `scheduledTasks`; croner on process presets; generated Cloudflare/Vercel schedules; optional `waitUntil`. | Experimental; one running invocation per task name; same-name callers share a result; `waitUntil` is runtime-dependent; more native presets are planned. | Suitable for command execution and cron dispatch. It is not, by itself, a durable queue, retry ledger, workflow engine, or saga store. | [tasks](https://nitro.build/docs/tasks) | +| WebSocket/SSE | CrossWS/H3 handlers across Node, Bun, Deno, Cloudflare; upgrade/open/message/close/error; peers, namespaces, pub/sub; H3 SSE. | Feature opt-in; remote address and underlying behavior are adapter-dependent. | Host real-time endpoints through Nitro, but keep NetScript stream persistence and auth semantics above the transport. | [WebSocket](https://nitro.build/docs/websocket) | +| Lifecycle | `request`, `response`, `error`, `close`; process errors captured; preset augmentation. | Static files run before middleware/routes; request-hook errors are reported but do not stop the pipeline; plugin registration is synchronous. | Define a lifecycle bridge with explicit ordering and cleanup ownership; do not assume Hono/Fresh middleware order matches Nitro. | [lifecycle](https://nitro.build/docs/lifecycle), [plugins](https://nitro.build/docs/plugins) | + +## Cloud deploy presets + +Nitro's output contract is real: the same source is transformed by preset, with selection through +environment, CLI, or config, and a compatibility date pins provider behavior. Auto-detected +providers are AWS Amplify, Azure, Cloudflare, Firebase App Hosting, Netlify, StormKit, Vercel, and +Zeabur. ([deploy overview](https://nitro.build/deploy)) + +Representative first-class pages name these presets: + +| Provider/runtime | Preset(s) | Notable caveat | Evidence | +| ---------------- | --------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------- | +| Deno server | `deno_server` | Node-built; Deno `--unstable` and broad permissions. | [Deno](https://nitro.build/deploy/runtimes/deno) | +| Deno Deploy | `deno_deploy` | Documented flow is Classic-only (`dash.deno.com`/`deployctl`), which sunsets 2026-07-20; new-platform compatibility is unproved. | [Nitro Deno Deploy](https://nitro.build/deploy/providers/deno-deploy), [migration guide](https://docs.deno.com/deploy/migration_guide/) | +| Cloudflare | `cloudflare_module`, `cloudflare_pages` | Module preset is recommended; platform adds scheduled/email/queue/tail/trace hooks. | [Cloudflare](https://nitro.build/deploy/providers/cloudflare) | +| Vercel | `vercel` | `/api` directory conflicts with Vercel conventions; route function rules may be needed. | [Vercel](https://nitro.build/deploy/providers/vercel) | +| Netlify | `netlify`, `netlify_edge` | Edge runtime uses Deno/V8 and differs from function output. | [Netlify](https://nitro.build/deploy/providers/netlify) | +| AWS Lambda | `aws_lambda` | Streaming and dynamic-import behavior require explicit flags. | [AWS Lambda](https://nitro.build/deploy/providers/aws) | +| Azure SWA | `azure-swa` | Generated/custom routing interaction must be tested. | [Azure](https://nitro.build/deploy/providers/azure) | +| Genezio | `genezio` | Explicitly experimental. | [Genezio](https://nitro.build/deploy/providers/genezio) | + +The provider index also documents recipes for Zerops, Koyeb, Zephyr, Heroku, Alwaysdata, Render, +IIS, DigitalOcean, Cleavr, Firebase, GitHub/GitLab Pages, Platform.sh, and others. A documented +provider recipe must not be counted as a distinct runtime preset without its page naming the preset. +([provider index](https://nitro.build/deploy/providers)) + +## Board inputs + +1. Add a Nitro-version/compatibility-date pin and an upgrade conformance gate. This follows directly + from beta maturity and compatibility-date behavior. ([beta](https://nitro.build/blog/v3-beta), + [deploy](https://nitro.build/deploy)) +2. Make `deno_server`, one Node server preset, and at least one proven isolate/serverless preset + separate runtime cells; they do not share identical task, lifecycle, storage, or WebSocket + behavior. Keep `deno_deploy` outside the v1 cells until the new-platform probe in + `deno-deploy-new.md` passes. ([tasks](https://nitro.build/docs/tasks), + [WebSocket](https://nitro.build/docs/websocket), + [Deno migration guide](https://docs.deno.com/deploy/migration_guide/)) +3. Preserve NetScript contracts above Nitro primitives. Database/tasks are experimental and storage + defaults to volatile memory, so direct substitution would silently weaken guarantees. + ([database](https://nitro.build/docs/database), [storage](https://nitro.build/docs/storage)) diff --git a/.llm/runs/plan-unified-runtime--seed/research/nitro-vs-own-rev2.md b/.llm/runs/plan-unified-runtime--seed/research/nitro-vs-own-rev2.md new file mode 100644 index 000000000..2841dc92d --- /dev/null +++ b/.llm/runs/plan-unified-runtime--seed/research/nitro-vs-own-rev2.md @@ -0,0 +1,187 @@ +# Nitro versus own layer — revision 2 + +Evidence date: 2026-07-18. Owner-linked live evidence is preserved at +`../evidence/nitro-vs-own-rev2-live-2026-07-18.md`. This supersedes the recommendation and cost +premise in `nitro-vs-own.md`; it does not mutate the locked board or `plan.md`. + +## Revised verdict + +The owner's condition is correct: **HYBRID is acceptable only when Nitro does not make a target less +native.** Applying that test changes HYBRID from “Nitro for Cloudflare/Vercel/Lambda” to +**provider-native HYBRID**: + +- own the composition, capability and deployment contracts; +- wrap official/provider-native tooling for Cloudflare and AWS; +- use Nitro presets only where no equally maintainable native path exists and only behind the same + deploy port; and +- keep Aspire/Docker for image-based targets. + +This follows both “wrap, do not reinvent” and the repository's already-governed deployment-target +pattern: one stable port, one adapter per target, and a thin CLI router +(`docs/architecture/doctrine/06-archetypes.md:257-299`; +`packages/cli/src/kernel/domain/deploy/deploy-target-port.ts:1-128`; +`packages/cli/src/kernel/extension-points.ts:23-37`). + +## 1. Does Nitro make each target less native? + +“Native” here means that provider configuration, bindings, event types, emulator, compatibility +controls and deployment CLI remain directly available through a NetScript adapter. It does not mean +copying the provider SDK. A wrapper that hides a capability is less native; a wrapper that types and +forwards it is not (`docs/architecture/doctrine/06-archetypes.md:266-275`). + +| Target/tool | Native path evidence | Compared with Nitro | Finding | +| ---------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Vercel / `vercel-deno` | The community runtime accepts `Deno.ServeHandler`/default `Deno.serve`, Deno permissions/version directives, assets and `vercel dev` (`../evidence/nitro-vs-own-rev2-live-2026-07-18.md`). | Nitro supplies a maintained Vercel output, routing, Cron and queue hooks, but builds through its Vite/Rolldown/Node toolchain (`nitro-vs-own.md:27-39`; `../evidence/nitro-vs-own-live-2026-07-18.md`). | **The Deno runtime is more runtime-native, but not yet more maintenance-native.** Its small community footprint and separate build-time Deno install make it an experimental owned adapter, not the v1 default. Nitro remains the safer provisional emitter if conformance proves no required Vercel feature is hidden. | +| Cloudflare / Wrangler Deno path | Deno's tutorial points Wrangler at TypeScript directly. Cloudflare's Vite plugin runs in workerd, exposes bindings/runtime APIs, builds assets and supports multi-Worker apps; Miniflare models modules, bindings and compatibility controls (`../evidence/nitro-vs-own-rev2-live-2026-07-18.md`). | Nitro can emit `cloudflare_module` and forward hooks, but adds a generic build/host layer between NetScript and the official Worker toolchain (`../evidence/nitro-vs-own-live-2026-07-18.md`). | **Yes, Nitro is less native for the full Cloudflare suite.** The official stack already solves bundle/dev/preview/deploy and exposes provider bindings directly. Own a thin Cloudflare adapter wrapping Wrangler/Vite/Miniflare. | +| Cloudflare / Denoflare | Denoflare offers a Deno-first CLI, Deno-2 esbuild loader, R2, and experimental multi-platform output (`../evidence/nitro-vs-own-rev2-live-2026-07-18.md`). | It removes Node/Wrangler but duplicates part of Cloudflare's official toolchain and is not needed to prove a Deno-native path. | Treat as an optional build strategy/research input, not the authoritative Cloudflare deploy adapter. Wrapping official Wrangler keeps product-suite coverage and compatibility semantics. | +| AWS / Lambda Web Adapter | AWS's adapter runs any HTTP app across managed/custom runtimes and OCI images, handles API Gateway/Function URL/ALB, binary, streaming, graceful shutdown and non-HTTP triggers, and includes a Deno example (`../evidence/nitro-vs-own-rev2-live-2026-07-18.md`). | Nitro's Lambda preset emits its own Lambda event handler and chunks (`../evidence/nitro-vs-own-live-2026-07-18.md`). | **Nitro is less native for AWS breadth.** Wrapping the AWS-maintained adapter retains the NetScript HTTP server and extends to AWS event/service bindings without adopting Nitro's handler. | +| AWS / Node-wrapper Deno experiment | The experiment demonstrates zip/layer feasibility but requires unstable compatibility flags, `--allow-all`, and disables telemetry (`../evidence/nitro-vs-own-rev2-live-2026-07-18.md`). | It is more Deno-direct than Nitro but operationally weaker than the AWS adapter. | Evidence for a research branch only; do not make it the production base. “Deno-native” alone does not outweigh telemetry/security/runtime risk. | + +The rev1 claim that Nitro avoids building raw output contracts was true but framed the alternative +incorrectly. The real choice is **wrap Nitro versus wrap the provider's own toolchain**. On +Cloudflare and AWS the second wrapper is both thinner and deeper. On Vercel, the available +Deno-native runtime is compelling but community-maintained, so Nitro retains provisional value +(`../evidence/nitro-vs-own-rev2-live-2026-07-18.md`). + +### Revised cost estimates + +These are planning estimates inferred from the cited wrapper surfaces, not measured delivery data. +They include adapter code, configuration emission and conformance fixtures, but exclude provider +accounts and production soak. + +| Target | Rev1 greenfield estimate | Wrap-don't-reinvent estimate | Why it falls | +| ------------------------------------------- | -----------------------: | -----------------------------------------------------------------: | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| Cloudflare Workers HTTP/deploy | 4–7 engineer-weeks | **2–4 weeks** | Wrangler accepts the TS entry; the Vite plugin supplies workerd build/preview and binding access; Miniflare supplies local target semantics (`../evidence/nitro-vs-own-rev2-live-2026-07-18.md`). | +| Cloudflare first leaf backing (KV or Queue) | not separated | **1–2 weeks/backing**, after shared CF binding resolver | Provider APIs already exist; work is semantic mapping and conformance, not service implementation. KV lacks NetScript CAS guarantees and Queue must preserve retry/DLQ semantics (`adapter-mapping.md:10-24`; `../evidence/nitro-vs-own-rev2-live-2026-07-18.md`). | +| AWS Lambda HTTP | 5–9 weeks | **2–4 weeks** | Lambda Web Adapter supplies event/HTTP translation, binary, streaming, readiness and shutdown (`../evidence/nitro-vs-own-rev2-live-2026-07-18.md`). | +| AWS first leaf backing/event source | not separated | **1.5–3 weeks/backing**, after shared AWS client/identity resolver | AWS supplies SQS polling/batching and broad event sources; NetScript must still map at-least-once delivery, idempotency and partial failures (`../evidence/nitro-vs-own-rev2-live-2026-07-18.md`; `adapter-mapping.md:19-29`). | +| Vercel HTTP via `vercel-deno` | 4–7 weeks | **1–3 weeks experimental** | Runtime, dev integration and Deno handler contract already exist, but maintenance/builder compatibility need proof (`../evidence/nitro-vs-own-rev2-live-2026-07-18.md`). | +| Docker-image provider | 0.5–1.5 weeks/provider | **0.5–1.5 weeks/provider** | Already an image plus thin deploy/config invocation; Nitro adds little (`packages/cli/src/kernel/adapters/aspire/aspire-cloud-deploy-target.ts:106-180`; [#346](https://github.com/rickylabs/netscript/issues/346)). | + +The cost reduction invalidates rev1's blanket reason to rent all tier-3 translation. It does not +make owned adapters free: each provider mapping still needs capability rejection, lifecycle, +security, local-emulator and live-smoke gates +(`packages/cli/src/kernel/domain/deploy/deploy-target-port.ts:90-128`; +`docs/architecture/doctrine/06-archetypes.md:257-299`). + +## 2. Does provider-suite depth flip Cloudflare and AWS? + +**Yes. Cloudflare and AWS flip to owned, provider-native adapter families.** Nitro can expose some +hooks and bindings, but its generic storage/tasks layer is weaker than NetScript's ports and cannot +express the full provider suite without provider-specific adapters anyway +(`adapter-mapping.md:10-33`). + +### Cloudflare + +| Provider capability | NetScript leaf | Fit and guardrail | +| ------------------- | --------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Workers KV | `@netscript/kv` adapter | Basic get/set/list/delete maps directly, but it must advertise no CAS/strong-consistency capability where the provider cannot prove it; it cannot back saga state requiring atomics (`../evidence/nitro-vs-own-rev2-live-2026-07-18.md`; `adapter-mapping.md:11-14`). | +| Queues | `@netscript/queue` adapter plus worker/trigger activation | Guaranteed delivery, batching, retry, delay, DLQ and pull consumers are much closer to `MessageQueue` than Nitro tasks. Conformance must still pin ack, attempt, ordering and duplicate behavior (`../evidence/nitro-vs-own-rev2-live-2026-07-18.md`; `adapter-mapping.md:19-24`). | +| Durable Objects | saga/worker state and coordination adapters | Strongly consistent attached storage, serialization and alarms are plausible saga/worker primitives. This is **not** a generic `KvStore` substitution: object identity/placement and transactional scope require a dedicated adapter and a saga-store proof (`../evidence/nitro-vs-own-rev2-live-2026-07-18.md`; `packages/plugin-sagas-core/src/runtime/create-saga-runtime.ts:20-115`). | +| Workers Cache | HTTP cache adapter | Direct provider cache is more native than routing through generic Nitro cache and can avoid Worker execution on hits (`../evidence/nitro-vs-own-rev2-live-2026-07-18.md`; `adapter-mapping.md:15-18`). | + +### AWS + +An owned AWS family can compose Lambda Web Adapter for HTTP with leaf adapters for SQS, DynamoDB, +Step Functions or later services. AWS explicitly documents SQS at-least-once delivery, duplicate +possibility, batching, visibility timeout and partial failures; those are exactly the semantics a +`MessageQueue` adapter must preserve rather than flatten +(`../evidence/nitro-vs-own-rev2-live-2026-07-18.md`; `adapter-mapping.md:19-29`). Lambda +event-source mappings also cover DynamoDB Streams, Kinesis, Kafka, MQ and DocumentDB; Step Functions +has richer workflow error handling than Lambda retries. That breadth makes a provider-family +boundary valuable even when only a subset ships in v1 +(`../evidence/nitro-vs-own-rev2-live-2026-07-18.md`). + +Owning these families does not mean one giant cloud SDK abstraction. Each leaf package retains its +stable semantic port and ships or imports a provider adapter; the deployment layer resolves +bindings, provisions/configures resources, and routes activation. The provider name is an extension +axis, not a replacement domain (`docs/architecture/doctrine/06-archetypes.md:266-281`). + +## 3. Merge single- and multi-runtime deployment layers + +The owner's proposed merge is architecturally stronger than separate “single-runtime” and +“distributed” deployment stacks. Logical topology and physical placement are separate decisions: the +same leaf adapter can bind locally/in-process or to a provider service, while deploy selects a cell +and wires it. The single composition root remains caller-owned +(`docs/architecture/doctrine/07-composition-and-extension.md:13-38`). + +### Leaf ownership + +- `@netscript/kv`: provider KV/storage implementations and declared consistency/atomic/watch + capabilities (`adapter-mapping.md:11-14`). +- `@netscript/queue`: provider enqueue/consumer implementations, retry/DLQ/ordering capability + (`adapter-mapping.md:19-24`). +- `@netscript/database`: provider connectors and writer/topology constraints + (`adapter-mapping.md:9-10`; `packages/database/deno.json:5-13`). +- workers/sagas/triggers/streams cores: provider activation, state, scheduler and transport adapters + only where their richer semantics belong (`adapter-mapping.md:25-31`). +- service/Fresh/oRPC: one Fetch-shaped host contract, independent of placement + (`adapter-mapping.md:32-33`; `packages/service/src/types.ts:13-20`). + +### Proposed `@netscript/deploy` + +Move the existing deploy domain out of CLI into a callable Archetype-2/7 core; retain CLI as the +Archetype-6 presentation router. This is a package proposal, not an implementation decision. It is +directly anticipated by doctrine's package-agnostic deploy core plus thin CLI layout +(`docs/architecture/doctrine/06-archetypes.md:257-299`) and extracts the already-public CLI port +(`packages/cli/src/kernel/domain/deploy/deploy-target-port.ts:1-128`; +`packages/cli/src/kernel/extension-points.ts:23-37`). + +Suggested public surface: + +| Surface | Responsibility | +| ---------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `DeploymentPlan` / `DeploymentCell` | Declarative physical topology: processes/functions, entrypoints, assets, leaf bindings, routes, triggers and placement; the provider target remains the named extension axis (`docs/architecture/doctrine/06-archetypes.md:257-281`). | +| `CapabilityRequirement` / `CapabilityManifest` | Requirements and supplied capabilities with explicit rejection before emit/up; reuses UR-5's contract rather than inventing preset flags (`../design/canonical/slot-map.md:20,42-44`). | +| `DeployTargetPort` | Keep `plan/emit/up/down/status/logs/rollback/secrets`; move ownership from CLI and preserve adapter conformance (`packages/cli/src/kernel/domain/deploy/deploy-target-port.ts:12-128`). | +| `ArtifactEmitterPort` | Turn a validated cell into target artifacts without deploying; implementations wrap Cloudflare official tooling, Lambda Web Adapter/IaC, Vercel Nitro or Deno runtime, process, or container (`../evidence/nitro-vs-own-rev2-live-2026-07-18.md`; `packages/cli/src/kernel/domain/deploy/deploy-target-port.ts:106-110`). | +| `ResourceBindingResolverPort` | Resolve declared logical leaf bindings to provider handles/config without exposing credentials or provider SDK objects across package ports; the need follows from CF KV/Queue bindings and leaf semantic boundaries (`../evidence/nitro-vs-own-rev2-live-2026-07-18.md`; `adapter-mapping.md:10-24`). | +| `ProvisionerPort` | Plan/apply/status/rollback provider resources; wrap Wrangler/AWS/Aspire/provider CLI or IaC and remain separate from artifact emission (`packages/cli/src/kernel/domain/deploy/deploy-target-port.ts:106-121`; `docs/architecture/doctrine/06-archetypes.md:266-275`). | +| `ActivationRouterPort` | Map provider events (HTTP, queue, schedule, stream) into service/worker/trigger entrypoints while retaining delivery semantics (`../evidence/nitro-vs-own-rev2-live-2026-07-18.md`; `adapter-mapping.md:19-31`). | +| `DeployTargetRegistry` | Closed-on-key target registration and dynamic selection; CLI performs parse → resolve → invoke only (`packages/cli/src/kernel/extension-points.ts:23-37`; `docs/architecture/doctrine/06-archetypes.md:272-299`). | + +The dependency direction is critical: leaf packages define semantic ports; provider adapter packages +depend on those ports; `@netscript/deploy` composes adapters and resource declarations; CLI depends +on deploy. `@netscript/deploy` must not absorb KV/queue/saga behavior or become a cloud god-object +(`docs/architecture/doctrine/07-composition-and-extension.md:70-76`; `adapter-mapping.md:35-42`). + +## 4. Revised per-target recommendation + +| Target family | v1 path | Nitro role | Rationale | +| ------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------ | ------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Deno server/bare metal | **Owned Deno-native host/emitter** | None | Existing Fetch/listener and deploy-port seams; no provider translation benefit (`packages/service/src/builder/service-builder-impl.ts:501-521`; `packages/cli/src/kernel/domain/deploy/deploy-target-port.ts:90-128`). | +| Docker/Compose, Kubernetes, Azure | **Aspire/Docker lane** | None | Existing registry and Aspire adapters already own this path (`packages/cli/src/kernel/application/registries/deploy-target-registry.ts:1-114`; `packages/cli/src/kernel/adapters/aspire/aspire-compose-deploy-target.ts:41-227`). | +| Cloud Run, Koyeb, Sevalla, Coolify, Dokploy, Fly.io, Render, DigitalOcean | **Aspire/Docker image + thin target adapter** | None | Image is the portable artifact; target work is provider config/invocation. Existing Cloud Run proves the pattern and #346 owns the Docker-provider lineage (`packages/cli/src/kernel/adapters/aspire/aspire-cloud-deploy-target.ts:106-180`; [#346](https://github.com/rickylabs/netscript/issues/346)). | +| Cloudflare Workers + suite | **Owned wrapper over Wrangler + CF Vite plugin + Miniflare; leaf CF bindings** | None by default; optional comparison fixture only | Official tooling is Deno-compatible and gives direct workerd/binding/product access (`../evidence/nitro-vs-own-rev2-live-2026-07-18.md`). | +| AWS Lambda + suite | **Owned wrapper over AWS Lambda Web Adapter + AWS event/resource adapters** | None by default; optional comparison fixture only | AWS adapter preserves HTTP portability and native event/product breadth; community Deno wrapper remains research-only (`../evidence/nitro-vs-own-rev2-live-2026-07-18.md`). | +| Vercel | **Nitro preset provisionally; owned `vercel-deno` adapter as a research/conformance challenger** | Optional v1 emitter | Deno runtime is more native but lacks vendor ownership/scale evidence; choose by identical conformance and maintenance gates (`../evidence/nitro-vs-own-rev2-live-2026-07-18.md`; `../evidence/nitro-vs-own-live-2026-07-18.md`). | +| Netlify and unsupported long-tail function formats | **Nitro preset only when it is the thinnest proven wrapper** | Optional | Retains Nitro's real breadth benefit without putting it in the composition contract (`nitro-vs-own.md:27-39`). | +| New Deno Deploy | **Owned research card** | None until proved | Current corpus withdrew it from v1 pending platform proof (`../design/canonical/slot-map.md:45-48,65-66`; `deno-deploy-new.md:85-102`). | + +## 5. Delta to the locked UR cards + +This is a supervisor-facing drift proposal only. The locked source remains +`../design/canonical/slot-map.md:15-28`. + +| Card | Rev2 disposition | +| ----------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| UR-0, UR-1, UR-3, UR-4, UR-7, UR-8, UR-9, UR-10 | **Survive in intent.** Lifecycle, in-process composition, Fetch mounting, writer/offline/durability and single-process contracts are provider-independent (`../design/canonical/slot-map.md:15-25`; `adapter-mapping.md:19-33`). | +| UR-2 | **Replace Nitro ownership.** NetScript host lifecycle owns listener/close; provider host adapters, including optional Nitro, consume it (`../design/canonical/slot-map.md:17,36-37`; `packages/service/src/builder/service-builder-impl.ts:501-521`). | +| UR-5 | **Generalize preset → deployment cell/provider capability.** Add provider-resource and leaf-binding requirements; preserve compile-time rejection and saga semantics (`../design/canonical/slot-map.md:20,42-44`; `adapter-mapping.md:25-29`). | +| UR-6 | **Replace preset columns with emitter/provider cells.** Keep `deno_server`, `node_server`, `cloudflare_module`, but Cloudflare becomes the owned official-toolchain reference cell; add emitter provenance and target-native conformance. Do not add Vercel/AWS to v1 merely because wrappers exist (`../design/canonical/slot-map.md:21,45-48`). | +| UR-11 | **Expand architecture contract.** Decide/extract `@netscript/deploy`, dependency direction, leaf adapter ownership, binding resolver, emitter/provisioner separation and thin CLI (`../design/canonical/slot-map.md:26,60-62`; `docs/architecture/doctrine/06-archetypes.md:257-299`). | +| UR-12 | **Rewrite acceptance around provider-native replacement.** Prove the three cells and that Nitro is absent from the public composition/leaf contracts; optional emitters must be droppable (`../design/canonical/slot-map.md:27,63-64`; `packages/cli/src/kernel/domain/deploy/deploy-target-port.ts:90-128`). | +| DD-RESEARCH | **Unchanged.** New Deno Deploy remains a successor proof, not a v1 claim (`../design/canonical/slot-map.md:28,65-66`). | + +## Final recommendation + +Adopt **provider-native HYBRID**, with Cloudflare and AWS flipped from Nitro presets to owned +adapter families built by wrapping their official tools. Keep Nitro only as a replaceable long-tail +emitter and a provisional Vercel option. Merge single- and multi-runtime deployment through +leaf-owned provider adapters plus a new `@netscript/deploy` composition/provisioning package; do not +merge leaf semantics into deploy. + +The decision rule is stricter than rev1: **Nitro is chosen per target only when it passes the same +conformance suite, exposes every required native binding/event/config surface, and costs less to +maintain than the best provider-native wrapper.** If it introduces a native-integration trade-off, +it fails the condition and the owned wrapper wins. diff --git a/.llm/runs/plan-unified-runtime--seed/research/nitro-vs-own.md b/.llm/runs/plan-unified-runtime--seed/research/nitro-vs-own.md new file mode 100644 index 000000000..9a95cab2d --- /dev/null +++ b/.llm/runs/plan-unified-runtime--seed/research/nitro-vs-own.md @@ -0,0 +1,122 @@ +# Should the unified runtime build on Nitro? + +Evidence date: 2026-07-18. Live-source extracts are preserved at +`../evidence/nitro-vs-own-live-2026-07-18.md`. This is supplemental Stage-B research, not a board +change. + +## Verdict + +**Choose HYBRID: NetScript owns the composition root, runtime contracts, and deploy-target port; +Nitro is an optional, replaceable output-emitter/host adapter for targets where its maintained +preset materially avoids provider-specific work.** Do not make H3, Nitro storage, or Nitro tasks the +universal NetScript runtime. This preserves the existing Fetch-shaped service seam and port +architecture while buying Nitro's real advantage: build and provider-output maintenance +(`packages/service/src/types.ts:13-20`; +`packages/cli/src/kernel/domain/deploy/deploy-target-port.ts:1-128`; +`docs/architecture/doctrine/07-composition-and-extension.md:15-37`; +`../evidence/nitro-vs-own-live-2026-07-18.md`). + +NITRO-HOST would couple every cell to a public-beta build/HTTP host even though NetScript's durable +queue, saga, trigger, and stream contracts remain necessary. OWN-LAYER would preserve control but +needlessly make NetScript maintain several fast-moving serverless artifact formats. HYBRID keeps the +logical runtime independent and permits a target to move from Nitro to an owned emitter without +changing application code (`adapter-mapping.md:19-33`; `adapter-mapping.md:35-42`; +`docs/architecture/doctrine/06-archetypes.md:119-145`). + +## 1. What Nitro actually adds + +| Surface | Nitro's real contribution | NetScript reality | Decision | +| ---------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------- | +| Deployment outputs | Roughly twenty documented provider families/recipes, preset selection/auto-detection, and provider-specific artifacts. The count is a breadth signal, not a claim that all presets have equal maturity (`../evidence/nitro-vs-own-live-2026-07-18.md`; `nitro-v3.md:43-59`). | A shipped deploy port and registry already cover process, Docker/Compose, Kubernetes, Azure, Deno Deploy, and Cloud Run (`packages/cli/src/kernel/domain/deploy/deploy-target-port.ts:1-128`; `packages/cli/src/kernel/application/registries/deploy-target-registry.ts:1-114`). | Unique value is highest for tier-3 serverless formats, not Docker-image targets. | +| Build | Rolldown/Vite backend build with route compilation, code splitting, tree shaking, minification, HMR, and a normalized `.output` (`../evidence/nitro-vs-own-live-2026-07-18.md`). | NetScript would require bundling/externalization/assets for any serverless emitter, but already delegates container publication to Aspire and Docker tooling (`packages/cli/src/kernel/adapters/aspire/aspire-compose-deploy-target.ts:41-227`; `packages/cli/src/kernel/adapters/aspire/aspire-cloud-deploy-target.ts:106-180`). | A meaningful shared build subsystem for serverless; little incremental value for existing image lanes. | +| HTTP host | H3 v2, Web-standard requests/responses, routes, middleware, lifecycle, and cross-runtime serving (`../evidence/nitro-vs-own-live-2026-07-18.md`; `nitro-v3.md:27-34`). | `ServiceApp.fetch(Request)` is already mountable; only `serve()` currently owns a listener (`packages/service/src/types.ts:13-20`; `packages/service/src/builder/service-builder-impl.ts:423-432`; `packages/service/src/builder/service-builder-impl.ts:501-521`). | Useful adapter, not a unique application contract. Keep Fetch authoritative. | +| Storage/cache/database/tasks | Host bindings, unstorage/ocache, experimental db0, tasks and scheduled activation (`nitro-v3.md:18-23`; `adapter-mapping.md:19-33`). | KV, queue, database, workers, sagas, triggers and streams expose stronger lifecycle/durability semantics; Nitro tasks are not a queue or saga engine (`adapter-mapping.md:19-33`). | Keep NetScript ports. HTTP/function cache is a genuine optional Nitro feature; other primitives are scoped adapters only. | +| Provider lifecycle | Cloudflare queue/scheduled hooks, Vercel Cron/queue hooks, and Lambda event adaptation are maintained with the preset (`../evidence/nitro-vs-own-live-2026-07-18.md`). | NetScript owns normalized activation, retry, DLQ, idempotency and workflow state (`adapter-mapping.md:23-31`). | Let Nitro translate provider events, then enter NetScript ports; do not inherit provider semantics into the domain. | + +The benefit is therefore narrower and more concrete than “one unified runtime”: Nitro packages a +backend build plus changing provider artifact/event conventions. It does **not** eliminate the +composition root or the durable adapters NetScript would build anyway (`adapter-mapping.md:19-42`). + +## 2. The OWN-LAYER alternative + +The owned design extends each package through its existing port: a hostable service lifecycle; +worker scheduler/queue activation; saga store, transport and scheduler; trigger ingress/scheduler; +stream transport; and KV/database/queue bindings. One composition root orders start, drain and stop. +That is consistent with the shipped worker and saga runtime factories +(`packages/plugin-workers-core/src/runtime/composition-root.ts:91-148`; +`packages/plugin-sagas-core/src/runtime/create-saga-runtime.ts:20-115`) and the doctrine's stable +port plus target-adapter archetype (`docs/architecture/doctrine/06-archetypes.md:119-145`). + +Deployment should remain a NetScript-owned extension axis. `DeployTargetPort`, its registry, and +shared target configuration already exist +(`packages/cli/src/kernel/domain/deploy/deploy-target-port.ts:1-128`; +`packages/cli/src/kernel/application/registries/deploy-target-registry.ts:1-114`; +`packages/config/src/domain/config-section-types.ts:356-593`). A narrower output-emitter port can +sit behind that surface: `emit(cell, target, capabilities) -> artifact + manifest`, with either an +owned or Nitro implementation. Nitro must not become the public deploy contract. + +### What an owned emitter must produce + +| Cell/target | Work without Nitro | Initial cost estimate | Nitro-adapter estimate | +| ---------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------: | ----------------------------------------: | +| Node/Deno process | Bundle or preserve modules, copy assets, emit an entry shim and lifecycle/capability manifest. NetScript already has the Fetch app and process listener seam (`packages/service/src/types.ts:13-20`; `packages/service/src/builder/service-builder-impl.ts:501-521`). | **1–2 engineer-weeks** | **1–2 weeks**; little advantage | +| Docker-image providers | Reuse the image and add thin provider invocation/config for Cloud Run, Koyeb, Render, and DigitalOcean. Cloud Run build/push/deploy already ships (`packages/cli/src/kernel/adapters/aspire/aspire-cloud-deploy-target.ts:106-180`; [#346](https://github.com/rickylabs/netscript/issues/346)). | **0.5–1.5 weeks/provider** | **0.5–1 week/provider**; little advantage | +| Cloudflare Workers | Bundle for workerd, emit `export default { fetch(request, env, ctx) }`, map assets/routes/bindings/environments/compatibility date, and emit Wrangler metadata plus schedules/queues (`../evidence/nitro-vs-own-live-2026-07-18.md`). | **4–7 weeks** | **1–2 weeks** to adapt/test Nitro output | +| Vercel | Emit `.vercel/output/static`, `.func` directories with `.vc-config.json`, global routing/config, function entry/event adaptation, Cron and queue configuration (`../evidence/nitro-vs-own-live-2026-07-18.md`). | **4–7 weeks** | **1–2 weeks** | +| AWS Lambda | Transpile/bundle dependencies, package handler/chunks, translate Lambda/API-Gateway or Function-URL events to Fetch responses, and handle streaming/binary/cookies plus deployment configuration (`../evidence/nitro-vs-own-live-2026-07-18.md`). | **5–9 weeks** | **1–3 weeks** | + +These are **planning estimates, not measured delivery data**. They infer scope from each cited +provider output contract and include implementation plus conformance fixtures, but exclude provider +account provisioning and production soak. Their purpose is comparative: the owned image lane is +already cheap, whereas recreating three serverless output/event contracts is several times the +adapter effort. The tier lineage agrees: Docker-image providers are active S10 scope while +Vercel/Cloudflare/Lambda were placed in WATCH tier 3 +([#327](https://github.com/rickylabs/netscript/issues/327), +[#346](https://github.com/rickylabs/netscript/issues/346), +[#349](https://github.com/rickylabs/netscript/issues/349)). + +## 3. Maintenance and risk delta + +| Choice | Risk NetScript accepts | Risk NetScript avoids | +| ---------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------ | +| NITRO-HOST | Nitro v3 is public beta; H3/build/preset changes affect every runtime cell. Provider compatibility dates must be pinned and deliberately advanced. A Deno-hosted project still consumes Nitro's Node/Vite/Rolldown build path (`../evidence/nitro-vs-own-live-2026-07-18.md`; `nitro-v3.md:8-14`). | Most provider bundling and output-format churn. | +| OWN-LAYER | NetScript owns bundler policy, Node compatibility, provider event translation, output manifests and every provider API change. Cloudflare compatibility dates, Vercel Build Output changes, and Lambda packaging become direct maintenance (`../evidence/nitro-vs-own-live-2026-07-18.md`). | Beta/API coupling and upstream preset regressions; exact control over artifacts. | +| HYBRID | Nitro remains a pinned optional build dependency for selected targets, with a target conformance suite required on upgrades. A preset failure affects that emitter, not the logical runtime (`../evidence/nitro-vs-own-live-2026-07-18.md`; `docs/architecture/doctrine/07-composition-and-extension.md:15-37`). | Reimplementing high-churn tier-3 formats while avoiding Nitro as a universal runtime dependency. | + +HYBRID still needs exact Nitro/Vite/Rolldown pins, recorded compatibility dates, artifact snapshots, +and live target smoke tests. “Nitro supports the preset” is not proof that NetScript's queue, +database, asset, lifecycle, or durability contract works there (`adapter-mapping.md:19-33`). The +Deno-via-Node build path is acceptable only inside the emitter toolchain; emitted runtime code must +pass the target cell's own conformance gate (`nitro-v3.md:8-14`). + +## 4. Effect on the locked UR board + +The following is a drift proposal for the supervisor, not an edit to the locked board. Card names +come from `../design/canonical/slot-map.md:15-28`. + +| Card(s) | Under OWN/HYBRID | +| ----------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| UR-0, UR-1, UR-7, UR-8, UR-9, UR-10 | **Survive unchanged in intent.** Hostable lifecycle, no-loopback logical composition, writer safety, offline profile, durable bindings, and single-process proof do not require Nitro (`../design/canonical/slot-map.md:15-28`; `adapter-mapping.md:19-33`). | +| UR-3 | **Generalize only:** Fresh mounts through a host-neutral Fetch/static contract; Nitro/H3 is one adapter (`packages/service/src/types.ts:13-20`; `../design/canonical/slot-map.md:18`). | +| UR-4 | **Survives, remove host assumption:** the oRPC Fetch bridge remains; test it against the generic host conformance suite and optionally Nitro (`../design/canonical/slot-map.md:19`; `orpc-fresh.md:37-52`). | +| UR-5 | **Rename:** preset capability manifest becomes a target/cell capability manifest. Unsupported saga/durability rejection is unchanged (`../design/canonical/slot-map.md:20`; `adapter-mapping.md:25-29`). | +| UR-11 | **Survives and expands:** document composition/public seams plus the deploy-output-emitter port and Nitro dependency boundary (`../design/canonical/slot-map.md:26`; `docs/architecture/doctrine/06-archetypes.md:119-145`). | +| UR-2 | **Replace:** “Nitro owns listener/lifecycle” becomes a NetScript host-runtime port/default listener, with `NitroHostAdapter` optional (`../design/canonical/slot-map.md:17`; `packages/service/src/builder/service-builder-impl.ts:501-521`). | +| UR-6 | **Replace:** three Nitro-preset cells become target emitter cells recording owned-vs-Nitro provenance and running identical conformance tests (`../design/canonical/slot-map.md:21`; `packages/cli/src/kernel/domain/deploy/deploy-target-port.ts:1-128`). | +| UR-12 | **Adjust acceptance wording:** prove the target matrix and replacement boundary, not Nitro adoption itself (`../design/canonical/slot-map.md:27`). | + +## 5. Recommendation and decision rule + +Adopt Nitro only behind a NetScript-owned output-emitter/host port for Cloudflare, Vercel, Lambda, +or a future target where its maintained output saves more work than the adapter costs. Keep owned +emitters for process, Docker/Compose, Kubernetes/Azure and Docker-image providers, where shipped +ports and Aspire delegation already cover the hard part +(`packages/cli/src/kernel/application/registries/deploy-target-registry.ts:1-114`; +`packages/cli/src/kernel/adapters/aspire/aspire-compose-deploy-target.ts:41-227`; +`packages/cli/src/kernel/adapters/aspire/aspire-cloud-deploy-target.ts:17-180`). + +A target may use Nitro only if its artifact is reproducible under exact pins, its compatibility date +is explicit, it passes the same cell conformance suite as an owned emitter, and no Nitro +storage/task/database type crosses a NetScript public port. If any one condition fails, replace that +target emitter without redesigning the composition root. This is the concrete benefit/risk balance: +**own the semantics; rent the volatile provider translation.** diff --git a/.llm/runs/plan-unified-runtime--seed/research/orpc-fresh.md b/.llm/runs/plan-unified-runtime--seed/research/orpc-fresh.md new file mode 100644 index 000000000..767d298fa --- /dev/null +++ b/.llm/runs/plan-unified-runtime--seed/research/orpc-fresh.md @@ -0,0 +1,67 @@ +# oRPC + Fresh 2 composition on Nitro v3 + +Research date: 2026-07-18. Live-doc extracts are preserved in +`../evidence/orpc-fresh-live-2026-07-18.md`; the original URLs remain the authority. + +## Existing request/response seams + +All three systems already meet at the Web Fetch API; the required bridge is routing and lifecycle +composition, not a new wire protocol. + +| Layer | Current surface | Consequence for a Nitro host | +| ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------- | +| Nitro/H3 | Nitro routes are H3 event handlers. oRPC's documented H3 adapter mounts `/rpc/**`, passes `event.req` to the Fetch `RPCHandler`, supplies a prefix/context, and returns the matched response. ([oRPC H3 adapter](https://orpc.dev/docs/adapters/h3)) | Nitro can own the outer router while delegating the RPC subtree to oRPC's Fetch handler. | +| oRPC | The Fetch adapter accepts a Web `Request` and produces a response/match result across Fetch runtimes, including Deno. ([oRPC HTTP adapter](https://orpc.dev/docs/adapters/http)) | The same RPC contract can be invoked through an H3 route or directly in-process; a loopback socket is not required. | +| NetScript service | `ServiceApp` structurally exposes `fetch(request): Promise` and `request(...)`; `FetchHandler` exposes `handle(request): Promise`. (`packages/service/src/types.ts:13-20`, `packages/service/src/types.ts:206-212`) | Nitro can mount the shipped service abstraction without exposing its internal router type. | +| NetScript oRPC implementation | `createRPCHandler()` constructs oRPC's Fetch `RPCHandler`, calls `handler.handle(request, { context })`, returns the response on a match, and emits a 404 otherwise. (`packages/service/src/primitives/handlers.ts:115-143`) | The repository already owns an adapter boundary suitable for H3 delegation; unified runtime should reuse it. | +| Fresh 2 | `app.handler()` turns a Fresh app into a Request→Response handler expressly for embedding in another framework; `app.listen()` starts its own listener and must not be combined with another server startup. ([Fresh App docs](https://usefresh.dev/docs/concepts/app)) | A Nitro composition must call the Fresh handler, never `listen()`, and keep exactly one outer listener per process. | +| NetScript Fresh wrapper | `defineFreshApp()` creates a Fresh `App`, installs state/security/tracing middleware, applies configuration, and then adds filesystem routes. (`packages/fresh/src/runtime/server/define-fresh-app.ts:1-119`) Its test invokes `app.handler()` with a Web `Request`. (`packages/fresh/src/runtime/server/define-fresh-app.test.ts:55-105`) | The shipped wrapper is already embeddable, but its middleware ordering and filesystem routes must remain intact. | + +The service builder currently returns a Hono-backed application, but its public result is the +structural `ServiceApp` Fetch surface rather than a Nitro- or H3-specific type. +(`packages/service/src/builder/service-builder-impl.ts:423-433`, +`packages/service/src/types.ts:13-20`) That separation is the compatibility asset: Nitro should +consume `fetch`, not reach into Hono. + +## Proposed composition boundary + +The smallest viable composition is one Nitro/H3 owner with two mounted Fetch delegates: + +1. Mount the NetScript/oRPC `FetchHandler` under the declared RPC prefix and pass the request, + request-scoped auth/telemetry context, and abort signal into the handler. This matches the live + oRPC H3 pattern. ([oRPC H3 adapter](https://orpc.dev/docs/adapters/h3), + `packages/service/src/primitives/handlers.ts:115-143`) +2. Mount the Fresh `app.handler()` for the UI route space or final application fallback. Do not + invoke `app.listen()`, because Fresh documents that it creates a listener and warns against a + second startup path. ([Fresh App docs](https://usefresh.dev/docs/concepts/app)) +3. Let Nitro own process startup, shutdown, and top-level error observation; Nitro exposes + `request`, `response`, `error`, and `close` lifecycle hooks. + ([Nitro lifecycle docs](https://nitro.build/guide/lifecycle)) + +This composition preserves issue #451's intended invariant—identical Web Request/Response API paths +with no loopback network hop—without requiring Nitro to know the service builder's Hono +implementation. ([issue #451](https://github.com/rickylabs/netscript/issues/451), +`packages/service/src/types.ts:13-20`) + +## Bridges the plan must specify + +| Bridge | Required contract and risk | +| --------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Route ownership | Declare non-overlapping RPC, health/metadata, Fresh UI, and static-asset spaces. Fresh resolves middleware/routes top-to-bottom, while Nitro has its own public-assets and route pipeline, so an implicit catch-all can bypass Fresh middleware or shadow RPC. ([Fresh App docs](https://usefresh.dev/docs/concepts/app), [Nitro routing docs](https://nitro.build/guide/routing)) | +| Prefix and base path | Carry one canonical mount prefix into both H3 matching and oRPC `handler.handle(..., { prefix })`; the live H3 example makes that prefix explicit. ([oRPC H3 adapter](https://orpc.dev/docs/adapters/h3)) | +| Context | Define how Nitro/H3 request state becomes NetScript auth, trace, and service context. The current service handler accepts a `context` factory, while the oRPC H3 example supplies request context at the adapter call. (`packages/service/src/primitives/handlers.ts:119-128`, [oRPC H3 adapter](https://orpc.dev/docs/adapters/h3)) | +| Error semantics | Preserve oRPC match/404 behavior and decide which failures remain typed RPC errors versus reaching Nitro's top-level `error` hook. (`packages/service/src/primitives/handlers.ts:124-142`, [Nitro lifecycle docs](https://nitro.build/guide/lifecycle)) | +| Lifecycle | Nitro's `close` hook must close NetScript adapters and background workers exactly once; embedding Fresh must not create its own listener. ([Nitro lifecycle docs](https://nitro.build/guide/lifecycle), [Fresh App docs](https://usefresh.dev/docs/concepts/app)) | +| Streaming and upgrade paths | Treat ordinary Fetch responses, streamed responses, and WebSocket upgrades as distinct conformance cases. Nitro's WebSocket support is opt-in through CrossWS/H3, not implied by mounting an ordinary Fetch handler. ([Nitro WebSocket docs](https://nitro.build/guide/websocket)) | +| Static assets | Choose whether Nitro or Fresh owns each asset namespace and test cache headers, fallbacks, and error pages through the composed entry point. Both frameworks have routing/asset stages, so ownership cannot be inferred from a shared Fetch type. ([Nitro routing docs](https://nitro.build/guide/routing), [Fresh App docs](https://usefresh.dev/docs/concepts/app)) | +| Version compatibility | The repository pins oRPC `^1.14.6`, while the live oRPC H3 page currently announces a v2 public beta. The board must pin and conformance-test the adapter API rather than copying a beta example unqualified. (`packages/service/deno.json:10-20`, [oRPC H3 adapter](https://orpc.dev/docs/adapters/h3)) | + +## Discovery verdict + +**Feasible with a thin Fetch bridge.** Fresh 2 and the shipped NetScript service surface are both +embeddable Web Request→Response handlers, and oRPC publishes a direct H3 composition pattern. +([Fresh App docs](https://usefresh.dev/docs/concepts/app), +[oRPC H3 adapter](https://orpc.dev/docs/adapters/h3), `packages/service/src/types.ts:13-20`) The +planning burden is therefore a precise ownership and conformance contract—routing, context, +lifecycle, assets, streams/upgrades, and pinned oRPC version—not a rewrite of Fresh or service RPC +on H3. diff --git a/.llm/runs/plan-unified-runtime--seed/research/sagas-constraint.md b/.llm/runs/plan-unified-runtime--seed/research/sagas-constraint.md new file mode 100644 index 000000000..411387b8b --- /dev/null +++ b/.llm/runs/plan-unified-runtime--seed/research/sagas-constraint.md @@ -0,0 +1,87 @@ +# Re-evaluation of the “Nitro excludes sagas” constraint + +Evidence date: 2026-07-18. + +## Original constraint + +Issue #327 decision D1 (2026-07-03) classified RFC-14 unified mode as a 3–5-month separate track +that “excludes sagas,” alongside the then-known `deno_server --unstable` limitation. The same issue +described Nitro as WATCH and tier-3 serverless as unofficial-runtime/isolate/container territory. +([issue #327, D1 and watch-item sections](https://github.com/rickylabs/netscript/issues/327)) + +That historical decision predates the live v3 task, WebSocket, lifecycle, and database pages now +cited by issue #824 as requiring re-validation. +([issue #824](https://github.com/rickylabs/netscript/issues/824)) + +## What Nitro v3 actually supplies + +| Question | Live answer | Evidence | +| ------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------ | +| Can Nitro define and invoke background work? | Yes. Experimental `defineTask`/`runTask` operations accept payload/context and can be called programmatically. | [Nitro tasks](https://nitro.build/docs/tasks) | +| Can it schedule work? | Yes. `scheduledTasks` uses croner on dev/Node/Bun/Deno process presets and generates native Cloudflare/Vercel schedules. | [Nitro tasks](https://nitro.build/docs/tasks) | +| Does it provide a durable queue? | No such contract is documented. Errors propagate to the caller; `waitUntil` may or may not exist; same-name concurrent callers share one running invocation. | [Nitro tasks](https://nitro.build/docs/tasks) | +| Does it provide saga state, correlation, compensation, outbox, or idempotency? | The task surface documents none of these semantics. Its contract is named task execution and scheduling. | [Nitro tasks](https://nitro.build/docs/tasks) | +| Can a long-running Nitro server own runtime resources and clean them up? | Yes. Plugins register behavior, and `close` is the documented shutdown cleanup hook. | [lifecycle](https://nitro.build/docs/lifecycle), [plugins](https://nitro.build/docs/plugins) | +| Can it host message ingress/transports? | Yes at the host layer: HTTP routes, cross-platform WebSockets, pub/sub topics, and provider-specific hooks are available. | [WebSocket](https://nitro.build/docs/websocket), [lifecycle](https://nitro.build/docs/lifecycle) | +| Are all presets equivalent for saga execution? | No. `waitUntil` is runtime-dependent; schedule integration differs by preset; the default is Node, while Deno and provider presets are distinct outputs. | [tasks](https://nitro.build/docs/tasks), [deploy](https://nitro.build/deploy) | + +## What shipped NetScript sagas require + +The shipped `SagaDefinition` is not “a background function.” It contains a durability tier, initial +state, handled message types, correlation rules, handlers, compensations, signal/query handlers, +retry, concurrency, and an optional schedule. +(`deno doc --filter SagaDefinition packages/plugin-sagas-core/mod.ts`) + +The shipped ports make the durable obligations explicit: + +- `SagaStorePort` persists state envelopes, transition history and correlation indexes, with + optional optimistic-write constraints. + (`deno doc --filter SagaStorePort packages/plugin-sagas-core/src/ports/mod.ts`) +- `SagaTransportPort` owns start/stop, publish and subscribe. + (`deno doc --filter SagaTransportPort packages/plugin-sagas-core/src/ports/mod.ts`) +- `SagaOutboxPort` is reserved for atomic state/cascaded-message commits, and `SagaIdempotencyPort` + reserves durable deduplication keys. + (`deno doc --filter SagaOutboxPort packages/plugin-sagas-core/src/ports/mod.ts`; + `deno doc --filter SagaIdempotencyPort packages/plugin-sagas-core/src/ports/mod.ts`) + +These requirements align with the doctrine that durable workflows are state machines with named +lifecycle/failure behavior, not opaque task callbacks +(`docs/architecture/doctrine/08-runtime-state-failure.md:11-25`). + +## Verdict + +**STALE as a categorical exclusion; VALID as a “Nitro does not implement saga semantics” warning.** +Nothing in the live Nitro v3 host contract prevents a NetScript saga runtime from running +in-process. A long-running preset can mount the shipped saga runtime, use NetScript +stores/transports, and bind its shutdown to Nitro's `close` hook. That is an integration +requirement, not an exclusion. ([Nitro lifecycle](https://nitro.build/docs/lifecycle); +`deno doc --filter SagaTransportPort packages/plugin-sagas-core/src/ports/mod.ts`) + +The constraint **does still hold for a naive substitution**: replacing saga execution with Nitro +tasks would discard correlation, persisted transitions, compensation, retry policy, idempotency and +outbox guarantees. Nitro tasks are experimental and explicitly expose runtime-dependent continuation +behavior. ([Nitro tasks](https://nitro.build/docs/tasks); +`deno doc --filter SagaDefinition packages/plugin-sagas-core/mod.ts`) + +It also remains **preset-conditional**. Serverless/isolate outputs must prove that their activation, +execution window, storage/transport connectors, and shutdown model satisfy the chosen +`SagaDurabilityTier`; otherwise those presets must reject sagas at build time or route saga work to +a macro-service running a compatible long-lived process. Nitro itself documents preset-dependent +`waitUntil` and schedule integrations, so cross-preset parity cannot be assumed. +([Nitro tasks](https://nitro.build/docs/tasks), [deploy presets](https://nitro.build/deploy)) + +## Board consequence + +Replace “Nitro excludes sagas” with a capability rule: + +1. **In-process supported only through the NetScript saga runtime**, never through direct task + substitution. The saga package's store/transport/outbox/ idempotency ports remain authoritative. + (Citations above.) +2. Each deploy preset declares `sagas: supported | externalized | rejected` and proves the + declaration against duration, lifecycle, connector and durability gates. Nitro's own + preset-dependent task behavior is evidence that this cannot be one global boolean. + ([Nitro tasks](https://nitro.build/docs/tasks)) +3. “Externalized” means the same app model splits saga resources into a macro-service; it is not a + silent downgrade to best-effort tasks. The same app-model premise comes from issue #823, while + this Stage-B finding limits the allowed realization. + ([issue #823](https://github.com/rickylabs/netscript/issues/823)) diff --git a/.llm/runs/plan-unified-runtime--seed/supervisor.md b/.llm/runs/plan-unified-runtime--seed/supervisor.md new file mode 100644 index 000000000..62c2f2322 --- /dev/null +++ b/.llm/runs/plan-unified-runtime--seed/supervisor.md @@ -0,0 +1,45 @@ +# Supervisor Identity — plan-unified-runtime--seed + +Seed run (stage contracts A–I per `.llm/harness/workflow/seed-run.md`) for issue #824 — the +unified-runtime board (Nitro v3 validation + epic decomposition). Supervised as G8 of the +beta-11 wave by the same Tier-A session. + +| Field | Value | +| --- | --- | +| Model | Claude Fable 5 (`claude-fable-5`) · effort low | +| Session | `86d308d5-c761-4e5d-a41f-8be959bc46d2` (beta-11 orchestrator, Tier-A) | +| Host | WSL2 Linux / user `codex` | +| Checkout | worktree `/home/codex/repos/wt-g8-seed` | +| Branch | `plan/unified-runtime` | +| Baseline | `origin/main` @ 56cf84b5 (2026-07-18, post-#847) | +| Run ID | `plan-unified-runtime--seed` | + +## Routes in force + +| Task lane | Provider / model / effort | Role | +| --- | --- | --- | +| `planning_decisions` | Claude · Fable 5 · low | Tier-A supervisor (stages A/C/E/H-filing/I) | +| Stage-B corpus | Sol · medium research sub-agents (Tier D via agentic suite) or committed Tier-C workflow | discovery fan-out | +| Stage-D packs | Opus 4.8 · medium sub-agents (`chore_code`/Tier B) | per-topic design packs | +| Stage-F adversarial | model distinct from all authors — Sol · max | unoriented plan review | +| `formal_evaluation` | OpenRouter qwen/qwen3.7-max | stage-G PLAN-EVAL | + +## Hard boundaries (seed-run doctrine + kickoff stop-line 5) + +- Drafts-only until stage H: ZERO board mutation (issues, epics, milestones, labels) before the + owner ratifies the decision brief IN-TURN. The run's own draft PR is the only writable GitHub + surface. +- One-shot filing from a committed manifest after ratification; FILING-LOG.md + supersession map + (#451/#453/#454/#455 re-homed; #349 close-as-superseded proposal). + +## Stop-lines (verbatim from the wave) + +1. Merge requires CI green + opposite-family eval PASS on the PR. Owner granted standing beta-11 + merge authorization (2026-07-17 in-turn) once that bar is met. +2. HARD STOP before any release publish (`release:cut`, JSR publish, tag push, canary or stable) + — owner sign-off in-turn only; a stale or relayed approval does not count. +3. HARD STOP before closing milestone 13 — owner sign-off only. +4. These stop-lines are repeated verbatim in EVERY sub-agent brief. A sub-brief without the + stop-lines section is invalid. +5. The #824 seed run is drafts-only until owner ratification; its board filing needs the owner + in-turn. diff --git a/.llm/runs/plan-unified-runtime--seed/synthesis.md b/.llm/runs/plan-unified-runtime--seed/synthesis.md new file mode 100644 index 000000000..54350ae2e --- /dev/null +++ b/.llm/runs/plan-unified-runtime--seed/synthesis.md @@ -0,0 +1,50 @@ +# Stage C — Supervisor synthesis (plan-unified-runtime--seed) + +Supervisor: Fable 5 session 86d308d5 (Tier-A). Full Stage-B corpus read 2026-07-18 (six topic +files, `research/`). Citations live in the corpus; this synthesis names conclusions and the +Stage-D fan-out. GitHub wins on conflict. + +## Accepted Stage-B verdicts (supervisor-ratified) + +1. **Nitro v3 = host/output substrate, not adapter replacement.** Public beta; `deno_server` is + Node-built + `--unstable`-launched; database/tasks experimental; storage defaults volatile. + NetScript ports remain the application contracts (corpus: nitro-v3.md, adapter-mapping.md). +2. **"Excludes sagas" (#327 D1) is STALE as a categorical exclusion** — superseded by a + capability rule: sagas run in-process only through the NetScript saga runtime (store/ + transport/outbox/idempotency ports); each deploy preset declares + `sagas: supported | externalized | rejected` and proves it; "externalized" = macro-service + split of the same app model, never a downgrade to Nitro tasks (sagas-constraint.md). +3. **The universal invariant is LOGICAL graph identity** (one composition root); physical + one-process execution is a per-preset capability. This resolves drift D-01/D-02 and preserves + RFC §3's earn-the-graph default without promising OS-process identity on provider presets. +4. **Transport = invocation placement over a stable Fetch/RPC contract** (D-07): in-memory + delegation via `ServiceApp.fetch` + oRPC handler; "no socket loopback" is the requirement, a + second codec is not. Pin the oRPC generation (shipped ^1.14.6 vs live v2 beta — D-11) and add + an H3-bridge conformance gate. +5. **Nitro owns the listener/lifecycle; Fresh mounts via `app.handler()`** — never nested + `listen()` (D-10). Route/static ownership + no-nested-listen acceptance tests are board cards. +6. **Data naming**: the shipped surface is `@netscript/database` — board language normalizes to + shipped package names; `@netscript/data` would need an explicit facade contract card (D-12). +7. **Desktop update/install mechanics are one target adapter** (D-04) — the shared contract is + the artifact/topology manifest (consistent with the beta-11 #456 one-lineage decision); + writer-ownership (D-08) and offline sync (D-09) become declared database capabilities. + +## Resolutions of supervisor-delegated decisions + +- **Drift dispositions D-01…D-12**: all accepted as tabled in drift-ledger.md; none rejected. + They become plan constraints, not open questions. +- **Milestone anchor**: unified-runtime epic #823 targets beta.12+ per the RFC train; exact + milestone split is a Stage-E output (owner fork). +- **Preset cell set (from nitro-v3.md board input 2)**: v1 board plans four runtime cells — + `deno_server`, `deno_deploy`, one Node server preset, one isolate/serverless preset — each a + capability-matrix column, not a global promise. + +## Stage-D fan-out (one focused pack per topic) + +| Pack | Scope | Feeds | +| --- | --- | --- | +| D1 `composition-host` | Composition contract: logical root, Nitro host integration (listener/lifecycle/plugins/close), Fresh handler mount, oRPC in-process bridge + conformance gate, version pins | epic #823 core issues | +| D2 `capability-matrix` | Preset × capability contract (sagas rule, KV/queue/database ownership mapping, writer/lock + offline-sync capabilities, task/schedule mapping), build-time rejection semantics | acceptance gates + per-preset issues | +| D3 `board-mechanics` | Epic decomposition + milestone train + supersession map (#451 fold-in per D-07, #453 per D-08, #454 re-scope per D-02, #455 per D-09, #349 close-as-superseded), issue drafts per netscript-pr | Stage-E plan lock + Stage-H manifest | + +Packs are DRAFTS — no GitHub mutation (stage-H boundary; owner ratifies in-turn).