Make multiple Prime provider instances safe and truthful #199

Description

@rynfar

Problem

Pylon's generic instance UI already allows more than one Prime provider even though the driver reports supportsMultipleInstances: false; that metadata is not enforced or sent to clients. Most Prime control paths are instance-scoped, but native daemon multi-instance operation is not yet safe:

  • recovered owned workers can receive ambient server credentials/environment instead of the owning instance's environment;
  • home identity differs between daemon spawn and auth/model/capacity reads;
  • blank/default or symlink-aliased homes can accidentally share account, settings, extensions, skills, harness state, logs, updates, and maintenance behavior;
  • same-ID provider replacement can accept stale status, model, capacity, maintenance, rate-limit, or usage results from the prior account/configuration;
  • forced teardown has an unbounded post-kill wait and owned-session completion is not observable;
  • OS-user-global Prime maintenance and stop --all behavior can affect all local Prime daemons.

Treat multi-Prime as reachable today, not as a future toggle.

Required invariant

One enabled Prime instance has one immutable server-owned runtime context: { instanceId, generation, configRevision, effectiveHome, exactLaunchEnv, backendKind }. Every launch, attach, recovery, probe, catalog/model read, auth/capacity read, cache receipt, event subscription, mutation, and cleanup must consume or verify that same context. Never recompute home or environment later from raw PrimeAgentSettings. Runtime generation and config revision are correlation fences only; they never identify an account or enter public events, provider snapshots, logs, or telemetry.

Dependencies

Blocked on prime-agent#33, which owns the public SDK caller-owned recovery-environment and observable-cleanup capability. Native multi-instance mode must require all three current proofs before Pylon admits a native runtime: frozen SDK metadata containing both negotiated_daemon_session_capabilities_v1 and caller_owned_session_environment_cleanup_v1, the server's negotiated offer, and getOwnedSessionContractProof() from the successful current owned attach. Missing, stale, invalidated, or contradictory proof selects ACP. Never infer support from a version, package provenance, method presence, or an earlier attachment.

Final native enablement is also blocked on prime-agent#27 and #84 for the Pylon-restart case. A replacement Pylon process has no prior owner connection and cannot treat generic daemon shutdown, socket closure, or supervisor PID exit as proof that every old owned worker settled. The final gate requires exact adoption followed by owner-scoped cleanup, or a separate public aggregate cleanup receipt with equivalent authority. PRs 1–3 below may land before that gate; PR 4 may not advertise native multi-instance support until the restart case is proved.

Ordered implementation

  1. Effective identity and capability gate. Merge the host snapshot and ordered instance overrides once; remove reserved Prime-internal/RLM keys; resolve explicit agent home, environment agent home, or the default against the merged effective OS home; canonicalize through the nearest existing ancestor; then stamp the canonical home into the exact launch environment. Apply that context to daemon, ACP, status, catalog, model, capacity, attach, recovery, and cleanup. Preflight every enabled instance before process launch and reject every participant in an equal/ancestor/symlink-aliased home overlap group. Pass exact ownedSessionLaunchEnv, require the full native proof, and add defensive MCP provider-instance assertions. Keep supportsMultipleInstances: false.
  2. Provider-generation fencing. Give every materialization/config revision an opaque in-process generation. Every subscription, refresh, capacity run, overlay, maintenance action, runtime event, MCP cleanup, and cache write captures { instanceId, driver, generation } and rechecks it at commit. On replacement, synchronously clear old account/backend/volatile state. Use a server-owned random configRevision for private disk-cache correlation and rotate it for every material config/environment/secret change. Legacy, missing, invalid, or unproved revisions are cold misses. Never hash materialized environment or secret values, and never add a new key subsystem only to warm this cache.
  3. Bounded teardown and durable quarantine. Bound graceful shutdown, force-kill, post-kill exit, socket cleanup, and scope close. Use single-flight disposeOwnedSession() and preserve its fixed completed, already-completed, owner-mismatch, uncertain-timeout, transport-failure, unsupported, and valid replacement-settled outcomes. Cleanup is proved only by an outcome tied to this connection's current or prior successful owned-attach proof and opaque session identity. Close only the instance-private daemon as final containment. Write a private atomic active-ownership receipt before every native client-owned create, scoped per session attempt and canonical home; remove only that attempt after the same live owner proves completion or proves ownership was never acquired. A crash, timeout, owner mismatch, transport loss, invalid result, or corrupt/unknown receipt leaves it dirty. Reload receipts before provider materialization and block every equal/ancestor/descendant home until docs: record the twelfth upstream batch #27/Prime Agent active turns cannot survive a Pylon server restart #84 identity-safe adoption and cleanup, or explicit documented remediation, clears them. Never ask an arbitrary replacement client to claim historical ownership.
  4. Truthful support and UX. Propagate and enforce supportsMultipleInstances in server validation, Settings, and the Add dialog. Flip Prime to true only after PRs 1–3, feat(prime): remove sole queued inputs #33, the docs: record the twelfth upstream batch #27/Prime Agent active turns cannot survive a Pylon server restart #84 restart truth gate, real A/B isolation tests, and N=1/2/4 resource measurements pass. Require or guide users to a distinct home and separate sign-in/state per instance. Explain ACP degradation on supported runtimes, WSL2 guidance, and the OS-user-global maintenance boundary. Web and desktop inherit the same server gate; mobile remains selection-only and must omit disabled, unavailable, or quarantined instances.

Acceptance coverage

  • Explicit-home, environment-only home, HOME/default resolution, relative paths, symlink aliases, non-overlap, and reserved environment keys.
  • Two real Prime instances with different homes, accounts, binaries, settings, model catalogs, capacity, sessions, sockets, checkpoints, MCP tokens, and credential sentinels.
  • Worker crash, daemon reconnect/replacement, Pylon restart, settings replacement, one-instance removal, and concurrent stop without cross-account data or cleanup. Prove post-attach proof invalidation and republication across each native reconnect/replacement path.
  • Deferred old status/catalog/capacity/usage/maintenance/rate-limit results and queued adapter events released after replacement never overwrite the new generation or clear the new MCP session.
  • Legacy/missing config revisions start cold; secret changes rotate correlation without hashing, logging, or exposing secret-derived values.
  • Hung graceful shutdown, hung post-kill exit, every fixed observable cleanup outcome, unsupported/contradictory capability proof, and fallback remain bounded and truthful.
  • Native ownership receipt precedes create; abrupt crash leaves it dirty; the next boot launches zero overlapping instances; concurrent attempts never cross-clear; corrupt receipts fail closed; ACP writes no native receipt.
  • ACP degradation stays explicit and verified on supported runtimes. Native Windows Prime execution/fallback is deferred; WSL2 uses the Linux runtime.
  • Measure N=1/2/4 process, memory, file-descriptor/handle, socket, and startup costs; document supported limits.
  • Cover web, desktop-hosted server, mobile selection, local, remote/relay, tunnel, multi-client, macOS, Linux, and WSL2. Verify at least one non-Prime provider remains unchanged. Windows clients may connect to WSL2; native Windows Prime execution is not a current gate.

Scope and non-goals

Use one PR per ordered concern. Shared Prime homes are not safe v1 and may be considered later only as an explicit opt-in. Do not mutate global process.env; persist or expose secret-derived fingerprints; treat generic shutdown/PID/socket state as owned cleanup proof; add a broad stop --all path; broaden the same-OS-user threat model; add hostile-co-tenant isolation; touch Prime #20; or include Comet.

Coordinate with #114 and prime-agent#33.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions

      , 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
       blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
      }
      } catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
      })();
      (function(){
      try {
      var __m = "github.com";
      var __re = new RegExp('^' + "github\\.com" + '
      
      Skip to content

      Make multiple Prime provider instances safe and truthful #199

      Description

      @rynfar

      Problem

      Pylon's generic instance UI already allows more than one Prime provider even though the driver reports supportsMultipleInstances: false; that metadata is not enforced or sent to clients. Most Prime control paths are instance-scoped, but native daemon multi-instance operation is not yet safe:

      • recovered owned workers can receive ambient server credentials/environment instead of the owning instance's environment;
      • home identity differs between daemon spawn and auth/model/capacity reads;
      • blank/default or symlink-aliased homes can accidentally share account, settings, extensions, skills, harness state, logs, updates, and maintenance behavior;
      • same-ID provider replacement can accept stale status, model, capacity, maintenance, rate-limit, or usage results from the prior account/configuration;
      • forced teardown has an unbounded post-kill wait and owned-session completion is not observable;
      • OS-user-global Prime maintenance and stop --all behavior can affect all local Prime daemons.

      Treat multi-Prime as reachable today, not as a future toggle.

      Required invariant

      One enabled Prime instance has one immutable server-owned runtime context: { instanceId, generation, configRevision, effectiveHome, exactLaunchEnv, backendKind }. Every launch, attach, recovery, probe, catalog/model read, auth/capacity read, cache receipt, event subscription, mutation, and cleanup must consume or verify that same context. Never recompute home or environment later from raw PrimeAgentSettings. Runtime generation and config revision are correlation fences only; they never identify an account or enter public events, provider snapshots, logs, or telemetry.

      Dependencies

      Blocked on prime-agent#33, which owns the public SDK caller-owned recovery-environment and observable-cleanup capability. Native multi-instance mode must require all three current proofs before Pylon admits a native runtime: frozen SDK metadata containing both negotiated_daemon_session_capabilities_v1 and caller_owned_session_environment_cleanup_v1, the server's negotiated offer, and getOwnedSessionContractProof() from the successful current owned attach. Missing, stale, invalidated, or contradictory proof selects ACP. Never infer support from a version, package provenance, method presence, or an earlier attachment.

      Final native enablement is also blocked on prime-agent#27 and #84 for the Pylon-restart case. A replacement Pylon process has no prior owner connection and cannot treat generic daemon shutdown, socket closure, or supervisor PID exit as proof that every old owned worker settled. The final gate requires exact adoption followed by owner-scoped cleanup, or a separate public aggregate cleanup receipt with equivalent authority. PRs 1–3 below may land before that gate; PR 4 may not advertise native multi-instance support until the restart case is proved.

      Ordered implementation

      1. Effective identity and capability gate. Merge the host snapshot and ordered instance overrides once; remove reserved Prime-internal/RLM keys; resolve explicit agent home, environment agent home, or the default against the merged effective OS home; canonicalize through the nearest existing ancestor; then stamp the canonical home into the exact launch environment. Apply that context to daemon, ACP, status, catalog, model, capacity, attach, recovery, and cleanup. Preflight every enabled instance before process launch and reject every participant in an equal/ancestor/symlink-aliased home overlap group. Pass exact ownedSessionLaunchEnv, require the full native proof, and add defensive MCP provider-instance assertions. Keep supportsMultipleInstances: false.
      2. Provider-generation fencing. Give every materialization/config revision an opaque in-process generation. Every subscription, refresh, capacity run, overlay, maintenance action, runtime event, MCP cleanup, and cache write captures { instanceId, driver, generation } and rechecks it at commit. On replacement, synchronously clear old account/backend/volatile state. Use a server-owned random configRevision for private disk-cache correlation and rotate it for every material config/environment/secret change. Legacy, missing, invalid, or unproved revisions are cold misses. Never hash materialized environment or secret values, and never add a new key subsystem only to warm this cache.
      3. Bounded teardown and durable quarantine. Bound graceful shutdown, force-kill, post-kill exit, socket cleanup, and scope close. Use single-flight disposeOwnedSession() and preserve its fixed completed, already-completed, owner-mismatch, uncertain-timeout, transport-failure, unsupported, and valid replacement-settled outcomes. Cleanup is proved only by an outcome tied to this connection's current or prior successful owned-attach proof and opaque session identity. Close only the instance-private daemon as final containment. Write a private atomic active-ownership receipt before every native client-owned create, scoped per session attempt and canonical home; remove only that attempt after the same live owner proves completion or proves ownership was never acquired. A crash, timeout, owner mismatch, transport loss, invalid result, or corrupt/unknown receipt leaves it dirty. Reload receipts before provider materialization and block every equal/ancestor/descendant home until docs: record the twelfth upstream batch #27/Prime Agent active turns cannot survive a Pylon server restart #84 identity-safe adoption and cleanup, or explicit documented remediation, clears them. Never ask an arbitrary replacement client to claim historical ownership.
      4. Truthful support and UX. Propagate and enforce supportsMultipleInstances in server validation, Settings, and the Add dialog. Flip Prime to true only after PRs 1–3, feat(prime): remove sole queued inputs #33, the docs: record the twelfth upstream batch #27/Prime Agent active turns cannot survive a Pylon server restart #84 restart truth gate, real A/B isolation tests, and N=1/2/4 resource measurements pass. Require or guide users to a distinct home and separate sign-in/state per instance. Explain ACP degradation on supported runtimes, WSL2 guidance, and the OS-user-global maintenance boundary. Web and desktop inherit the same server gate; mobile remains selection-only and must omit disabled, unavailable, or quarantined instances.

      Acceptance coverage

      • Explicit-home, environment-only home, HOME/default resolution, relative paths, symlink aliases, non-overlap, and reserved environment keys.
      • Two real Prime instances with different homes, accounts, binaries, settings, model catalogs, capacity, sessions, sockets, checkpoints, MCP tokens, and credential sentinels.
      • Worker crash, daemon reconnect/replacement, Pylon restart, settings replacement, one-instance removal, and concurrent stop without cross-account data or cleanup. Prove post-attach proof invalidation and republication across each native reconnect/replacement path.
      • Deferred old status/catalog/capacity/usage/maintenance/rate-limit results and queued adapter events released after replacement never overwrite the new generation or clear the new MCP session.
      • Legacy/missing config revisions start cold; secret changes rotate correlation without hashing, logging, or exposing secret-derived values.
      • Hung graceful shutdown, hung post-kill exit, every fixed observable cleanup outcome, unsupported/contradictory capability proof, and fallback remain bounded and truthful.
      • Native ownership receipt precedes create; abrupt crash leaves it dirty; the next boot launches zero overlapping instances; concurrent attempts never cross-clear; corrupt receipts fail closed; ACP writes no native receipt.
      • ACP degradation stays explicit and verified on supported runtimes. Native Windows Prime execution/fallback is deferred; WSL2 uses the Linux runtime.
      • Measure N=1/2/4 process, memory, file-descriptor/handle, socket, and startup costs; document supported limits.
      • Cover web, desktop-hosted server, mobile selection, local, remote/relay, tunnel, multi-client, macOS, Linux, and WSL2. Verify at least one non-Prime provider remains unchanged. Windows clients may connect to WSL2; native Windows Prime execution is not a current gate.

      Scope and non-goals

      Use one PR per ordered concern. Shared Prime homes are not safe v1 and may be considered later only as an explicit opt-in. Do not mutate global process.env; persist or expose secret-derived fingerprints; treat generic shutdown/PID/socket state as owned cleanup proof; add a broad stop --all path; broaden the same-OS-user threat model; add hostile-co-tenant isolation; touch Prime #20; or include Comet.

      Coordinate with #114 and prime-agent#33.

      Metadata

      Metadata

      Assignees

      No one assigned

        Labels

        Type

        No type

        Projects

        No projects

          Milestone

          No milestone

          Relationships

          None yet

          Development

          No branches or pull requests

          Issue actions

          , 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
          Skip to content

          Make multiple Prime provider instances safe and truthful #199

          Description

          @rynfar

          Problem

          Pylon's generic instance UI already allows more than one Prime provider even though the driver reports supportsMultipleInstances: false; that metadata is not enforced or sent to clients. Most Prime control paths are instance-scoped, but native daemon multi-instance operation is not yet safe:

          • recovered owned workers can receive ambient server credentials/environment instead of the owning instance's environment;
          • home identity differs between daemon spawn and auth/model/capacity reads;
          • blank/default or symlink-aliased homes can accidentally share account, settings, extensions, skills, harness state, logs, updates, and maintenance behavior;
          • same-ID provider replacement can accept stale status, model, capacity, maintenance, rate-limit, or usage results from the prior account/configuration;
          • forced teardown has an unbounded post-kill wait and owned-session completion is not observable;
          • OS-user-global Prime maintenance and stop --all behavior can affect all local Prime daemons.

          Treat multi-Prime as reachable today, not as a future toggle.

          Required invariant

          One enabled Prime instance has one immutable server-owned runtime context: { instanceId, generation, configRevision, effectiveHome, exactLaunchEnv, backendKind }. Every launch, attach, recovery, probe, catalog/model read, auth/capacity read, cache receipt, event subscription, mutation, and cleanup must consume or verify that same context. Never recompute home or environment later from raw PrimeAgentSettings. Runtime generation and config revision are correlation fences only; they never identify an account or enter public events, provider snapshots, logs, or telemetry.

          Dependencies

          Blocked on prime-agent#33, which owns the public SDK caller-owned recovery-environment and observable-cleanup capability. Native multi-instance mode must require all three current proofs before Pylon admits a native runtime: frozen SDK metadata containing both negotiated_daemon_session_capabilities_v1 and caller_owned_session_environment_cleanup_v1, the server's negotiated offer, and getOwnedSessionContractProof() from the successful current owned attach. Missing, stale, invalidated, or contradictory proof selects ACP. Never infer support from a version, package provenance, method presence, or an earlier attachment.

          Final native enablement is also blocked on prime-agent#27 and #84 for the Pylon-restart case. A replacement Pylon process has no prior owner connection and cannot treat generic daemon shutdown, socket closure, or supervisor PID exit as proof that every old owned worker settled. The final gate requires exact adoption followed by owner-scoped cleanup, or a separate public aggregate cleanup receipt with equivalent authority. PRs 1–3 below may land before that gate; PR 4 may not advertise native multi-instance support until the restart case is proved.

          Ordered implementation

          1. Effective identity and capability gate. Merge the host snapshot and ordered instance overrides once; remove reserved Prime-internal/RLM keys; resolve explicit agent home, environment agent home, or the default against the merged effective OS home; canonicalize through the nearest existing ancestor; then stamp the canonical home into the exact launch environment. Apply that context to daemon, ACP, status, catalog, model, capacity, attach, recovery, and cleanup. Preflight every enabled instance before process launch and reject every participant in an equal/ancestor/symlink-aliased home overlap group. Pass exact ownedSessionLaunchEnv, require the full native proof, and add defensive MCP provider-instance assertions. Keep supportsMultipleInstances: false.
          2. Provider-generation fencing. Give every materialization/config revision an opaque in-process generation. Every subscription, refresh, capacity run, overlay, maintenance action, runtime event, MCP cleanup, and cache write captures { instanceId, driver, generation } and rechecks it at commit. On replacement, synchronously clear old account/backend/volatile state. Use a server-owned random configRevision for private disk-cache correlation and rotate it for every material config/environment/secret change. Legacy, missing, invalid, or unproved revisions are cold misses. Never hash materialized environment or secret values, and never add a new key subsystem only to warm this cache.
          3. Bounded teardown and durable quarantine. Bound graceful shutdown, force-kill, post-kill exit, socket cleanup, and scope close. Use single-flight disposeOwnedSession() and preserve its fixed completed, already-completed, owner-mismatch, uncertain-timeout, transport-failure, unsupported, and valid replacement-settled outcomes. Cleanup is proved only by an outcome tied to this connection's current or prior successful owned-attach proof and opaque session identity. Close only the instance-private daemon as final containment. Write a private atomic active-ownership receipt before every native client-owned create, scoped per session attempt and canonical home; remove only that attempt after the same live owner proves completion or proves ownership was never acquired. A crash, timeout, owner mismatch, transport loss, invalid result, or corrupt/unknown receipt leaves it dirty. Reload receipts before provider materialization and block every equal/ancestor/descendant home until docs: record the twelfth upstream batch #27/Prime Agent active turns cannot survive a Pylon server restart #84 identity-safe adoption and cleanup, or explicit documented remediation, clears them. Never ask an arbitrary replacement client to claim historical ownership.
          4. Truthful support and UX. Propagate and enforce supportsMultipleInstances in server validation, Settings, and the Add dialog. Flip Prime to true only after PRs 1–3, feat(prime): remove sole queued inputs #33, the docs: record the twelfth upstream batch #27/Prime Agent active turns cannot survive a Pylon server restart #84 restart truth gate, real A/B isolation tests, and N=1/2/4 resource measurements pass. Require or guide users to a distinct home and separate sign-in/state per instance. Explain ACP degradation on supported runtimes, WSL2 guidance, and the OS-user-global maintenance boundary. Web and desktop inherit the same server gate; mobile remains selection-only and must omit disabled, unavailable, or quarantined instances.

          Acceptance coverage

          • Explicit-home, environment-only home, HOME/default resolution, relative paths, symlink aliases, non-overlap, and reserved environment keys.
          • Two real Prime instances with different homes, accounts, binaries, settings, model catalogs, capacity, sessions, sockets, checkpoints, MCP tokens, and credential sentinels.
          • Worker crash, daemon reconnect/replacement, Pylon restart, settings replacement, one-instance removal, and concurrent stop without cross-account data or cleanup. Prove post-attach proof invalidation and republication across each native reconnect/replacement path.
          • Deferred old status/catalog/capacity/usage/maintenance/rate-limit results and queued adapter events released after replacement never overwrite the new generation or clear the new MCP session.
          • Legacy/missing config revisions start cold; secret changes rotate correlation without hashing, logging, or exposing secret-derived values.
          • Hung graceful shutdown, hung post-kill exit, every fixed observable cleanup outcome, unsupported/contradictory capability proof, and fallback remain bounded and truthful.
          • Native ownership receipt precedes create; abrupt crash leaves it dirty; the next boot launches zero overlapping instances; concurrent attempts never cross-clear; corrupt receipts fail closed; ACP writes no native receipt.
          • ACP degradation stays explicit and verified on supported runtimes. Native Windows Prime execution/fallback is deferred; WSL2 uses the Linux runtime.
          • Measure N=1/2/4 process, memory, file-descriptor/handle, socket, and startup costs; document supported limits.
          • Cover web, desktop-hosted server, mobile selection, local, remote/relay, tunnel, multi-client, macOS, Linux, and WSL2. Verify at least one non-Prime provider remains unchanged. Windows clients may connect to WSL2; native Windows Prime execution is not a current gate.

          Scope and non-goals

          Use one PR per ordered concern. Shared Prime homes are not safe v1 and may be considered later only as an explicit opt-in. Do not mutate global process.env; persist or expose secret-derived fingerprints; treat generic shutdown/PID/socket state as owned cleanup proof; add a broad stop --all path; broaden the same-OS-user threat model; add hostile-co-tenant isolation; touch Prime #20; or include Comet.

          Coordinate with #114 and prime-agent#33.

          Metadata

          Metadata

          Assignees

          No one assigned

            Labels

            Type

            No type

            Projects

            No projects

              Milestone

              No milestone

              Relationships

              None yet

              Development

              No branches or pull requests

              Issue actions

              , 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
              Skip to content

              Make multiple Prime provider instances safe and truthful #199

              Description

              @rynfar

              Problem

              Pylon's generic instance UI already allows more than one Prime provider even though the driver reports supportsMultipleInstances: false; that metadata is not enforced or sent to clients. Most Prime control paths are instance-scoped, but native daemon multi-instance operation is not yet safe:

              • recovered owned workers can receive ambient server credentials/environment instead of the owning instance's environment;
              • home identity differs between daemon spawn and auth/model/capacity reads;
              • blank/default or symlink-aliased homes can accidentally share account, settings, extensions, skills, harness state, logs, updates, and maintenance behavior;
              • same-ID provider replacement can accept stale status, model, capacity, maintenance, rate-limit, or usage results from the prior account/configuration;
              • forced teardown has an unbounded post-kill wait and owned-session completion is not observable;
              • OS-user-global Prime maintenance and stop --all behavior can affect all local Prime daemons.

              Treat multi-Prime as reachable today, not as a future toggle.

              Required invariant

              One enabled Prime instance has one immutable server-owned runtime context: { instanceId, generation, configRevision, effectiveHome, exactLaunchEnv, backendKind }. Every launch, attach, recovery, probe, catalog/model read, auth/capacity read, cache receipt, event subscription, mutation, and cleanup must consume or verify that same context. Never recompute home or environment later from raw PrimeAgentSettings. Runtime generation and config revision are correlation fences only; they never identify an account or enter public events, provider snapshots, logs, or telemetry.

              Dependencies

              Blocked on prime-agent#33, which owns the public SDK caller-owned recovery-environment and observable-cleanup capability. Native multi-instance mode must require all three current proofs before Pylon admits a native runtime: frozen SDK metadata containing both negotiated_daemon_session_capabilities_v1 and caller_owned_session_environment_cleanup_v1, the server's negotiated offer, and getOwnedSessionContractProof() from the successful current owned attach. Missing, stale, invalidated, or contradictory proof selects ACP. Never infer support from a version, package provenance, method presence, or an earlier attachment.

              Final native enablement is also blocked on prime-agent#27 and #84 for the Pylon-restart case. A replacement Pylon process has no prior owner connection and cannot treat generic daemon shutdown, socket closure, or supervisor PID exit as proof that every old owned worker settled. The final gate requires exact adoption followed by owner-scoped cleanup, or a separate public aggregate cleanup receipt with equivalent authority. PRs 1–3 below may land before that gate; PR 4 may not advertise native multi-instance support until the restart case is proved.

              Ordered implementation

              1. Effective identity and capability gate. Merge the host snapshot and ordered instance overrides once; remove reserved Prime-internal/RLM keys; resolve explicit agent home, environment agent home, or the default against the merged effective OS home; canonicalize through the nearest existing ancestor; then stamp the canonical home into the exact launch environment. Apply that context to daemon, ACP, status, catalog, model, capacity, attach, recovery, and cleanup. Preflight every enabled instance before process launch and reject every participant in an equal/ancestor/symlink-aliased home overlap group. Pass exact ownedSessionLaunchEnv, require the full native proof, and add defensive MCP provider-instance assertions. Keep supportsMultipleInstances: false.
              2. Provider-generation fencing. Give every materialization/config revision an opaque in-process generation. Every subscription, refresh, capacity run, overlay, maintenance action, runtime event, MCP cleanup, and cache write captures { instanceId, driver, generation } and rechecks it at commit. On replacement, synchronously clear old account/backend/volatile state. Use a server-owned random configRevision for private disk-cache correlation and rotate it for every material config/environment/secret change. Legacy, missing, invalid, or unproved revisions are cold misses. Never hash materialized environment or secret values, and never add a new key subsystem only to warm this cache.
              3. Bounded teardown and durable quarantine. Bound graceful shutdown, force-kill, post-kill exit, socket cleanup, and scope close. Use single-flight disposeOwnedSession() and preserve its fixed completed, already-completed, owner-mismatch, uncertain-timeout, transport-failure, unsupported, and valid replacement-settled outcomes. Cleanup is proved only by an outcome tied to this connection's current or prior successful owned-attach proof and opaque session identity. Close only the instance-private daemon as final containment. Write a private atomic active-ownership receipt before every native client-owned create, scoped per session attempt and canonical home; remove only that attempt after the same live owner proves completion or proves ownership was never acquired. A crash, timeout, owner mismatch, transport loss, invalid result, or corrupt/unknown receipt leaves it dirty. Reload receipts before provider materialization and block every equal/ancestor/descendant home until docs: record the twelfth upstream batch #27/Prime Agent active turns cannot survive a Pylon server restart #84 identity-safe adoption and cleanup, or explicit documented remediation, clears them. Never ask an arbitrary replacement client to claim historical ownership.
              4. Truthful support and UX. Propagate and enforce supportsMultipleInstances in server validation, Settings, and the Add dialog. Flip Prime to true only after PRs 1–3, feat(prime): remove sole queued inputs #33, the docs: record the twelfth upstream batch #27/Prime Agent active turns cannot survive a Pylon server restart #84 restart truth gate, real A/B isolation tests, and N=1/2/4 resource measurements pass. Require or guide users to a distinct home and separate sign-in/state per instance. Explain ACP degradation on supported runtimes, WSL2 guidance, and the OS-user-global maintenance boundary. Web and desktop inherit the same server gate; mobile remains selection-only and must omit disabled, unavailable, or quarantined instances.

              Acceptance coverage

              • Explicit-home, environment-only home, HOME/default resolution, relative paths, symlink aliases, non-overlap, and reserved environment keys.
              • Two real Prime instances with different homes, accounts, binaries, settings, model catalogs, capacity, sessions, sockets, checkpoints, MCP tokens, and credential sentinels.
              • Worker crash, daemon reconnect/replacement, Pylon restart, settings replacement, one-instance removal, and concurrent stop without cross-account data or cleanup. Prove post-attach proof invalidation and republication across each native reconnect/replacement path.
              • Deferred old status/catalog/capacity/usage/maintenance/rate-limit results and queued adapter events released after replacement never overwrite the new generation or clear the new MCP session.
              • Legacy/missing config revisions start cold; secret changes rotate correlation without hashing, logging, or exposing secret-derived values.
              • Hung graceful shutdown, hung post-kill exit, every fixed observable cleanup outcome, unsupported/contradictory capability proof, and fallback remain bounded and truthful.
              • Native ownership receipt precedes create; abrupt crash leaves it dirty; the next boot launches zero overlapping instances; concurrent attempts never cross-clear; corrupt receipts fail closed; ACP writes no native receipt.
              • ACP degradation stays explicit and verified on supported runtimes. Native Windows Prime execution/fallback is deferred; WSL2 uses the Linux runtime.
              • Measure N=1/2/4 process, memory, file-descriptor/handle, socket, and startup costs; document supported limits.
              • Cover web, desktop-hosted server, mobile selection, local, remote/relay, tunnel, multi-client, macOS, Linux, and WSL2. Verify at least one non-Prime provider remains unchanged. Windows clients may connect to WSL2; native Windows Prime execution is not a current gate.

              Scope and non-goals

              Use one PR per ordered concern. Shared Prime homes are not safe v1 and may be considered later only as an explicit opt-in. Do not mutate global process.env; persist or expose secret-derived fingerprints; treat generic shutdown/PID/socket state as owned cleanup proof; add a broad stop --all path; broaden the same-OS-user threat model; add hostile-co-tenant isolation; touch Prime #20; or include Comet.

              Coordinate with #114 and prime-agent#33.

              Metadata

              Metadata

              Assignees

              No one assigned

                Labels

                Type

                No type

                Projects

                No projects

                  Milestone

                  No milestone

                  Relationships

                  None yet

                  Development

                  No branches or pull requests

                  Issue actions

                  , 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
                  Skip to content

                  Make multiple Prime provider instances safe and truthful #199

                  Description

                  @rynfar

                  Problem

                  Pylon's generic instance UI already allows more than one Prime provider even though the driver reports supportsMultipleInstances: false; that metadata is not enforced or sent to clients. Most Prime control paths are instance-scoped, but native daemon multi-instance operation is not yet safe:

                  • recovered owned workers can receive ambient server credentials/environment instead of the owning instance's environment;
                  • home identity differs between daemon spawn and auth/model/capacity reads;
                  • blank/default or symlink-aliased homes can accidentally share account, settings, extensions, skills, harness state, logs, updates, and maintenance behavior;
                  • same-ID provider replacement can accept stale status, model, capacity, maintenance, rate-limit, or usage results from the prior account/configuration;
                  • forced teardown has an unbounded post-kill wait and owned-session completion is not observable;
                  • OS-user-global Prime maintenance and stop --all behavior can affect all local Prime daemons.

                  Treat multi-Prime as reachable today, not as a future toggle.

                  Required invariant

                  One enabled Prime instance has one immutable server-owned runtime context: { instanceId, generation, configRevision, effectiveHome, exactLaunchEnv, backendKind }. Every launch, attach, recovery, probe, catalog/model read, auth/capacity read, cache receipt, event subscription, mutation, and cleanup must consume or verify that same context. Never recompute home or environment later from raw PrimeAgentSettings. Runtime generation and config revision are correlation fences only; they never identify an account or enter public events, provider snapshots, logs, or telemetry.

                  Dependencies

                  Blocked on prime-agent#33, which owns the public SDK caller-owned recovery-environment and observable-cleanup capability. Native multi-instance mode must require all three current proofs before Pylon admits a native runtime: frozen SDK metadata containing both negotiated_daemon_session_capabilities_v1 and caller_owned_session_environment_cleanup_v1, the server's negotiated offer, and getOwnedSessionContractProof() from the successful current owned attach. Missing, stale, invalidated, or contradictory proof selects ACP. Never infer support from a version, package provenance, method presence, or an earlier attachment.

                  Final native enablement is also blocked on prime-agent#27 and #84 for the Pylon-restart case. A replacement Pylon process has no prior owner connection and cannot treat generic daemon shutdown, socket closure, or supervisor PID exit as proof that every old owned worker settled. The final gate requires exact adoption followed by owner-scoped cleanup, or a separate public aggregate cleanup receipt with equivalent authority. PRs 1–3 below may land before that gate; PR 4 may not advertise native multi-instance support until the restart case is proved.

                  Ordered implementation

                  1. Effective identity and capability gate. Merge the host snapshot and ordered instance overrides once; remove reserved Prime-internal/RLM keys; resolve explicit agent home, environment agent home, or the default against the merged effective OS home; canonicalize through the nearest existing ancestor; then stamp the canonical home into the exact launch environment. Apply that context to daemon, ACP, status, catalog, model, capacity, attach, recovery, and cleanup. Preflight every enabled instance before process launch and reject every participant in an equal/ancestor/symlink-aliased home overlap group. Pass exact ownedSessionLaunchEnv, require the full native proof, and add defensive MCP provider-instance assertions. Keep supportsMultipleInstances: false.
                  2. Provider-generation fencing. Give every materialization/config revision an opaque in-process generation. Every subscription, refresh, capacity run, overlay, maintenance action, runtime event, MCP cleanup, and cache write captures { instanceId, driver, generation } and rechecks it at commit. On replacement, synchronously clear old account/backend/volatile state. Use a server-owned random configRevision for private disk-cache correlation and rotate it for every material config/environment/secret change. Legacy, missing, invalid, or unproved revisions are cold misses. Never hash materialized environment or secret values, and never add a new key subsystem only to warm this cache.
                  3. Bounded teardown and durable quarantine. Bound graceful shutdown, force-kill, post-kill exit, socket cleanup, and scope close. Use single-flight disposeOwnedSession() and preserve its fixed completed, already-completed, owner-mismatch, uncertain-timeout, transport-failure, unsupported, and valid replacement-settled outcomes. Cleanup is proved only by an outcome tied to this connection's current or prior successful owned-attach proof and opaque session identity. Close only the instance-private daemon as final containment. Write a private atomic active-ownership receipt before every native client-owned create, scoped per session attempt and canonical home; remove only that attempt after the same live owner proves completion or proves ownership was never acquired. A crash, timeout, owner mismatch, transport loss, invalid result, or corrupt/unknown receipt leaves it dirty. Reload receipts before provider materialization and block every equal/ancestor/descendant home until docs: record the twelfth upstream batch #27/Prime Agent active turns cannot survive a Pylon server restart #84 identity-safe adoption and cleanup, or explicit documented remediation, clears them. Never ask an arbitrary replacement client to claim historical ownership.
                  4. Truthful support and UX. Propagate and enforce supportsMultipleInstances in server validation, Settings, and the Add dialog. Flip Prime to true only after PRs 1–3, feat(prime): remove sole queued inputs #33, the docs: record the twelfth upstream batch #27/Prime Agent active turns cannot survive a Pylon server restart #84 restart truth gate, real A/B isolation tests, and N=1/2/4 resource measurements pass. Require or guide users to a distinct home and separate sign-in/state per instance. Explain ACP degradation on supported runtimes, WSL2 guidance, and the OS-user-global maintenance boundary. Web and desktop inherit the same server gate; mobile remains selection-only and must omit disabled, unavailable, or quarantined instances.

                  Acceptance coverage

                  • Explicit-home, environment-only home, HOME/default resolution, relative paths, symlink aliases, non-overlap, and reserved environment keys.
                  • Two real Prime instances with different homes, accounts, binaries, settings, model catalogs, capacity, sessions, sockets, checkpoints, MCP tokens, and credential sentinels.
                  • Worker crash, daemon reconnect/replacement, Pylon restart, settings replacement, one-instance removal, and concurrent stop without cross-account data or cleanup. Prove post-attach proof invalidation and republication across each native reconnect/replacement path.
                  • Deferred old status/catalog/capacity/usage/maintenance/rate-limit results and queued adapter events released after replacement never overwrite the new generation or clear the new MCP session.
                  • Legacy/missing config revisions start cold; secret changes rotate correlation without hashing, logging, or exposing secret-derived values.
                  • Hung graceful shutdown, hung post-kill exit, every fixed observable cleanup outcome, unsupported/contradictory capability proof, and fallback remain bounded and truthful.
                  • Native ownership receipt precedes create; abrupt crash leaves it dirty; the next boot launches zero overlapping instances; concurrent attempts never cross-clear; corrupt receipts fail closed; ACP writes no native receipt.
                  • ACP degradation stays explicit and verified on supported runtimes. Native Windows Prime execution/fallback is deferred; WSL2 uses the Linux runtime.
                  • Measure N=1/2/4 process, memory, file-descriptor/handle, socket, and startup costs; document supported limits.
                  • Cover web, desktop-hosted server, mobile selection, local, remote/relay, tunnel, multi-client, macOS, Linux, and WSL2. Verify at least one non-Prime provider remains unchanged. Windows clients may connect to WSL2; native Windows Prime execution is not a current gate.

                  Scope and non-goals

                  Use one PR per ordered concern. Shared Prime homes are not safe v1 and may be considered later only as an explicit opt-in. Do not mutate global process.env; persist or expose secret-derived fingerprints; treat generic shutdown/PID/socket state as owned cleanup proof; add a broad stop --all path; broaden the same-OS-user threat model; add hostile-co-tenant isolation; touch Prime #20; or include Comet.

                  Coordinate with #114 and prime-agent#33.

                  Metadata

                  Metadata

                  Assignees

                  No one assigned

                    Labels

                    Type

                    No type

                    Projects

                    No projects

                      Milestone

                      No milestone

                      Relationships

                      None yet

                      Development

                      No branches or pull requests

                      Issue actions

                      , 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
                      Skip to content

                      Make multiple Prime provider instances safe and truthful #199

                      Description

                      @rynfar

                      Problem

                      Pylon's generic instance UI already allows more than one Prime provider even though the driver reports supportsMultipleInstances: false; that metadata is not enforced or sent to clients. Most Prime control paths are instance-scoped, but native daemon multi-instance operation is not yet safe:

                      • recovered owned workers can receive ambient server credentials/environment instead of the owning instance's environment;
                      • home identity differs between daemon spawn and auth/model/capacity reads;
                      • blank/default or symlink-aliased homes can accidentally share account, settings, extensions, skills, harness state, logs, updates, and maintenance behavior;
                      • same-ID provider replacement can accept stale status, model, capacity, maintenance, rate-limit, or usage results from the prior account/configuration;
                      • forced teardown has an unbounded post-kill wait and owned-session completion is not observable;
                      • OS-user-global Prime maintenance and stop --all behavior can affect all local Prime daemons.

                      Treat multi-Prime as reachable today, not as a future toggle.

                      Required invariant

                      One enabled Prime instance has one immutable server-owned runtime context: { instanceId, generation, configRevision, effectiveHome, exactLaunchEnv, backendKind }. Every launch, attach, recovery, probe, catalog/model read, auth/capacity read, cache receipt, event subscription, mutation, and cleanup must consume or verify that same context. Never recompute home or environment later from raw PrimeAgentSettings. Runtime generation and config revision are correlation fences only; they never identify an account or enter public events, provider snapshots, logs, or telemetry.

                      Dependencies

                      Blocked on prime-agent#33, which owns the public SDK caller-owned recovery-environment and observable-cleanup capability. Native multi-instance mode must require all three current proofs before Pylon admits a native runtime: frozen SDK metadata containing both negotiated_daemon_session_capabilities_v1 and caller_owned_session_environment_cleanup_v1, the server's negotiated offer, and getOwnedSessionContractProof() from the successful current owned attach. Missing, stale, invalidated, or contradictory proof selects ACP. Never infer support from a version, package provenance, method presence, or an earlier attachment.

                      Final native enablement is also blocked on prime-agent#27 and #84 for the Pylon-restart case. A replacement Pylon process has no prior owner connection and cannot treat generic daemon shutdown, socket closure, or supervisor PID exit as proof that every old owned worker settled. The final gate requires exact adoption followed by owner-scoped cleanup, or a separate public aggregate cleanup receipt with equivalent authority. PRs 1–3 below may land before that gate; PR 4 may not advertise native multi-instance support until the restart case is proved.

                      Ordered implementation

                      1. Effective identity and capability gate. Merge the host snapshot and ordered instance overrides once; remove reserved Prime-internal/RLM keys; resolve explicit agent home, environment agent home, or the default against the merged effective OS home; canonicalize through the nearest existing ancestor; then stamp the canonical home into the exact launch environment. Apply that context to daemon, ACP, status, catalog, model, capacity, attach, recovery, and cleanup. Preflight every enabled instance before process launch and reject every participant in an equal/ancestor/symlink-aliased home overlap group. Pass exact ownedSessionLaunchEnv, require the full native proof, and add defensive MCP provider-instance assertions. Keep supportsMultipleInstances: false.
                      2. Provider-generation fencing. Give every materialization/config revision an opaque in-process generation. Every subscription, refresh, capacity run, overlay, maintenance action, runtime event, MCP cleanup, and cache write captures { instanceId, driver, generation } and rechecks it at commit. On replacement, synchronously clear old account/backend/volatile state. Use a server-owned random configRevision for private disk-cache correlation and rotate it for every material config/environment/secret change. Legacy, missing, invalid, or unproved revisions are cold misses. Never hash materialized environment or secret values, and never add a new key subsystem only to warm this cache.
                      3. Bounded teardown and durable quarantine. Bound graceful shutdown, force-kill, post-kill exit, socket cleanup, and scope close. Use single-flight disposeOwnedSession() and preserve its fixed completed, already-completed, owner-mismatch, uncertain-timeout, transport-failure, unsupported, and valid replacement-settled outcomes. Cleanup is proved only by an outcome tied to this connection's current or prior successful owned-attach proof and opaque session identity. Close only the instance-private daemon as final containment. Write a private atomic active-ownership receipt before every native client-owned create, scoped per session attempt and canonical home; remove only that attempt after the same live owner proves completion or proves ownership was never acquired. A crash, timeout, owner mismatch, transport loss, invalid result, or corrupt/unknown receipt leaves it dirty. Reload receipts before provider materialization and block every equal/ancestor/descendant home until docs: record the twelfth upstream batch #27/Prime Agent active turns cannot survive a Pylon server restart #84 identity-safe adoption and cleanup, or explicit documented remediation, clears them. Never ask an arbitrary replacement client to claim historical ownership.
                      4. Truthful support and UX. Propagate and enforce supportsMultipleInstances in server validation, Settings, and the Add dialog. Flip Prime to true only after PRs 1–3, feat(prime): remove sole queued inputs #33, the docs: record the twelfth upstream batch #27/Prime Agent active turns cannot survive a Pylon server restart #84 restart truth gate, real A/B isolation tests, and N=1/2/4 resource measurements pass. Require or guide users to a distinct home and separate sign-in/state per instance. Explain ACP degradation on supported runtimes, WSL2 guidance, and the OS-user-global maintenance boundary. Web and desktop inherit the same server gate; mobile remains selection-only and must omit disabled, unavailable, or quarantined instances.

                      Acceptance coverage

                      • Explicit-home, environment-only home, HOME/default resolution, relative paths, symlink aliases, non-overlap, and reserved environment keys.
                      • Two real Prime instances with different homes, accounts, binaries, settings, model catalogs, capacity, sessions, sockets, checkpoints, MCP tokens, and credential sentinels.
                      • Worker crash, daemon reconnect/replacement, Pylon restart, settings replacement, one-instance removal, and concurrent stop without cross-account data or cleanup. Prove post-attach proof invalidation and republication across each native reconnect/replacement path.
                      • Deferred old status/catalog/capacity/usage/maintenance/rate-limit results and queued adapter events released after replacement never overwrite the new generation or clear the new MCP session.
                      • Legacy/missing config revisions start cold; secret changes rotate correlation without hashing, logging, or exposing secret-derived values.
                      • Hung graceful shutdown, hung post-kill exit, every fixed observable cleanup outcome, unsupported/contradictory capability proof, and fallback remain bounded and truthful.
                      • Native ownership receipt precedes create; abrupt crash leaves it dirty; the next boot launches zero overlapping instances; concurrent attempts never cross-clear; corrupt receipts fail closed; ACP writes no native receipt.
                      • ACP degradation stays explicit and verified on supported runtimes. Native Windows Prime execution/fallback is deferred; WSL2 uses the Linux runtime.
                      • Measure N=1/2/4 process, memory, file-descriptor/handle, socket, and startup costs; document supported limits.
                      • Cover web, desktop-hosted server, mobile selection, local, remote/relay, tunnel, multi-client, macOS, Linux, and WSL2. Verify at least one non-Prime provider remains unchanged. Windows clients may connect to WSL2; native Windows Prime execution is not a current gate.

                      Scope and non-goals

                      Use one PR per ordered concern. Shared Prime homes are not safe v1 and may be considered later only as an explicit opt-in. Do not mutate global process.env; persist or expose secret-derived fingerprints; treat generic shutdown/PID/socket state as owned cleanup proof; add a broad stop --all path; broaden the same-OS-user threat model; add hostile-co-tenant isolation; touch Prime #20; or include Comet.

                      Coordinate with #114 and prime-agent#33.

                      Metadata

                      Metadata

                      Assignees

                      No one assigned

                        Labels

                        Type

                        No type

                        Projects

                        No projects

                          Milestone

                          No milestone

                          Relationships

                          None yet

                          Development

                          No branches or pull requests

                          Issue actions

                          , 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
                          Skip to content

                          Make multiple Prime provider instances safe and truthful #199

                          Description

                          @rynfar

                          Problem

                          Pylon's generic instance UI already allows more than one Prime provider even though the driver reports supportsMultipleInstances: false; that metadata is not enforced or sent to clients. Most Prime control paths are instance-scoped, but native daemon multi-instance operation is not yet safe:

                          • recovered owned workers can receive ambient server credentials/environment instead of the owning instance's environment;
                          • home identity differs between daemon spawn and auth/model/capacity reads;
                          • blank/default or symlink-aliased homes can accidentally share account, settings, extensions, skills, harness state, logs, updates, and maintenance behavior;
                          • same-ID provider replacement can accept stale status, model, capacity, maintenance, rate-limit, or usage results from the prior account/configuration;
                          • forced teardown has an unbounded post-kill wait and owned-session completion is not observable;
                          • OS-user-global Prime maintenance and stop --all behavior can affect all local Prime daemons.

                          Treat multi-Prime as reachable today, not as a future toggle.

                          Required invariant

                          One enabled Prime instance has one immutable server-owned runtime context: { instanceId, generation, configRevision, effectiveHome, exactLaunchEnv, backendKind }. Every launch, attach, recovery, probe, catalog/model read, auth/capacity read, cache receipt, event subscription, mutation, and cleanup must consume or verify that same context. Never recompute home or environment later from raw PrimeAgentSettings. Runtime generation and config revision are correlation fences only; they never identify an account or enter public events, provider snapshots, logs, or telemetry.

                          Dependencies

                          Blocked on prime-agent#33, which owns the public SDK caller-owned recovery-environment and observable-cleanup capability. Native multi-instance mode must require all three current proofs before Pylon admits a native runtime: frozen SDK metadata containing both negotiated_daemon_session_capabilities_v1 and caller_owned_session_environment_cleanup_v1, the server's negotiated offer, and getOwnedSessionContractProof() from the successful current owned attach. Missing, stale, invalidated, or contradictory proof selects ACP. Never infer support from a version, package provenance, method presence, or an earlier attachment.

                          Final native enablement is also blocked on prime-agent#27 and #84 for the Pylon-restart case. A replacement Pylon process has no prior owner connection and cannot treat generic daemon shutdown, socket closure, or supervisor PID exit as proof that every old owned worker settled. The final gate requires exact adoption followed by owner-scoped cleanup, or a separate public aggregate cleanup receipt with equivalent authority. PRs 1–3 below may land before that gate; PR 4 may not advertise native multi-instance support until the restart case is proved.

                          Ordered implementation

                          1. Effective identity and capability gate. Merge the host snapshot and ordered instance overrides once; remove reserved Prime-internal/RLM keys; resolve explicit agent home, environment agent home, or the default against the merged effective OS home; canonicalize through the nearest existing ancestor; then stamp the canonical home into the exact launch environment. Apply that context to daemon, ACP, status, catalog, model, capacity, attach, recovery, and cleanup. Preflight every enabled instance before process launch and reject every participant in an equal/ancestor/symlink-aliased home overlap group. Pass exact ownedSessionLaunchEnv, require the full native proof, and add defensive MCP provider-instance assertions. Keep supportsMultipleInstances: false.
                          2. Provider-generation fencing. Give every materialization/config revision an opaque in-process generation. Every subscription, refresh, capacity run, overlay, maintenance action, runtime event, MCP cleanup, and cache write captures { instanceId, driver, generation } and rechecks it at commit. On replacement, synchronously clear old account/backend/volatile state. Use a server-owned random configRevision for private disk-cache correlation and rotate it for every material config/environment/secret change. Legacy, missing, invalid, or unproved revisions are cold misses. Never hash materialized environment or secret values, and never add a new key subsystem only to warm this cache.
                          3. Bounded teardown and durable quarantine. Bound graceful shutdown, force-kill, post-kill exit, socket cleanup, and scope close. Use single-flight disposeOwnedSession() and preserve its fixed completed, already-completed, owner-mismatch, uncertain-timeout, transport-failure, unsupported, and valid replacement-settled outcomes. Cleanup is proved only by an outcome tied to this connection's current or prior successful owned-attach proof and opaque session identity. Close only the instance-private daemon as final containment. Write a private atomic active-ownership receipt before every native client-owned create, scoped per session attempt and canonical home; remove only that attempt after the same live owner proves completion or proves ownership was never acquired. A crash, timeout, owner mismatch, transport loss, invalid result, or corrupt/unknown receipt leaves it dirty. Reload receipts before provider materialization and block every equal/ancestor/descendant home until docs: record the twelfth upstream batch #27/Prime Agent active turns cannot survive a Pylon server restart #84 identity-safe adoption and cleanup, or explicit documented remediation, clears them. Never ask an arbitrary replacement client to claim historical ownership.
                          4. Truthful support and UX. Propagate and enforce supportsMultipleInstances in server validation, Settings, and the Add dialog. Flip Prime to true only after PRs 1–3, feat(prime): remove sole queued inputs #33, the docs: record the twelfth upstream batch #27/Prime Agent active turns cannot survive a Pylon server restart #84 restart truth gate, real A/B isolation tests, and N=1/2/4 resource measurements pass. Require or guide users to a distinct home and separate sign-in/state per instance. Explain ACP degradation on supported runtimes, WSL2 guidance, and the OS-user-global maintenance boundary. Web and desktop inherit the same server gate; mobile remains selection-only and must omit disabled, unavailable, or quarantined instances.

                          Acceptance coverage

                          • Explicit-home, environment-only home, HOME/default resolution, relative paths, symlink aliases, non-overlap, and reserved environment keys.
                          • Two real Prime instances with different homes, accounts, binaries, settings, model catalogs, capacity, sessions, sockets, checkpoints, MCP tokens, and credential sentinels.
                          • Worker crash, daemon reconnect/replacement, Pylon restart, settings replacement, one-instance removal, and concurrent stop without cross-account data or cleanup. Prove post-attach proof invalidation and republication across each native reconnect/replacement path.
                          • Deferred old status/catalog/capacity/usage/maintenance/rate-limit results and queued adapter events released after replacement never overwrite the new generation or clear the new MCP session.
                          • Legacy/missing config revisions start cold; secret changes rotate correlation without hashing, logging, or exposing secret-derived values.
                          • Hung graceful shutdown, hung post-kill exit, every fixed observable cleanup outcome, unsupported/contradictory capability proof, and fallback remain bounded and truthful.
                          • Native ownership receipt precedes create; abrupt crash leaves it dirty; the next boot launches zero overlapping instances; concurrent attempts never cross-clear; corrupt receipts fail closed; ACP writes no native receipt.
                          • ACP degradation stays explicit and verified on supported runtimes. Native Windows Prime execution/fallback is deferred; WSL2 uses the Linux runtime.
                          • Measure N=1/2/4 process, memory, file-descriptor/handle, socket, and startup costs; document supported limits.
                          • Cover web, desktop-hosted server, mobile selection, local, remote/relay, tunnel, multi-client, macOS, Linux, and WSL2. Verify at least one non-Prime provider remains unchanged. Windows clients may connect to WSL2; native Windows Prime execution is not a current gate.

                          Scope and non-goals

                          Use one PR per ordered concern. Shared Prime homes are not safe v1 and may be considered later only as an explicit opt-in. Do not mutate global process.env; persist or expose secret-derived fingerprints; treat generic shutdown/PID/socket state as owned cleanup proof; add a broad stop --all path; broaden the same-OS-user threat model; add hostile-co-tenant isolation; touch Prime #20; or include Comet.

                          Coordinate with #114 and prime-agent#33.

                          Metadata

                          Metadata

                          Assignees

                          No one assigned

                            Labels

                            Type

                            No type

                            Projects

                            No projects

                              Milestone

                              No milestone

                              Relationships

                              None yet

                              Development

                              No branches or pull requests

                              Issue actions

                              , 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
                              Skip to content

                              Make multiple Prime provider instances safe and truthful #199

                              Description

                              @rynfar

                              Problem

                              Pylon's generic instance UI already allows more than one Prime provider even though the driver reports supportsMultipleInstances: false; that metadata is not enforced or sent to clients. Most Prime control paths are instance-scoped, but native daemon multi-instance operation is not yet safe:

                              • recovered owned workers can receive ambient server credentials/environment instead of the owning instance's environment;
                              • home identity differs between daemon spawn and auth/model/capacity reads;
                              • blank/default or symlink-aliased homes can accidentally share account, settings, extensions, skills, harness state, logs, updates, and maintenance behavior;
                              • same-ID provider replacement can accept stale status, model, capacity, maintenance, rate-limit, or usage results from the prior account/configuration;
                              • forced teardown has an unbounded post-kill wait and owned-session completion is not observable;
                              • OS-user-global Prime maintenance and stop --all behavior can affect all local Prime daemons.

                              Treat multi-Prime as reachable today, not as a future toggle.

                              Required invariant

                              One enabled Prime instance has one immutable server-owned runtime context: { instanceId, generation, configRevision, effectiveHome, exactLaunchEnv, backendKind }. Every launch, attach, recovery, probe, catalog/model read, auth/capacity read, cache receipt, event subscription, mutation, and cleanup must consume or verify that same context. Never recompute home or environment later from raw PrimeAgentSettings. Runtime generation and config revision are correlation fences only; they never identify an account or enter public events, provider snapshots, logs, or telemetry.

                              Dependencies

                              Blocked on prime-agent#33, which owns the public SDK caller-owned recovery-environment and observable-cleanup capability. Native multi-instance mode must require all three current proofs before Pylon admits a native runtime: frozen SDK metadata containing both negotiated_daemon_session_capabilities_v1 and caller_owned_session_environment_cleanup_v1, the server's negotiated offer, and getOwnedSessionContractProof() from the successful current owned attach. Missing, stale, invalidated, or contradictory proof selects ACP. Never infer support from a version, package provenance, method presence, or an earlier attachment.

                              Final native enablement is also blocked on prime-agent#27 and #84 for the Pylon-restart case. A replacement Pylon process has no prior owner connection and cannot treat generic daemon shutdown, socket closure, or supervisor PID exit as proof that every old owned worker settled. The final gate requires exact adoption followed by owner-scoped cleanup, or a separate public aggregate cleanup receipt with equivalent authority. PRs 1–3 below may land before that gate; PR 4 may not advertise native multi-instance support until the restart case is proved.

                              Ordered implementation

                              1. Effective identity and capability gate. Merge the host snapshot and ordered instance overrides once; remove reserved Prime-internal/RLM keys; resolve explicit agent home, environment agent home, or the default against the merged effective OS home; canonicalize through the nearest existing ancestor; then stamp the canonical home into the exact launch environment. Apply that context to daemon, ACP, status, catalog, model, capacity, attach, recovery, and cleanup. Preflight every enabled instance before process launch and reject every participant in an equal/ancestor/symlink-aliased home overlap group. Pass exact ownedSessionLaunchEnv, require the full native proof, and add defensive MCP provider-instance assertions. Keep supportsMultipleInstances: false.
                              2. Provider-generation fencing. Give every materialization/config revision an opaque in-process generation. Every subscription, refresh, capacity run, overlay, maintenance action, runtime event, MCP cleanup, and cache write captures { instanceId, driver, generation } and rechecks it at commit. On replacement, synchronously clear old account/backend/volatile state. Use a server-owned random configRevision for private disk-cache correlation and rotate it for every material config/environment/secret change. Legacy, missing, invalid, or unproved revisions are cold misses. Never hash materialized environment or secret values, and never add a new key subsystem only to warm this cache.
                              3. Bounded teardown and durable quarantine. Bound graceful shutdown, force-kill, post-kill exit, socket cleanup, and scope close. Use single-flight disposeOwnedSession() and preserve its fixed completed, already-completed, owner-mismatch, uncertain-timeout, transport-failure, unsupported, and valid replacement-settled outcomes. Cleanup is proved only by an outcome tied to this connection's current or prior successful owned-attach proof and opaque session identity. Close only the instance-private daemon as final containment. Write a private atomic active-ownership receipt before every native client-owned create, scoped per session attempt and canonical home; remove only that attempt after the same live owner proves completion or proves ownership was never acquired. A crash, timeout, owner mismatch, transport loss, invalid result, or corrupt/unknown receipt leaves it dirty. Reload receipts before provider materialization and block every equal/ancestor/descendant home until docs: record the twelfth upstream batch #27/Prime Agent active turns cannot survive a Pylon server restart #84 identity-safe adoption and cleanup, or explicit documented remediation, clears them. Never ask an arbitrary replacement client to claim historical ownership.
                              4. Truthful support and UX. Propagate and enforce supportsMultipleInstances in server validation, Settings, and the Add dialog. Flip Prime to true only after PRs 1–3, feat(prime): remove sole queued inputs #33, the docs: record the twelfth upstream batch #27/Prime Agent active turns cannot survive a Pylon server restart #84 restart truth gate, real A/B isolation tests, and N=1/2/4 resource measurements pass. Require or guide users to a distinct home and separate sign-in/state per instance. Explain ACP degradation on supported runtimes, WSL2 guidance, and the OS-user-global maintenance boundary. Web and desktop inherit the same server gate; mobile remains selection-only and must omit disabled, unavailable, or quarantined instances.

                              Acceptance coverage

                              • Explicit-home, environment-only home, HOME/default resolution, relative paths, symlink aliases, non-overlap, and reserved environment keys.
                              • Two real Prime instances with different homes, accounts, binaries, settings, model catalogs, capacity, sessions, sockets, checkpoints, MCP tokens, and credential sentinels.
                              • Worker crash, daemon reconnect/replacement, Pylon restart, settings replacement, one-instance removal, and concurrent stop without cross-account data or cleanup. Prove post-attach proof invalidation and republication across each native reconnect/replacement path.
                              • Deferred old status/catalog/capacity/usage/maintenance/rate-limit results and queued adapter events released after replacement never overwrite the new generation or clear the new MCP session.
                              • Legacy/missing config revisions start cold; secret changes rotate correlation without hashing, logging, or exposing secret-derived values.
                              • Hung graceful shutdown, hung post-kill exit, every fixed observable cleanup outcome, unsupported/contradictory capability proof, and fallback remain bounded and truthful.
                              • Native ownership receipt precedes create; abrupt crash leaves it dirty; the next boot launches zero overlapping instances; concurrent attempts never cross-clear; corrupt receipts fail closed; ACP writes no native receipt.
                              • ACP degradation stays explicit and verified on supported runtimes. Native Windows Prime execution/fallback is deferred; WSL2 uses the Linux runtime.
                              • Measure N=1/2/4 process, memory, file-descriptor/handle, socket, and startup costs; document supported limits.
                              • Cover web, desktop-hosted server, mobile selection, local, remote/relay, tunnel, multi-client, macOS, Linux, and WSL2. Verify at least one non-Prime provider remains unchanged. Windows clients may connect to WSL2; native Windows Prime execution is not a current gate.

                              Scope and non-goals

                              Use one PR per ordered concern. Shared Prime homes are not safe v1 and may be considered later only as an explicit opt-in. Do not mutate global process.env; persist or expose secret-derived fingerprints; treat generic shutdown/PID/socket state as owned cleanup proof; add a broad stop --all path; broaden the same-OS-user threat model; add hostile-co-tenant isolation; touch Prime #20; or include Comet.

                              Coordinate with #114 and prime-agent#33.

                              Metadata

                              Metadata

                              Assignees

                              No one assigned

                                Labels

                                Type

                                No type

                                Projects

                                No projects

                                  Milestone

                                  No milestone

                                  Relationships

                                  None yet

                                  Development

                                  No branches or pull requests

                                  Issue actions