15 KiB
Migrated
Migrated from TODO.md entry without a legacy ticket file. No legacy review file was present at migration time.
Plan
Implementation will proceed through a child orchestrator Pod in a dedicated worktree as an experiment in nested Pod delegation.
Initial implementation target:
- Introduce Nix profile resolution as a new manifest source before the existing manifest cascade.
- Start with explicit path-based profiles; discovered-name/default selection and rich TUI picker can be staged after the core resolver if necessary.
- Provide a minimal bundled Nix helper that can produce a typed resolved manifest/config artifact.
- Keep existing TOML manifest loading as compatibility/debug/test infrastructure.
- Persist enough profile identity and resolved snapshot data for future restore semantics; do not silently re-evaluate profiles on resume.
- Secret values must remain references only; plaintext secrets are out of scope for the profile resolver.
The child orchestrator may split implementation among sub-Pods, but final merge/close remains parent-side.
Review: approve
Reviewed the nested Pod implementation from branch work/nix-manifest-profiles.
Result: approved after blocking fix.
Findings:
- Initial review found one blocking issue:
--profilerejected non-emptyINSOMNIA_USER_MANIFEST. That contradicted the profile design because a selected Nix profile is a standalone runtime config artifact and ambient user/project manifest cascade should not affect it. - The child orchestrator fixed this in commit
c9a175a fix: ignore user manifest for profilesand addedprofile_ignores_non_empty_user_manifest_envwithout invoking real Nix. - Profile foundation is intentionally a vertical slice: explicit path-based Nix profile resolution, minimal Nix helper, CLI/TUI spawn entrypoints, resolved snapshot metadata, and restore-from-snapshot behavior. Rich discovery/default picker remains future work.
Validation run by reviewer:
cargo fmt --checkcargo test -p manifest profile -- --nocapturecargo test -p pod --bin insomnia-pod profile -- --nocapturecargo check -p session-store -p manifest -p pod -p client -p tui -p providercargo check -p pod -p tuigit diff --check- Manual
nix eval --json --filesmoke check forresources/nix/profile-lib.nix
Non-blocking follow-up candidates:
- Hide or narrow
ResolvedProfile::raw_artifactif future call sites might log/persist accidental raw Nix output. - Add a timeout around
nix evalso profile startup cannot hang indefinitely. - Validate direct
client::SpawnConfigconstruction that combinesprofile_pathwithresume_from; TUI currently avoids it. - Build richer profile discovery/default selection and the full TUI profile picker.
Plan
Continue implementation beyond the merged Nix profile foundation. The previous nested delegation stopped at a reviewable vertical slice; this phase should keep iterating until the work item acceptance criteria are materially closer to completion or a real blocker is found.
Phase 2 target:
- Add profile discovery/default selection instead of requiring only explicit
--profile <path>. - Support discovered-name selection with source disambiguation where needed, e.g. builtin/user/project/path semantics.
- Add or substantially advance the new Pod profile selection UX so a default can be displayed as
profile: coder (default)and changed before spawn. - Preserve the core design: selected Nix profile resolves to a standalone manifest/config artifact; ambient user/project manifests do not merge into it.
- Keep Pod resume using resolved snapshots rather than silent Nix re-evaluation.
- Keep secrets as references only.
The delegated orchestrator should not return merely because one slice is reviewable. It should internally review acceptance criteria, delegate sub-Pods as needed, and continue with the next reachable slice unless it hits a concrete design or technical blocker. Parent-side merge/close remains reserved for this parent Pod.
Review: approve
Reviewed phase 2 implementation from branch work/nix-manifest-profiles-phase2.
Result: approved after two parent-review fixes.
Implemented scope:
- Profile registry/discovery for builtin/user/project sources.
[profiles]metadata in user/project manifests for discovery/default/alias only; it is not merged into the selected runtime manifest.--profileselector parsing for explicit paths,path:<path>, discovered names,default, and source-qualified names such asproject:coder.- Ambiguous unqualified discovered names fail closed.
- TUI fresh-spawn UI now shows a selectable
profile:row, uses discovered choices, marks defaults, and includesmanifest cascadeas opt-out. - SpawnConfig passes selected profiles to
insomnia-pod --profile; resume/attach paths do not re-evaluate profiles. - Docs and focused tests updated.
Parent review findings fixed by child orchestrator:
- Unqualified alias targets initially resolved globally. Fixed so aliases declared in a source resolve unqualified targets within that declaring source by default.
- Defaults pointing at aliases initially did not mark the resolved target entry as default, causing TUI to fall back to
manifest cascade. Fixed by resolving the default throughselect_named()before settingis_defaultflags.
Validation run by parent reviewer:
cargo fmt --checkcargo checkcargo test -p manifest profile -- --nocapturecargo test -p tui spawn -- --nocapturecargo test -p pod profile -- --nocapturecargo test -p client spawn -- --nocapturegit diff --check
All passed. Full cargo test was run by the child orchestrator and failed only in the unrelated existing/flaky llm-worker parallel timing test class.
Remaining polish/follow-up candidates, not blockers for this work item:
- A richer popup-style profile picker instead of inline cycling.
- Actual bundled builtin profile files once default builtin semantics are decided.
nix evaltimeout/robustness follow-up.- Encrypted secret store integration remains tracked by the related encrypted-secrets work item.
Closed
id: 20260527-000022-manifest-profiles slug: manifest-profiles title: Nix profile entrypoints that resolve to portable Pod manifests status: closed kind: feature priority: P2 labels: [manifest, profiles, nix, tui] created_at: 2026-05-27T00:00:22Z updated_at: 2026-05-29T17:45:59Z assignee: null legacy_ticket: null
Migration reference
- legacy_ticket: null
- migrated_from: TODO.md / tickets directory migration on 2026-05-27
Nix profile entrypoints that resolve to portable Pod manifests
Background
This work item was migrated from an unfinished TODO.md entry:
事前定義したManifestをProfile的に扱い、Orchestrator/Coder/Researcherで別々のモデル/設定を使わせる運用ができるようにする
The current manifest cascade is good at configuration defaults by location: built-in defaults, user manifest, workspace manifest, and explicit overlays. That is less suitable for operational role selection. Users want to choose between profiles such as Orchestrator, Coder, Researcher, Reviewer, or cheap/fast variants, and they want those profiles to be portable as a pure artifact rather than assembled implicitly from several ambient layers.
Another problem is authoring ergonomics. The current manifest exposes many low-level numeric parameters that require implementation-specific intuition, such as compaction thresholds, pruning protection sizes, memory thresholds, and feature-specific token limits. Profiles should let users express high-level intent and reusable presets while the resolver produces the precise runtime manifest.
Related work
work-items/open/20260529-145355-manifest-profile-encrypted-secrets/item.md: profiles should integrate with explicit encrypted secret references so API keys/tokens are not limited to process environment variables.
Design direction
Use Nix as the default human-authored profile format. A profile is a Nix expression that produces the final Pod manifest/configuration artifact through an Insomnia-provided mkProfile / mkManifest style library.
The profile itself is the source of truth. Commonality, imports, role presets, and any cascade-like behavior should be expressed in Nix by the profile author instead of being implemented as an additional ambient manifest cascade in Insomnia.
The runtime boundary should be:
selected Nix profile + explicit startup inputs
=> deterministic resolved manifest/config snapshot
=> Pod runtime
Do not introduce a three-layer authoring model where Nix generates TOML profiles that then merge into TOML manifests. That would make manifest/profile/Nix ownership unclear and hard to operate. Rust should consume the resolved artifact, ideally as a typed JSON/config representation, and preserve a snapshot for Pod restore.
Requirements
- Add a Nix-based profile entrypoint as the default path for new Pod creation.
- Provide an Insomnia Nix library with
mkProfile/mkManifesthelpers. - The helper should produce a pure resolved manifest/config artifact that Rust can deserialize and validate.
- Profile authors may use Nix imports/functions to share common settings, implement their own cascade, or build role presets.
- Provide an Insomnia Nix library with
- Treat the resolved manifest/config as the runtime contract.
- Persist the selected profile identity/source and the resolved snapshot in Pod/session metadata.
- Pod resume should prefer the saved resolved snapshot, not silently re-evaluate the Nix profile.
- Re-evaluating a profile for an existing Pod must be explicit because it may change model, tools, permissions, or thresholds.
- Move role-oriented authoring into profiles.
- Support profiles for roles such as Orchestrator, Coder, Researcher, Reviewer, and cost/performance variants.
- Profiles should be able to select model/provider settings, prompts, tools, permissions, memory behavior, web/search behavior, workflows, skills, and context/compaction strategy.
- Prefer semantic presets in the Nix library for values that are difficult to tune by raw numbers, e.g. context budget, compaction behavior, retention, autonomy, and tool policy.
- Keep raw low-level numeric overrides available as an advanced escape hatch, not the primary user-facing interface.
- Shrink ambient cascade to discovery/default selection rather than runtime config merging.
- User/project configuration may provide profile registries, aliases, defaults, and UI preferences.
- User/project configuration should not be required as intermediate runtime override layers for model IDs, compaction thresholds, or other behavior controlled by the selected profile.
- Existing TOML manifest cascade can remain as compatibility/debug/test infrastructure, but it should not be the main profile design.
- Add profile discovery and selection UX.
- New Pod creation UI should show a selectable profile field such as
profile: coder (default). - The profile picker should list built-in/user/project/explicit profiles with enough source/default information to avoid ambiguity.
- CLI/TUI should support explicit profile selection by name/source and by path/flakeref where appropriate.
- Ambiguous profile names should fail closed or require source-qualified selection rather than being implicitly merged.
- New Pod creation UI should show a selectable profile field such as
- Keep secrets as references, not plaintext values.
- Nix profiles may refer to credentials using typed secret references, e.g.
secrets.ref "brave.search.default". - Nix evaluation output, resolved config serialization, diagnostics, session logs, and model context must not contain plaintext secrets.
- Secret dereferencing/decryption happens in Rust at the consumer boundary.
- Nix profiles may refer to credentials using typed secret references, e.g.
- Define compatibility and fallback behavior.
--manifest/ TOML manifest loading may continue to work for compatibility, tests, fixtures, and low-level debugging.- If Nix is unavailable, diagnostics should clearly say that profile resolution requires Nix and point to the manifest/resolved-config fallback path.
- Existing manifest behavior should not be broken until the Nix profile path is implemented and documented.
Open design points
- Exact Nix entrypoint shape:
- flake output names, e.g.
insomniaProfiles.<name>/profiles.<name> - path-based profiles, e.g.
.insomnia/profiles/coder/profile.nix - whether both are supported initially
- flake output names, e.g.
- Exact Rust-facing artifact:
- JSON resolved config vs TOML manifest snapshot vs a new typed
ResolvedPodConfig - whether
PodManifestremains the final runtime type or becomes the legacy/compatibility representation
- JSON resolved config vs TOML manifest snapshot vs a new typed
- Profile registry/default storage:
- where user-level profile aliases live
- where project-level defaults live
- how built-in profiles are exposed
- How much Nix support is external-command based initially vs embedded/library-integrated later.
- How profile summaries are generated for the new Pod UI without exposing low-level internals or secrets.
Acceptance criteria
- A Nix profile can be selected when creating a new Pod and resolves to the complete runtime manifest/config for that Pod.
- Insomnia provides a documented
mkProfile/mkManifestNix helper for producing a valid resolved profile artifact. - Profile authors can share common settings and implement cascade-like composition in Nix without relying on ambient user/project manifest merging.
- New Pod UI includes profile selection and displays the effective default, e.g.
profile: coder (default). - CLI/TUI profile selection supports at least one explicit path/flakeref flow and one discovered-name/default flow.
- Resolved profile artifacts are validated with clear diagnostics before Pod creation.
- Pod/session metadata persists the selected profile identity/source and the resolved snapshot.
- Pod resume uses the persisted resolved snapshot unless the user explicitly asks to reload/re-resolve the profile.
- Secret references are preserved as references through Nix evaluation and resolved config; plaintext secrets are not written to config snapshots, logs, diagnostics, or model context.
- Existing TOML manifest path remains available as a compatibility/debug/test path during the migration.
- Documentation explains the new profile model, why ambient cascade is no longer the primary runtime config mechanism, and how users should structure reusable Nix profiles.
- Focused tests cover Nix profile resolution, validation errors, profile default/source selection, ambiguity handling, snapshot persistence, and no-plaintext secret serialization paths.
cargo fmt --check- Relevant manifest/profile/pod/tui tests pass.