Skip to content

chore(runtime): classify #16741 into port tracks; track the remote install model doc - #24137

Closed
OrcaWin wants to merge 3 commits into
mainfrom
OrcaWin/node-rt-p3-prep
Closed

OrcaWin wants to merge 3 commits into
mainfrom
OrcaWin/node-rt-p3-prep

Conversation

@OrcaWin

@OrcaWin OrcaWin commented Sep 30, 2026 •

Copy link
Copy Markdown
Collaborator
Files Added Deleted Net
Test 2 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​217 0 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​217
Prod 12 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​6245 $\color{#cf222e}{\Huge{\mathbf{−}}}$​41 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​6204

ELI5

This prepares the port of #16741 (SSH and remote convergence). It adds a script that sorts every file #16741 changes into the planned stack of smaller PRs, and a tracked document for the remote install model. The document replaces the missing shipping-orcad.html that code comments cite.

What Changed

  • Track manifest: config/scripts/pr16741-track-manifest.mjs, with pr16741-track-rules.mjs and a generated pr16741-track-manifest.json.
    • Classifies all 1,985 files changed between 277c289bd4 and the frozen head a68b6f3531 into tracks T0–T9, with prod and test line counts.
    • Each file's disposition is port, dropped (T0, the Bun pieces), deferred (T7 and T8, live terminal transfer) or reconcile (14 files where main has diverged).
    • It fails if any file is unassigned, and it never fetches.
  • Install-model doc: docs/reference/remote-server-install-model.md, allow-listed in .gitignore.
    • Describes the converged model: two install paths, server-<version>/ plus runtimes/node-<sha>/, a legacy sweep that deletes only on exited, a two-release GC handover, and one registered identity per machine.
    • Every code comment that cited shipping-orcad.html now points at it. Only comments change.

Why

Design D9 says to port #16741 by subsystem, so every file needs an owner track. Design D10: the §06 rule can't be amended in a document nobody has.

Linked Issue

Part of the Node runtime plan (Phase 3 prep).

Visual Proof

N/A. This adds a script, generated data and docs.

Testing

  • 41 classifier tests pass.

  • Fixed in review: renamed files are now judged by their rename source.

  • Open for track owners: T1 comes out much smaller than the design estimate (915 prod lines against about 3.8k), because the src/main/ssh/** catch-all puts transport and work-drain files in T2.

  • I manually tested these changes locally

  • Automated tests added/updated, or explained why not below

Agent skill upstream boundary

  • Not applicable, or this change follows docs/reference/agent-skill-sharing-upstream-boundary.md and copies or mechanically translates no upstream skill-installer source, tests, fixtures, registry entries, path tables, comments, or documentation.

m4air added 3 commits September 30, 2026 04:44
Adds config/scripts/pr16741-track-manifest.mjs, which reads the frozen
#16741 head (a68b6f3) against its merge-base 277c289 and assigns
every changed file to a track T0-T9 from one first-match glob table
(pr16741-track-rules.mjs). It fails when any file matches no rule, splits
prod from test lines, marks Bun pieces dropped, T7/T8 deferred, and
flags paths where main has since diverged as reconcile.

The generated manifest lives at config/scripts/pr16741-track-manifest.json
beside its generator, like ci-shard-timings.json; docs/** is gitignored.
…ng-orcad.html §06

shipping-orcad.html was never checked in, yet seven code comments cited it.
docs/reference/remote-server-install-model.md records the D10 replacement:
one converged server package with client-pushed and user-installed paths,
server-<version>/ plus runtimes/node-<sha256>/, a legacy relay-*/orcad-*
sweep that deletes only on an exited verdict, a two-release GC hand-over,
and one registered execution identity per machine as the permanent rule.
The comments now point there; no behaviour changes.
…ts new path

The new path of a rename is absent from main by construction, so every
rename was flagged as reconcile ('main has since removed'). Extract the
check into findMainDivergence and unit-test it.
@coderabbitai

coderabbitai Bot commented Sep 30, 2026

Copy link
Copy Markdown
Contributor

Review in Change Stack →

Navigate logical layers of code changes, visualize relationships, and explore their blast radius.

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Advanced

Run ID: ff544177-844c-410c-99e2-de5bc3a41785

📥 Commits

Reviewing files that changed from the base of the PR and between 85f8d6b and d1f7655.

📒 Files selected for processing (14)
  • .gitignore
  • config/scripts/orcad-operations-restart-safety.test.mjs
  • config/scripts/pr16741-track-manifest.json
  • config/scripts/pr16741-track-manifest.mjs
  • config/scripts/pr16741-track-manifest.test.mjs
  • config/scripts/pr16741-track-rules.mjs
  • docs/reference/remote-server-install-model.md
  • src/main/ssh/orcad-activation-gate.ts
  • src/main/ssh/orcad-remote-gc.ts
  • src/main/ssh/orcad-remote-launch.ts
  • src/main/ssh/orcad-state-snapshot.ts
  • src/main/ssh/remote-install-coexistence.ts
  • src/main/ssh/remote-install-gc.ts
  • src/main/ssh/remote-install-model.ts

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 8 remain after this review.


📝 Walkthrough

Walkthrough

The changes add track rules and a script that classifies changed files, calculates per-track counts, checks for divergence from main, and writes a JSON manifest and text summary. New tests cover the script’s parsing, classification, divergence, and output. The changes also add a remote server install model reference, update related source comments, and add an ignore rule for the reference path.

Priority: ⬇️ Low

Merge Risk: ⚪ Minimal · up to d1f76

The PR adds manifest tooling and consolidates remote-install documentation without changing installation behavior. No concrete merge-blocking issue remains; it is mergeable subject to normal checks.

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description covers the main changes, motivation, testing, visual proof, and agent-skill boundary. However, the Linked Issue section does not provide an actual issue link or issue reference, and th… Add the required linked issue reference, such as a valid GitHub issue link or Fixes #123, and complete the Review, Notes, and Checklist sections or state why they are not applicable.
Docstring Coverage ⚠️ Warning Docstring coverage is 57.14% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 14 functions across 11 files. (2 skipped:… Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly identifies both primary changes: classifying PR #16741 into port tracks and tracking the remote install model document.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Full details: Description check

Explanation

The description covers the main changes, motivation, testing, visual proof, and agent-skill boundary. However, the Linked Issue section does not provide an actual issue link or issue reference, and the Review, Notes, and Checklist sections are omitted.

Full details: Docstring Coverage

Explanation

Docstring coverage is 57.14% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 14 functions across 11 files. (2 skipped: 2 unsupported.)

  • Fix all pre-merge checks with AI
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Commit to this branch
  • Create a new PR

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@greptile-apps

greptile-apps Bot commented Sep 30, 2026 •

Copy link
Copy Markdown

RetriggerConfidence Score: 3/5

[Medium risk] Adds documentation and test infrastructure for a design classification.

The PR should not be merged as a porting plan until the deferred RPC dependencies and overlapping-file dispositions are corrected.

Findings

  1. P1 T2 imports deferred methods ▶
  2. P1 Shared edits miss reconciliation ▶

Summary

This PR adds a generated file-to-track plan for porting #16741 and a tracked reference for the proposed remote server install model. The track plan needs correction before it guides staged ports:

Diagram
%%{init: {'theme': 'neutral'}}%%
flowchart LR
  T2["T2: RPC method index"] --> T7["T7: deferred ownership-transfer methods"]
  T2 --> T8["T8: deferred captured-PTY methods"]
  T7 -. "not present during T2 port" .-> Build["Staged build"]
  T8 -. "not present during T2 port" .-> Build
Loading

Reviews (1) · Last reviewed commit: "fix(runtime): judge a renamed #16741 fil..."

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ℹ️ Minor suggestions only.

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ℹ️ Minor suggestions only. Two reference details and one checked-in artifact are worth a look before merge.

Reviewed changes

  • Track manifest generator — config/scripts/pr16741-track-manifest.mjs classifies the 1,985 files of #16741 into D9 tracks (T0–T9), parses --numstat -z, detects structural main divergence, and emits a stable JSON. Verified against the committed data: 1985 files — 84 dropped, 1096 port, 12 reconcile, 793 deferred — all consistent with the rules.
  • Track rules — config/scripts/pr16741-track-rules.mjs defines TRACKS and the first-match-wins TRACK_RULES, with narrow rules above the directory catch-alls.
  • Generated manifest — config/scripts/pr16741-track-manifest.json, regenerated against origin/main = db73d28e51; oxfmt --check clean.
  • Tests — config/scripts/pr16741-track-manifest.test.mjs, 42 passing; the findMainDivergence case actually pins the rename fix.
  • Install-model doc — docs/reference/remote-server-install-model.md, allow-listed in .gitignore, replaces citations to the untracked shipping-orcad.html in six src/main/ssh/* comments and one test comment. Comments only, no runtime change.

Verification: vitest run config/scripts/pr16741-track-manifest.test.mjs → 42 passed; oxlint and oxfmt --check clean on the new files.

ℹ️ Nitpicks

  • The PR body says "14 files where main has diverged"; the committed manifest has 12 reconcile entries (d1f7655093 regenerated it after the rename fix). Worth refreshing the body so the count matches the artifact.
  • Nothing ties pr16741-track-manifest.json back to pr16741-track-rules.mjs, so a rules edit that forgets to regenerate leaves the committed data stale with no CI signal. A cheap invariant test over classifyPath (allowing reconcile as an override) would catch it; I confirmed the current file is consistent, so this is only a guard.

@@ -0,0 +1,317 @@
// The D9 track table for #16741 (docs/reference/node-runtime-design.html), read by

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This cites docs/reference/node-runtime-design.html as the authority for the D9 table, but that file is not tracked in the repo — the same dangling-reference problem this PR fixes for shipping-orcad.html. pr16741-track-manifest.mjs:1 cites the same path. If the design doc is intentionally local, say so here; otherwise the citation reintroduces exactly what D10 sets out to remove.

}

/**
* Paths where main diverged from the PR's merge-base. A rename is judged by its source: its new

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The docstring claims "paths where main diverged from the PR's merge-base", but findMainDivergence only detects structural divergence — a path main added, removed, or renamed. A file both branches independently modified stays port, which is the most common reconcile case, so the wording overstates what callers get. If concurrent modification is deliberately out of scope, naming that limitation here would keep the docstring honest.

'src/main/daemon/**',
'src/main/orca-profiles/**',
'src/main/persistence/**',
'src/main/runtime/**',

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 T2 imports deferred methods

The manifest assigns src/main/runtime/rpc/methods/index.ts to T2, but the #16741 changes to that file import and register methods assigned to deferred T7 and T8. Porting the index changes with T2 would import files that have not been ported, breaking the staged build. Those registrations need to land with their methods.

Comment on lines +231 to +240
for (const entry of entries) {
const created = addedPaths.has(entry.path) || entry.previousPath !== undefined
if (created && mainPaths.has(entry.path)) {
divergence.set(entry.path, 'main has since added its own copy; port the delta only')
} else if (entry.previousPath !== undefined && !mainPaths.has(entry.previousPath)) {
divergence.set(entry.path, 'main has since removed or renamed the rename source')
} else if (!created && !mainPaths.has(entry.path)) {
divergence.set(entry.path, 'main has since removed or renamed this file')
}
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Shared edits miss reconciliation

When main and #16741 both modify an existing file, this check sees that the path still exists and marks it port instead of reconcile. That happened for remote-install-model.ts, remote-install-gc.ts, and orcad-remote-launch.ts between the recorded merge base and main SHA. Track owners get no warning to reconcile those changes and could overwrite main's edits during the port.

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ℹ️ Minor suggestions only. Two reference details and one checked-in artifact are worth a look before merge.

Reviewed changes

  • Track manifest generator — config/scripts/pr16741-track-manifest.mjs classifies the 1,985 files of #16741 into D9 tracks (T0–T9), parses --numstat -z, detects structural main divergence, and emits a stable JSON. Verified against the committed data: 1985 files — 84 dropped, 1096 port, 12 reconcile, 793 deferred — all consistent with the rules.
  • Track rules — config/scripts/pr16741-track-rules.mjs defines TRACKS and the first-match-wins TRACK_RULES, with narrow rules above the directory catch-alls.
  • Generated manifest — config/scripts/pr16741-track-manifest.json, regenerated against origin/main = db73d28e51; oxfmt --check clean.
  • Tests — config/scripts/pr16741-track-manifest.test.mjs, 42 passing; the findMainDivergence case actually pins the rename fix.
  • Install-model doc — docs/reference/remote-server-install-model.md, allow-listed in .gitignore, replaces citations to the untracked shipping-orcad.html in six src/main/ssh/* comments and one test comment. Comments only, no runtime change.

Verification: vitest run config/scripts/pr16741-track-manifest.test.mjs → 42 passed; oxlint and oxfmt --check clean on the new files.

ℹ️ Nitpicks

  • The PR body says "14 files where main has diverged"; the committed manifest has 12 reconcile entries (d1f7655093 regenerated it after the rename fix). Worth refreshing the body so the count matches the artifact.
  • Nothing ties pr16741-track-manifest.json back to pr16741-track-rules.mjs, so a rules edit that forgets to regenerate leaves the committed data stale with no CI signal. A cheap invariant test over classifyPath (allowing reconcile as an override) would catch it; I confirmed the current file is consistent, so this is only a guard.

Pullfrog  | Fix all ➔ | Fix 👍s ➔ | View workflow run | Using DeepSeek Flash (free via Pullfrog for OSS) | 𝕏

@@ -0,0 +1,317 @@
// The D9 track table for #16741 (docs/reference/node-runtime-design.html), read by

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This cites docs/reference/node-runtime-design.html as the authority for the D9 table, but that file is not tracked in the repo — the same dangling-reference problem this PR fixes for shipping-orcad.html. pr16741-track-manifest.mjs:1 cites the same path. If the design doc is intentionally local, say so here; otherwise the citation reintroduces exactly what D10 sets out to remove.

}

/**
* Paths where main diverged from the PR's merge-base. A rename is judged by its source: its new

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The docstring claims "paths where main diverged from the PR's merge-base", but findMainDivergence only detects structural divergence — a path main added, removed, or renamed. A file both branches independently modified stays port, which is the most common reconcile case, so the wording overstates what callers get. If concurrent modification is deliberately out of scope, naming that limitation here would keep the docstring honest.

@OrcaWin

OrcaWin commented Oct 1, 2026

Copy link
Copy Markdown
Collaborator Author

Keeping the #16741 track manifest and the install-model doc local for now; not merging.

@OrcaWin OrcaWin closed this Oct 1, 2026
OrcaWin pushed a commit that referenced this pull request Oct 1, 2026
…release gate)

Dormant seam for the Phase 3 port of #16741 (design D9.3): the shared
contracts later T1/T2 slices build on. No production module imports any of
it yet; only tests do. Existing behavior is unchanged: the call-queue hold
check is a no-op until something calls holdIdleSelectors.

Adds:
- RelayWorkAdmission + relay-work-drain-contract: closes relay handler
  admission and waits for in-flight work, still admitting the cleanup
  requests/notifications (cancel, acks, unwatch) that let that work finish.
- TransportPublicationDrain: counts local write completions against one
  transport and fails sticky once that transport is replaced.
- pty-ownership-transfer-release-gate: exact-match opt-in
  (ORCA_ENABLE_PTY_OWNERSHIP_TRANSFER_MUTATION=1) that SSH core uses to keep
  live transfer off (D9.2).
- RuntimeRpcCallQueuePool.holdIdleSelectors + RuntimeRpcCallQueueBusyError:
  atomically fence idle selectors while routing changes.

Porting note (source: #16741 head a68b6f3, merge-base 277c289; T1 per
the #24137 track manifest):
- Taken verbatim: pty-ownership-transfer-release-gate(.test),
  runtime-rpc-call-queue delta (+ retirement test), relay-work-admission
  API and behavior, transport-publication-drain API and behavior.
- Adapted: relay-work-drain-contract omits relay.reset,
  relay.recoverPreparedReset (T3) and relay.networkTunnel.close/.frame
  (T4); those contracts do not exist on this base and join the sets when
  their tracks land. Promise.withResolvers replaced with plain promises in
  relay-reachable code, because the legacy relay bundle still targets
  node18 hosts. RequestContext.transportGeneration is not added here (it
  belongs with the dispatcher slice), so the admission test drops it.
  Added transport-publication-drain.test.ts, since #16741 covered it only
  through relay-producer-publication-drain.
- Dropped: the pty-source-credit-contract/-validation/-record/ledger-test
  deltas. They only carry the ownershipTransfer output envelope, which is
  live-transfer engine (T7, deferred per D9.2), so the credit contract on
  this base is already the seam T2 needs. The post-slice
  assertPtySourceSpan re-validation came with that envelope and is
  dropped with it.
- Not in this slice (next T1 slices, which are also the first consumers):
  dispatcher wiring (dispatcher-client-state / rpc-routing /
  producer-transport / notification-publication +
  RequestContext.transportGeneration) that constructs RelayWorkAdmission;
  relay-producer-publication-drain on TransportPublicationDrain; fs/git
  stream shutdown; ws-transport + node-websocket-lifecycle +
  websocket-transport-limits; renderer flow-controller deltas. Later
  consumers: T2 ssh-pty-preparation-admission (drain contract),
  ssh-pty-source-preparation-drain (release gate); T4 tunnels
  (publication drain); T5 runtime-environment-call-queue (selector hold).

No wire change: no new RPC fields, methods, or opcodes.
OrcaWin pushed a commit that referenced this pull request Oct 1, 2026
…acking

Dormant foundation for the T2 SSH core port of #16741 (design D9.3). No
production module imports it yet; only tests do, so SSH behavior is
unchanged. The next T2 slice wires SshConnection.exec/sftp/channel opens and
forwarded sockets through it.

Adds:
- SshConnectionWorkLedger: tracks local operation and channel lifetimes per
  connection. fenceForReset closes admission (except work nested under an
  already-admitted operation and one exactly-identified control channel)
  and drain() waits for the rest, failing sticky on any failure or
  unverifiable opening observed after the fence. Channel closure is local
  lifetime evidence only, never proof that a remote process exited.
- trackSshConnectionChannelLifetime / openTrackedSshSocket: bind an opened
  channel or socket to its ledger entry and settle it only on 'close'
  ('end', 'error' and the destroyed flag are not closure).

Porting note (source: #16741 head a68b6f3, merge-base 277c289; T2 per
the #24137 track manifest):
- Taken verbatim: ssh-connection-work-ledger behavior and tests,
  ssh-forward-socket-admission.test.ts, openTrackedSshSocket.
- Adapted: the ledger no longer calls assertProfileLifetimeAdmission on
  every admit. That module is an opt-in native-addon profile lock (addon
  dropped in T0) that overlaps the SQLite authority from #22612; callers
  inject their own admission check through the existing constructor
  argument instead (SshConnection will pass its disposed check). The broad
  `object` resource type became SshConnectionWorkChannel (on/once/
  removeListener), and trackSshConnectionChannelLifetime uses a type guard
  instead of a cast, so a value without removeListener is now reported
  unverifiable rather than tracked. Added ssh-connection-channel-lifetime
  tests, since #16741 covered it only through SshConnection.
- Dropped: none in these files.
- Not in this slice: SshConnection wiring (ssh-connection.ts), forwarded
  channel lifetime (T4), upload session lifetime (T6), profile lifetime
  admission/lock/participation (needs a D9.4 decision against #22612).

No wire change: nothing is sent to relays or clients.
OrcaWin pushed a commit that referenced this pull request Oct 1, 2026
Dormant foundation for the T2 SSH core port of #16741. No production module
imports it yet, so SSH behavior is unchanged; the next T2 slice has
SshConnection track every ssh2 client it allocates and gate its
transport-closure subscribers on this ledger plus the work ledger.

Adds:
- SshTransportCloseLedger: remembers every allocated client (including
  ones whose authentication failed) until it emits 'close'. drain() waits
  for the snapshot and fails with ssh_client_close_allocations_changed if a
  client was allocated after the caller should have fenced allocation.
  Authentication settlement, 'end' and 'error' are not physical closure.
- observeSshTransportClose: registers 'close' listeners on a set of
  transport resources before close is initiated; wait() is cancelable
  without dropping the evidence, dispose() removes the listeners.

Porting note (source: #16741 head a68b6f3, merge-base 277c289; T2 per
the #24137 track manifest):
- Taken verbatim: both modules and ssh-transport-close-ledger.test.ts.
- Adapted: the ledger test no longer casts EventEmitter to ssh2 Client,
  since track() already accepts an EventEmitter. Added
  ssh-transport-close-observation tests, since #16741 covered it only
  through SshConnection.dispose.
- Dropped: none.

No wire change. Loss of transport is still reported as unverifiable, never
as remote process exit.
OrcaWin added a commit that referenced this pull request Oct 1, 2026
…release gate) (#24156)

Dormant seam for the Phase 3 port of #16741 (design D9.3): the shared
contracts later T1/T2 slices build on. No production module imports any of
it yet; only tests do. Existing behavior is unchanged: the call-queue hold
check is a no-op until something calls holdIdleSelectors.

Adds:
- RelayWorkAdmission + relay-work-drain-contract: closes relay handler
  admission and waits for in-flight work, still admitting the cleanup
  requests/notifications (cancel, acks, unwatch) that let that work finish.
- TransportPublicationDrain: counts local write completions against one
  transport and fails sticky once that transport is replaced.
- pty-ownership-transfer-release-gate: exact-match opt-in
  (ORCA_ENABLE_PTY_OWNERSHIP_TRANSFER_MUTATION=1) that SSH core uses to keep
  live transfer off (D9.2).
- RuntimeRpcCallQueuePool.holdIdleSelectors + RuntimeRpcCallQueueBusyError:
  atomically fence idle selectors while routing changes.

Porting note (source: #16741 head a68b6f3, merge-base 277c289; T1 per
the #24137 track manifest):
- Taken verbatim: pty-ownership-transfer-release-gate(.test),
  runtime-rpc-call-queue delta (+ retirement test), relay-work-admission
  API and behavior, transport-publication-drain API and behavior.
- Adapted: relay-work-drain-contract omits relay.reset,
  relay.recoverPreparedReset (T3) and relay.networkTunnel.close/.frame
  (T4); those contracts do not exist on this base and join the sets when
  their tracks land. Promise.withResolvers replaced with plain promises in
  relay-reachable code, because the legacy relay bundle still targets
  node18 hosts. RequestContext.transportGeneration is not added here (it
  belongs with the dispatcher slice), so the admission test drops it.
  Added transport-publication-drain.test.ts, since #16741 covered it only
  through relay-producer-publication-drain.
- Dropped: the pty-source-credit-contract/-validation/-record/ledger-test
  deltas. They only carry the ownershipTransfer output envelope, which is
  live-transfer engine (T7, deferred per D9.2), so the credit contract on
  this base is already the seam T2 needs. The post-slice
  assertPtySourceSpan re-validation came with that envelope and is
  dropped with it.
- Not in this slice (next T1 slices, which are also the first consumers):
  dispatcher wiring (dispatcher-client-state / rpc-routing /
  producer-transport / notification-publication +
  RequestContext.transportGeneration) that constructs RelayWorkAdmission;
  relay-producer-publication-drain on TransportPublicationDrain; fs/git
  stream shutdown; ws-transport + node-websocket-lifecycle +
  websocket-transport-limits; renderer flow-controller deltas. Later
  consumers: T2 ssh-pty-preparation-admission (drain contract),
  ssh-pty-source-preparation-drain (release gate); T4 tunnels
  (publication drain); T5 runtime-environment-call-queue (selector hold).

No wire change: no new RPC fields, methods, or opcodes.

Co-authored-by: m4air <m4air@m4airs-Air.localdomain>
OrcaWin pushed a commit that referenced this pull request Oct 1, 2026
…acking

Dormant foundation for the T2 SSH core port of #16741 (design D9.3). No
production module imports it yet; only tests do, so SSH behavior is
unchanged. The next T2 slice wires SshConnection.exec/sftp/channel opens and
forwarded sockets through it.

Adds:
- SshConnectionWorkLedger: tracks local operation and channel lifetimes per
  connection. fenceForReset closes admission (except work nested under an
  already-admitted operation and one exactly-identified control channel)
  and drain() waits for the rest, failing sticky on any failure or
  unverifiable opening observed after the fence. Channel closure is local
  lifetime evidence only, never proof that a remote process exited.
- trackSshConnectionChannelLifetime / openTrackedSshSocket: bind an opened
  channel or socket to its ledger entry and settle it only on 'close'
  ('end', 'error' and the destroyed flag are not closure).

Porting note (source: #16741 head a68b6f3, merge-base 277c289; T2 per
the #24137 track manifest):
- Taken verbatim: ssh-connection-work-ledger behavior and tests,
  ssh-forward-socket-admission.test.ts, openTrackedSshSocket.
- Adapted: the ledger no longer calls assertProfileLifetimeAdmission on
  every admit. That module is an opt-in native-addon profile lock (addon
  dropped in T0) that overlaps the SQLite authority from #22612; callers
  inject their own admission check through the existing constructor
  argument instead (SshConnection will pass its disposed check). The broad
  `object` resource type became SshConnectionWorkChannel (on/once/
  removeListener), and trackSshConnectionChannelLifetime uses a type guard
  instead of a cast, so a value without removeListener is now reported
  unverifiable rather than tracked. Added ssh-connection-channel-lifetime
  tests, since #16741 covered it only through SshConnection.
- Dropped: none in these files.
- Not in this slice: SshConnection wiring (ssh-connection.ts), forwarded
  channel lifetime (T4), upload session lifetime (T6), profile lifetime
  admission/lock/participation (needs a D9.4 decision against #22612).

No wire change: nothing is sent to relays or clients.
OrcaWin pushed a commit that referenced this pull request Oct 1, 2026
Dormant foundation for the T2 SSH core port of #16741. No production module
imports it yet, so SSH behavior is unchanged; the next T2 slice has
SshConnection track every ssh2 client it allocates and gate its
transport-closure subscribers on this ledger plus the work ledger.

Adds:
- SshTransportCloseLedger: remembers every allocated client (including
  ones whose authentication failed) until it emits 'close'. drain() waits
  for the snapshot and fails with ssh_client_close_allocations_changed if a
  client was allocated after the caller should have fenced allocation.
  Authentication settlement, 'end' and 'error' are not physical closure.
- observeSshTransportClose: registers 'close' listeners on a set of
  transport resources before close is initiated; wait() is cancelable
  without dropping the evidence, dispose() removes the listeners.

Porting note (source: #16741 head a68b6f3, merge-base 277c289; T2 per
the #24137 track manifest):
- Taken verbatim: both modules and ssh-transport-close-ledger.test.ts.
- Adapted: the ledger test no longer casts EventEmitter to ssh2 Client,
  since track() already accepts an EventEmitter. Added
  ssh-transport-close-observation tests, since #16741 covered it only
  through SshConnection.dispose.
- Dropped: none.

No wire change. Loss of transport is still reported as unverifiable, never
as remote process exit.
OrcaWin added a commit that referenced this pull request Oct 1, 2026
…dger (#16741 T2) (#24210)

* feat(ssh): add the SSH connection work ledger and channel lifetime tracking

Dormant foundation for the T2 SSH core port of #16741 (design D9.3). No
production module imports it yet; only tests do, so SSH behavior is
unchanged. The next T2 slice wires SshConnection.exec/sftp/channel opens and
forwarded sockets through it.

Adds:
- SshConnectionWorkLedger: tracks local operation and channel lifetimes per
  connection. fenceForReset closes admission (except work nested under an
  already-admitted operation and one exactly-identified control channel)
  and drain() waits for the rest, failing sticky on any failure or
  unverifiable opening observed after the fence. Channel closure is local
  lifetime evidence only, never proof that a remote process exited.
- trackSshConnectionChannelLifetime / openTrackedSshSocket: bind an opened
  channel or socket to its ledger entry and settle it only on 'close'
  ('end', 'error' and the destroyed flag are not closure).

Porting note (source: #16741 head a68b6f3, merge-base 277c289; T2 per
the #24137 track manifest):
- Taken verbatim: ssh-connection-work-ledger behavior and tests,
  ssh-forward-socket-admission.test.ts, openTrackedSshSocket.
- Adapted: the ledger no longer calls assertProfileLifetimeAdmission on
  every admit. That module is an opt-in native-addon profile lock (addon
  dropped in T0) that overlaps the SQLite authority from #22612; callers
  inject their own admission check through the existing constructor
  argument instead (SshConnection will pass its disposed check). The broad
  `object` resource type became SshConnectionWorkChannel (on/once/
  removeListener), and trackSshConnectionChannelLifetime uses a type guard
  instead of a cast, so a value without removeListener is now reported
  unverifiable rather than tracked. Added ssh-connection-channel-lifetime
  tests, since #16741 covered it only through SshConnection.
- Dropped: none in these files.
- Not in this slice: SshConnection wiring (ssh-connection.ts), forwarded
  channel lifetime (T4), upload session lifetime (T6), profile lifetime
  admission/lock/participation (needs a D9.4 decision against #22612).

No wire change: nothing is sent to relays or clients.

* feat(ssh): add SSH transport close ledger and close observation

Dormant foundation for the T2 SSH core port of #16741. No production module
imports it yet, so SSH behavior is unchanged; the next T2 slice has
SshConnection track every ssh2 client it allocates and gate its
transport-closure subscribers on this ledger plus the work ledger.

Adds:
- SshTransportCloseLedger: remembers every allocated client (including
  ones whose authentication failed) until it emits 'close'. drain() waits
  for the snapshot and fails with ssh_client_close_allocations_changed if a
  client was allocated after the caller should have fenced allocation.
  Authentication settlement, 'end' and 'error' are not physical closure.
- observeSshTransportClose: registers 'close' listeners on a set of
  transport resources before close is initiated; wait() is cancelable
  without dropping the evidence, dispose() removes the listeners.

Porting note (source: #16741 head a68b6f3, merge-base 277c289; T2 per
the #24137 track manifest):
- Taken verbatim: both modules and ssh-transport-close-ledger.test.ts.
- Adapted: the ledger test no longer casts EventEmitter to ssh2 Client,
  since track() already accepts an EventEmitter. Added
  ssh-transport-close-observation tests, since #16741 covered it only
  through SshConnection.dispose.
- Dropped: none.

No wire change. Loss of transport is still reported as unverifiable, never
as remote process exit.

---------

Co-authored-by: m4air <m4air@m4airs-Air.localdomain>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant