Skip to content

feat(ai): local chat and reference embeddings through managed Pumas inference - #29

Draft
MrScripty wants to merge 9 commits into
mainfrom
codex/pumas-local-inference
Draft

MrScripty wants to merge 9 commits into
mainfrom
codex/pumas-local-inference

Conversation

@MrScripty

@MrScripty MrScripty commented Oct 10, 2026 •

Copy link
Copy Markdown
Owner

Local chat and reference embeddings now use independently selected Pumas models/runtime profiles through Pumas's serving lifecycle and typed model-operation v1, pinned to ad31e391dcd94c204b3fcd748cc98d27b3281e65 (0.8.0-rc.1). Explicit Load/Unload controls and capability/error checks preserve existing direct llama.cpp and OpenRouter providers.

Reference indexing publishes complete documents only after successful embeddings, binds exact source/session/provider/model/profile/provenance/load revision and dimensions, reindexes saved references on project reopen or embedding-selection changes, and exposes ready/stale/failed status plus explicit Reindex. Generation reports consumed reference sources or retrieval errors; Last Generation Prompt shows the retrieved text included in the actual generation request. Optional Linux selected-root Pumas bootstrap drains only an owned service, observes its child-exit receipt before desktop exit, and survives cancellation during admitted startup. Borrowed services remain running. Explicit startup failures preserve Pumas selection and display the actual error.

Follow-up review repairs: unload decodes the pinned producer's typed UnserveModelResponse, rejects success:true/error:Some/unloaded:false, preserves error-free unloaded:false as already unserved, and rejects missing receipts. Retrieval checks the captured scope while holding the index guard before any compatibility/status mutation. Exact regressions first reproduced the old failures, then proved a fresh newer-revision/dimension index remains ready and usable after late queries across Reindex and same-path reopen.

Validation on repair head b09f9c2: 123 core + 611 server tests and all-target/all-feature core/server clippy passed locally; frontend lint/format/typecheck and 606 tests passed; formatting and decision traceability passed. Exact-head CI run 96 is fully green: Linux and Windows workspace clippy/tests, frontend lint/format/typecheck/tests, ONNX no-download guard, authoring regressions and decision traceability. Linux passed 977 Rust tests; Windows passed 975. Both platforms retain two existing ignored native-display renderer tests.

Controlled producer/process fixtures cover load/embed/unload, failures, revision/model changes, source upload/reopen/retrieval-to-chat prompt, typed streaming/cancellation, and owned versus borrowed cleanup. Full local desktop build was blocked by missing GTK/WebKit development libraries; the pre-push desktop hook failed at glib-2.0 and was excluded for push after the listed checks passed. The repair head subsequently passed full native workspace checks in CI.

No real-model inference was executed because no embedding/chat weights are available in this environment; fixture outputs are test data only, never production fallbacks. Native-display acceptance remains unexecuted. Pumas typed v1 supplies no immutable weight revision in each response, so identity is session/provenance-bound and out-of-band weight mutation without metadata/reload remains a producer limitation.

Operator setup and real-model acceptance: docs/pumas-local-inference.md. Pumas producer unchanged. Keep draft; do not merge without coordinating with the parent task.

Integration and review update — 2026-10-14

Current head: 1148fb0e44efc25420e1b71494eef6d7cae99840. This merge commit preserves original PR head b09f9c28 and main 59793c19 as parents, including PR30's native UI fixes. Pumas deliberately remains ad31e391 (0.8.0-rc.1): main's older setup pin lacks the discovery and typed-operation APIs this consumer uses.

Independent GPT-6.1 Sol High review found a genuine mismatch: the pinned producer omits optional loaded_at, while Eidetic required it. The old fixture invented a timestamp. A producer-shaped regression first failed, then passed after identity was bound to the producer's monotonic serving cursor, instance/service generations and actual metadata. Pre/post inference checks remain enforced. Same-model reloads with unchanged metadata and changes during embedding reject old vectors; unrelated serving mutations conservatively require Reindex.

Exact-head local checks pass: 123 core + 615 server tests and all example targets; 16 targeted Pumas fixture tests; strict all-target/all-feature core/server Clippy; frontend lint/format/typecheck and 608 tests; ONNX no-download and authoring regressions; formatting and decision traceability. Independent review reports no remaining confirmed P1/P2 in the reviewed Pumas/reference paths. Exact-head CI run 100 completed successfully: Linux and Windows full-workspace Clippy/tests, frontend, ONNX no-download safeguards, authoring regressions and decision traceability all pass. Linux passed 983 Rust tests and Windows passed 981, with two existing native-display tests ignored on each platform. GitHub's PR merge tree matches the pushed head's tree. The local canonical workspace command remains blocked at missing glib/GTK/WebKit; its pre-push test hook was excluded after the listed checks, retaining hosted native CI.

Keep draft for parent review. Trained-model acceptance remains unexecuted: no local weights are present, and ordinary public artifact access receives proxy CONNECT 403; no bypass or credentials were used. Fixtures are synthetic test data only. The separate dependency audit also fails on the existing frontend stack (14 high / 3 critical, manifests and lockfile unchanged from main); local Rust audit tools are absent. Source CI and PR30's native UI captures do not satisfy those gates.

The committed readiness report records evidence and the deferred borrowed-bootstrap robustness observation. Minimal operator step: supply accessible local trained chat and embedding packages to the pinned Pumas runtime, load both, and run the real-model acceptance procedure. No release or merge has been performed.

Dependency audit repair — current head be03aa1

Current head: be03aa1f2b7e6e19da632fac3b2b7eb89ec12c73, preserving 1148fb0e. The exact-lockfile audit report maps all 14 high / 3 critical baseline package rows to 19 unique upstream advisories, actual shipped/runtime-capable versus build/lint/test consumers, affected ranges and repairs. The earlier inference from npm fixAvailable: false to no upstream fix is corrected.

Targeted compatible patches include Vite 6.4.4 and the affected devalue/PostCSS/nanoid/source-map/YAML/brace chains. Vitest and coverage move together to 4.1.11, removing unpatched Tinypool 1.x through its supported parent rather than forcing a transitive major. Kit 2.70.3 also repairs a verified reachable development-page Accept-header path; humanfs 0.16.8 and selector-parser 7.1.6 close the related ESLint/PostCSS lower-severity chains. No unrelated direct Svelte/ESLint/Tailwind/TypeScript/Rust family update, overrides or audit-force command is used.

Final local audit: zero moderate/high/critical; three low rows are one cookie 0.6 advisory propagated through Kit and adapter-static. Kit 2's current supported range still requires cookie 0.6; the report records absent application cookie-metadata input/Node production server, owner, reassessment triggers, and the parent decision to schedule a separately reviewed Kit 3 migration or supported backport. This is a specific existing low finding, not a blanket acceptance or reduced gate.

Fresh npm ci, npm ls, dependency script, lint/format/typecheck, all 107 files / 608 frontend tests and static build pass. A bounded synthetic Buffer regression reproduces devalue 5.8.1 serializing a 64-byte backing store for a two-byte view; patched 5.9.4 preserves only the selected two bytes. A five-test V8-coverage smoke passes. No tests, assertions or discovery filters were weakened. Independent GPT-6.1 Sol High review approved this exact commit with no confirmed P1/P2. Exact-head CI run 101 completed successfully: frontend audit/lint/format/typecheck, all 608 tests and static build; decision traceability; Linux/Windows full-workspace Clippy and tests; ONNX no-download safeguards. Linux passed 983 Rust tests and Windows passed 981, retaining two existing native-display tests ignored on each. Hosted audit confirms only the three low rows for the single cookie advisory. The CI merge tree matches the pushed candidate.

PR29 remains draft and unmerged for parent review. Trained-model inference remains unexecuted and gated; no model-access bypass, credentials or release action occurred. Local native testing remains environment-blocked at glib/GTK/WebKit, and optional local Rust audit tools remain absent as explicitly reported.

@coderabbitai

coderabbitai Bot commented Oct 10, 2026 •

Copy link
Copy Markdown

Important

Draft PR not reviewed

Draft PRs are not automatically reviewed by default.

  • Trigger a manual review

To automatically review draft PRs, update your CodeRabbit configuration:

reviews:
  auto_review:
    drafts: true
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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.

Jeremy and others added 3 commits October 14, 2026 20:37
Retain authoring and Pumas documentation contracts, preserve the exact inference producer pin, and record fresh source validation separately from outstanding trained-model/native acceptance.

Copy link
Copy Markdown
Owner Author

Disposition: retain this PR as draft; do not close its unique Pumas chat/embedding, reference-index and lifecycle work. The dependency-security repair is already retained on main via the authoring integration.

Integration commit b4af7e9 normally merges main 6bef187 into be03aa1, preserving both histories and the ad31e391 producer pin. Six documentation conflicts retain both contracts; source merges mechanically. Independent GPT-6.1 Sol High review found no new confirmed P1/P2 and separately checked consumed discovery/DTO/typed operation/SSE/metadata/cursor contracts against the exact producer. The updated readiness report preserves the original evidence.

Fresh local composed-tree validation passes: 129 core + 638 server tests and all example targets; strict all-target/all-feature core/server Clippy; Rust formatting and decision traceability; five ONNX guard unit tests and seven authoring fixture regressions; pinned Node npm ci/lint/format/typecheck, all 115 files / 646 frontend tests and static build. Dependency checks pass with three low cookie-related rows; cargo-audit/deny/machete remain explicit missing-tool skips. GTK/glib/WebKit development packages are absent locally. Exact-head CI run 110 is queued; hosted results will be recorded separately.

Blocking merge: actual trained chat + embedding and native lifecycle acceptance is still unexecuted. An operator with accessible local model packages must run the acceptance procedure, recording real generation/structured output, indexed reference contribution in the consumed prompt, reopen/reindex, same-model reload invalidation, visible failures, and owned/borrowed cleanup; then the owner must disposition that runtime gate. Synthetic fixtures, generic CI and earlier native authoring captures do not establish it. No model/credential acquisition or denied-access retry was attempted. The documented lower-priority borrowed-bootstrap timeout observer issue remains deferred.

Copy link
Copy Markdown
Owner Author

Additional acceptance findings from independent review against current Coding-Standards 0fc92a24: mechanical source integration b4af7e9 is approved, but this does not establish complete product acceptance or standards compliance.

Lifecycle ownership remains incomplete in pumas_runtime.rs: the admitted startup task at line 45 has no retained completion/panic observer after caller cancellation and can discard a start error; the stdout drain at line 118 discards its handle and I/O result; Drop cleanup at line 207 detaches its fallback completion. The known borrowed-bootstrap timeout at lines 121–128 also drops its child observer. Rust async ownership and concurrency ownership require an actual terminal/error/shutdown owner. The inference lifecycle owner must repair these paths or record an explicit owned, justified exception before final acceptance. No lifecycle feature lane was opened during cleanup.

The synchronous shutdown wait in src-tauri/src/lib.rs:86 deliberately retains the drain receipt before exit. Its callback/exit execution contract and accepted design rationale still need to be established. This is a design/acceptance concern; the reviewer did not demonstrate deadlock or an async-worker-thread violation, and block_on is not categorically forbidden in all synchronous callbacks.

These findings reinforce retaining the unique PR as draft. They do not invalidate the mechanical integration or authorize discarding its work. Required real-model/native evidence remains separately blocked, as recorded above.

Copy link
Copy Markdown
Owner Author

Fresh exact-head CI run 110 is now fully successful for b4af7e9: Linux/Windows full-workspace Clippy and tests, frontend audit/lint/format/typecheck/tests/static build, ONNX no-download safeguards, authoring regressions and decision traceability all pass. The admitted GitHub merge-test tree matched the reviewed head tree exactly.

Source integration is validated. Disposition remains retain draft / blocked for product acceptance, for the real-model/native operator procedure and the lifecycle ownership/design findings recorded above. No generic CI result is being used as trained-model or native interaction acceptance. README-only PR33 has been separately reviewed and normally merged as 728a7d6; no PR29 product work was merged or discarded.

Retain child/output results through explicit shutdown and reap the spawned borrowed helper on timeout without touching its service. Keep cancelled-construction and last-Drop observation gated on the documented composition-owner decision.

Copy link
Copy Markdown
Owner Author

Published partial lifecycle repair 338890f3bc4c61bf5908b6616a32121a41ecf8b3, a normal child of b4af7e9 with no history rewrite. Independent GPT-6.1 Sol High review approved the exact five-file tree 8550c4f8 narrowly.

The existing runtime owner now retains child + stdout completion, reports stdout I/O errors/panics as sticky shutdown failures, and retains the handle across a cancelled shutdown waiter. A timed-out borrowed bootstrap has only our spawned helper killed/reaped; no service shutdown/unload RPC is sent. The new regression first failed on b4af7e9 with timed-out borrowed bootstrap helper lost its exit observer; the deliberate hung fixture was cleaned up. After repair, helper disappearance, empty RPC log and continued borrowed-service connectivity are asserted.

Local checks pass: six targeted lifecycle tests; 129 core + 642 server tests and all example targets; strict all-target/all-feature core/server Clippy; formatting/traceability; configured pre-commit lint/format/typecheck and commit-message checks. Canonical ./launcher.sh --test still stops at missing glib-2.0 development metadata; original output is preserved. No test or threshold was weakened. Exact-head CI run 112 is in progress and retains hosted native-workspace checks.

Remaining material decision, not silently implemented: an owner must be retained by the application composition root before subprocess admission and explicitly drained after cancelled initialization/last-Drop cleanup requests. Current cancellable attach/AppState::new plus synchronous Drop cannot themselves supply an external terminal observer. Startup success/error/panic and fallback completion—including exceptional helper termination/stdout timeout failures—are therefore NOT fully closed. The lifecycle report specifies the bounded next design and alternatives requiring parent disposition. No global owner, alternate runtime, cleanup thread or public API change was introduced.

The synchronous Tauri shutdown contract was source-reviewed at locked 2.11.2; no demonstrated deadlock or native execution acceptance is claimed. Required native exit qualification and actual trained chat/embedding acceptance remain open; no models/credentials or denied-access retries were acquired. Keep draft.

MrScripty commented Oct 22, 2026 •

Copy link
Copy Markdown
Owner Author

Reviewed composition-owner proposal (no API implementation)

Source baseline: 338890f3bc4c61bf5908b6616a32121a41ecf8b3. Independent GPT-6.1 Sol High review approved the exact proposal SHA256 808ed86484916e502fc378ef75a89fe57a94c1b3288acb2fd51079fc337c7766, including the focused admission, acknowledgement-authority, worker-death wakeup and exit-code corrections. This is a proposed implementation direction awaiting the explicit API decision. No breaking source change was made.

CI112 / run 39710649846, source head338890f3: attempt1 is terminal failure. Linux Rust1016 passed, Windows Rust1010 passed; two native-display tests ignored on each. Traceability passed. Frontend npm audit --audit-level=high failed with a five-minute network timeout at https://registry.npmjs.org/-/npm/v1/security/advisories/bulk, exit1; later frontend checks were skipped. Original failure log retained. The single failed-only retry (attempt2, frontend job119606393184) is now terminal failure: the same registry bulk endpoint returned HTTP503 Service Unavailable, exit1, at2026-10-22T02:50:13Z. Lint/format/typecheck/tests/static build were again skipped. The run is completed/failure at exact source head338890f3, attempt2, updated02:50:17Z. Both original frontend logs are retained; no further retry or threshold/configuration change was made. Rust and traceability successes carry forward; two native-display tests remain ignored per platform. Missing local glib metadata, actual native lifecycle execution and actual trained-model acceptance remain separate gates. This does not certify native/model acceptance.

Full reviewed proposal

PR29 retained composition owner: implementation proposal

Status: proposed, awaiting the construction/API decision; no implementation is
admitted by this document. Source baseline:
338890f3bc4c61bf5908b6616a32121a41ecf8b3 (2026-10-22).
This is the bounded follow-up to the lifecycle report,
not a replacement architecture or a claim of product acceptance.

Decision requested

Preserve the existing cancelled-startup and eventual-cleanup guarantees by
giving Pumas work an owner that exists before construction and survives its
caller. Require that owner at the public AppState construction boundary and
migrate the known callers together. Do not retain an ownerless owned-bootstrap
implementation behind a deprecated wrapper.

The proposed API changes below require an explicit decision before source
implementation. Requiring a handle is a source break; keeping the old signature
but refusing owned startup would instead be a behavior break. An additive
constructor alone cannot preserve all existing semantics and fix the old path.

Small ownership boundary

Add a Pumas-specific PumasLifecycleOwner in crates/server, constructed
synchronously by the composition root with its existing Tokio runtime handle.
It is unique and non-Clone. A cloneable PumasLifecycleHandle provides admission
and cleanup requests, but is not a substitute for retaining/draining the owner.
Neither AppState nor a Tauri managed-state entry owns the root owner. Keep the
existing generic backend supervisor and Pumas producer/protocol unchanged.

The owner holds one admitted Pumas session for the one AppState at each current
root. Reject a second admission and admission after closing with a recorded,
visible startup error; no queue or replacement-service behavior is introduced.
Admission is synchronous and closed atomically against exit. Hold the same
synchronous admission lock across entry registration, control-task spawn and
JoinHandle installation. Root close/drain takes this lock before closing and
inspecting entries, so it cannot observe a half-installed admission even when
a multithreaded runtime immediately polls the new task. Register the resource
record before spawn; only admitted work may execute Command::spawn. If exit
wins admission, no subprocess can be created. All work uses the injected
existing runtime. Handle failed spawn without leaving an unobservable entry.

Each owner entry retains (a) the control-task JoinHandle and its terminal result,
(b) a separate shared session resource record, and (c) sticky startup/output/
cleanup outcomes. The control task may hold the resource record, not the owner
registry containing its own JoinHandle: no self-retaining ownership cycle.
Immediately after successful child creation, put the child in that record
before any await. No child or completion handle is moved into a cancellable
caller or removed from custody across an await. Install and retain the stdout
reader task before awaiting acknowledgement; it owns the single reader, parses
the acknowledgement, then drains output. Observe both its acknowledgement and
its final I/O/JoinError outcome, including panic before acknowledgement.

The stdout reader stores validated bootstrap ownership, service description and
generation/endpoint fence in the shared record before sending acknowledgement
or continuing on worker-local state. A panic between parsing and handoff must
not lose root recovery's authority. Retain its terminal output outcome separately
from the acknowledgement channel. The existing owned/borrowed classification
and generation/endpoint checks stay authoritative. Before a valid acknowledgement
the spawned PID is the bootstrap helper; failed startup terminates/reaps that
exact helper. After a borrowed
acknowledgement, never unload, shut down or signal the external service. After
an owned acknowledgement, use the existing owned-service shutdown protocol;
do not broaden authority to a replacement generation or kill an owned service
merely because its drain budget expired.

Cancellation, panic and terminal custody

The control task remains admitted through startup, facade lifetime and cleanup.
Cancelling the construction reply waiter requests release; it does not cancel
the admitted work. A successful acknowledgement after cancellation therefore
enters cleanup instead of publishing an unreachable facade. Startup failure,
control-task panic/cancellation, stdout failure/panic and cleanup failure remain
distinguishable records even when no AppState was returned.

Last facade Drop only signals the already admitted task, synchronously. It
never spawns a fallback. Explicit shutdown also requests release and waits for
the session receipt or worker-death notification. Constructor, facade and
shutdown waiters must wake on worker death without first invoking root drain:
use request/reply channel closure or a synchronous task-drop notification whose
producer is not retained by the owner. This reports a nonterminal worker failure,
not cleanup completion. Root still retains and joins the actual JoinHandle to
record its error/panic and drain resources. Smoke/examples can therefore leave
a failed shutdown wait and reach root drain. A cancelled shutdown waiter leaves
all resources/results
with the owner. If the control task panics, root drain observes its JoinError
and continues cleanup using the separately retained child/output record. It
must not wait forever for a reply from the dead worker. Catching an unwind or
logging a failure alone is not terminal observation.

Use one retained session state machine: admitted -> starting -> attached or
startup-failed -> draining -> terminal. Release and admission closure are
monotonic. Only terminal means child exit/reaping and all spawned task/output
outcomes have been observed. Retain the aggregate receipt for repeat observers;
a later success cannot erase an earlier error. No observer-count metric or
diagnostic log can substitute for this receipt.

Expose close_admission(&self) and a cancellation-safe
drain_to_terminal(&mut self) -> Result<PumasDrainReport, PumasDrainError> on the
owner. The root is the terminal observer. Returning Err is permitted only after
cessation; it carries observed failures, not abandoned live resources. Existing
timeout budgets produce an explicit incomplete diagnostic while retaining
custody, not a terminal receipt. With no authority to kill the owned service,
the root remains in its exit drain and waits for actual cessation. There is no
automatic retry campaign or normal process exit on incomplete cleanup. An
operator-forced termination is outside the graceful-completion claim and must
not be labeled success. This may leave the process visibly exiting until the
service stops; that is an explicit consequence of preserving the guarantee.

If drain itself is cancelled, another call on the same retained owner resumes
observation. Dropping the owner/runtime without terminal drain is a caller
protocol violation, not an async Drop guarantee. Document this requirement;
do not add a global owner, cleanup runtime/thread or unowned panic fallback.

Exact caller migration

AppState::new currently starts document/autosave tasks before its asynchronous
model-library/Pumas initialization. Move those existing spawns after the last
asynchronous initialization and immediately before returning Self, with no
intervening await. This removes the pre-Self cancellation window for those
tasks without redesigning their supervisor. Pumas admission uses the supplied
handle; retain current visible startup-error/AiConfig behavior and defaults.

Desktop (src-tauri/src/lib.rs, run, constructor currently line 38):

  1. Create the root owner from tauri::async_runtime::handle().inner().clone()
    before constructing AppState. Construct AppState outside Builder::setup;
    retain an original state at the root and move a clone into setup. It does
    not need an AppHandle to initialize. Retain the owner even if construction
    never returns Self.
  2. Build the existing Tauri application and use locked Tauri 2.11.2 desktop
    App::run_return, rather than Builder::run, so the root has a final phase.
    Stop current bridge/render owners at their existing boundary; on application
    exit close Pumas admission. Remove backend block_on drain from the synchronous
    Destroyed callback. Final Pumas observation occurs outside GUI callbacks.
  3. After event-loop return, close admission, stop/join existing backend tasks,
    request Pumas release and await owner terminal drain on the still-live
    injected runtime. The private helper returns the intended event-loop exit
    code and terminal lifecycle outcome only after drain. Keep run() -> ():
    its wrapper preserves a nonzero event-loop code using process::exit only
    after drain; a lifecycle failure with code zero produces a nonzero exit.
    Returning normally after logging failure is insufficient.
  4. Retain the root across initialization/build/setup/event-loop errors and
    unwind handling; all these paths perform the same final drain before
    returning an error or resuming unwind. Catching unwind supplements custody.
    No result-dependent ? or process::exit may bypass that final phase.

Tauri's Builder::run/App::run do not provide a post-return cleanup phase.
run_return supports the current desktop targets, but restart/request_restart
can bypass its return and iOS falls back to run. Current repository code has
no restart, AppHandle::exit or runtime override calls. This plan covers current
graceful desktop routes; adding a restart/direct-exit/mobile route requires
placing it behind the same drain, not relying on the post-loop path. Forced
process termination and runtime destruction cannot promise async completion.
The existing synchronous callback inspection establishes no demonstrated
deadlock; native qualification of the changed exit boundary is still required.

Backend smoke (src-tauri/src/desktop_smoke.rs, constructor line 50): create
the owner before the constructor future, retain it outside any fallible/unwind
work, initialize/report/shutdown within the existing runtime, then close and
drain before publishing an ok report or serialization result. A lifecycle
failure must reach main.rs --smoke as a nonzero failure after terminal drain;
update its misleading serialization-only error message. launcher.sh and the
release workflow consume the CLI exit code and need no interface change.
Graph/timeline renderer smoke functions do not construct AppState and keep
their interfaces and evidence claims.

Examples: migrate all five roots in crates/server/examples/:
authoring_capture_fixture.rs:8, bible_fact_capture_fixture.rs:8,
canonical_scene_capture_fixture.rs:11, portfolio_authored_demo.rs:22, and
scene_order_capture_fixture.rs:12. Each creates an owner on its existing Tokio
runtime, retains preparation errors until after shutdown/drain, and never exits
or prints success before the receipt. Preserve owner custody on panic too.
Their fixture output is not model acceptance.

Tests: migrate 44 construction calls in 24 server files and the three calls at
src-tauri/src/graph_renderer_projection.rs:286,301,358, in addition to the
desktop/smoke roots. A small test harness retains/drains a real owner on each
existing runtime, including failure paths. Do not solve lifetime by returning
only AppState from a helper, changing ambient environment globally, or silently
disabling selected-root startup. Total inventory: 54 calls in 32 files. Repeat
the repository-wide constructor search before implementation; unknown external
path-dependency consumers cannot be ruled out by publish = false.

Externally callable signature decisions

Surface at baseline Recommended implementation Compatibility
eidetic_server::state::AppState::new() -> Self (async) new(lifecycle: &PumasLifecycleHandle) -> Self (async) Required argument is a source break; keeps selected-root startup semantics with a sound root.
eidetic_desktop::smoke_report_json() -> Result<String, serde_json::Error> Result<String, DesktopSmokeError>; publicly reexport the error type Error-type source break; can represent lifecycle failure honestly. Success JSON stays unchanged.
AppState::shutdown_tasks_async(&self) -> () (async), shutdown_tasks(&self) -> () Keep signatures. The async method requests/waits session cleanup; synchronous method retains its existing abort-only backend meaning. Owner drain is the authoritative Pumas receipt. No signature break; neither unit return certifies successful Pumas cleanup.
eidetic_desktop::run() -> (); Tauri commands; graph/timeline smoke exports Keep signatures No planned wire/command/frontend/API change.

Add only the owner/handle/receipt/error types and their constructor, handle,
admission-close and drain methods as needed at eidetic_server::pumas_lifecycle.
Keep PumasRuntime/attach private. desktop_smoke::smoke_report can return Result
internally: its module is private and this function is not reexported. Do not
mislabel a lifecycle failure as serde_json::Error.

An additive migration can add new_with_pumas_lifecycle and a checked smoke
function first. It cannot leave old new() launching owned work safely without
a caller-owned root. Refusing owned bootstrap there is source-compatible but
changes behavior; retaining the old detached path retains an unsound promise.
For smoke, a legacy JSON wrapper could encode an explicit non-ok status after
drain, but callers checking only Result/exit status would change semantics or
miss the failure. Neither option is full compatibility. Recommend the two
explicit signature migrations above rather than hiding either difference.

Bounded implementation and evidence gates

  1. After the API decision, add the Pumas owner/session state machine and migrate
    AppState plus every caller in one coherent source slice. Remove detached
    startup/Drop spawns; preserve the ordinary helper/stdout repairs from 338890f.
    Leave producer pin, inference behavior and unrelated owners untouched.
  2. Add deterministic regressions for cancellation before admission (no spawn),
    after admission/before acknowledgement, and after acknowledgement. Observe
    successful, failed and panicking startup from the retained root after the
    construction waiter is gone. Inject child-wait/kill/output failures; verify
    borrowed-helper timeout never touches its service and never loses custody.
  3. Exercise last-facade Drop, explicit shutdown-waiter cancellation, root-drain
    cancellation/resumption, duplicate/closed admission, worker panic before/after
    child registration, and timeout/incomplete state. Require retained handles,
    actual child reaping, sticky terminal receipts, and no completion until
    cessation. These controlled process/I/O tests prove only those boundaries.
  4. Verify desktop setup/build/unwind/normal exit and smoke error exits retain
    the same owner and drain on the active runtime. Independently review source
    and exact resulting head, run required strict checks/CI, then qualify the
    desktop exit path on supported native hardware/display. Do not infer native
    execution or deadlock from source inspection or a mock.
  5. Keep PR29 draft until remaining acceptance is independently dispositioned:
    actual trained chat/embedding and native lifecycle acceptance from the
    existing operator procedure, plus an exact-head green CI run. Missing local
    glib development metadata and missing real models are distinct gates. No
    credentials/models or frozen scientific campaigns are acquired/run here.

This proposal adds no feature lane, generic task framework or public API
implementation. The PR discussion records independent plan review and exact
CI112 results separately; CI is not evidence that this unimplemented owner
already works.

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