# Design ## Objective Provide one native DSH Profile Bundle that installs a genuine user-owned Agent preset optimized for GPT-5.6 Sol, Terra, and Luna while preserving genuine DSH PTC and a stable request prefix throughout a session. The preset controls trajectory, not routing. The user selects a model when creating a session; the preset keeps that model, persona, tool catalog, and presentation mode fixed for the session. ## Plane decision The product has two deliberately separated pieces. The Agent preset owns session-scoped behavior: - persona and exact-model behavioral guidance; - model-facing tool rows; - compaction, planning, delegation, and workflow tools; - fixed Code Mode presentation. The Profile Bundle contributes one narrow Host installer row. It consumes the Host-owned `agentPresets` service to perform a one-time staging-to-publication flow and mount validation. It does not publish a replacement roster or move model routing, credentials, sandbox, approvals, persistence, registries, or provider backends out of their Host owners. The final preset is not package-owned runtime state. Once published into a user root, it is a locally authored snapshot owned by the user. ## Official authoring boundary DSH `0.1.0-rc.8` supports Profile Bundles through `dsh.bundle.patch`, but has no manifest field that imports an external package template directly into the roster. The public creation seam is: ```text agentPresets.copy(from, id, name?) ``` `copy()` refuses every existing id, chooses the first configured `user` root, copies a complete known preset, dereferences symlinks, tightens permissions, and removes its own failed partial copy. It returns no path, so every created id is subsequently resolved through `resolve(id)`. The installer never mutates the documented-readonly `agentPresets.roots` array. It reads the first user root only to prove containment. Its local expansion of `~`, `~/`, and `~\` mirrors rc.8 `expandHomePath`; path normalization mirrors `writableRoot()`. ## Why staging is necessary Creating the fixed final id first and deleting it on a later failure is unsafe. Between asynchronous steps, another actor could remove that directory and replace it. rc.8 `remove(id)` resolves the id again at deletion time, so a blind rollback could delete the replacement. The installer therefore never edits or rolls back the fixed final id. Every fallible edit happens under an unpredictable staging id: ```text gpt56-ptc-install- ``` Only after staging is complete and mount-validated does a second official `copy()` publish the final id. A concurrent final-id winner causes `copy()` to fail without overwriting it. The installer can then remove only its random, token-marked staging preset. ## Installation state machine The first activation follows this sequence: 1. list the roster and stop with zero writes if any root already supplies `gpt56-ptc`; 2. locate the first configured `user` root and read both packaged template files before any authoring write; 3. generate a UUID token and staging id; 4. call `copy('code', stagingId, 'GPT-5.6 PTC installer staging')`; 5. resolve staging and prove all of the following before writing: - exact id; - `trust === 'user'`; - exact normalized path `//agent.cordis.yml`; - a real directory and regular composition file, not links; - realpath containment beneath the real user root; 6. write an `installing` marker containing the token, staging id, package version, and template hashes; 7. replace staging composition and metadata through exclusive same-directory temporary files and rename; 8. re-read both files and verify their SHA-256 hashes; 9. call `standingKeyFor(stagingId)`; only after success change the staging marker to `validated`; 10. call `copy(stagingId, 'gpt56-ptc', 'GPT-5.6 PTC')` to publish a complete tree under the final id; 11. resolve the final id and repeat exact path, real-directory, and hash checks; 12. call `standingKeyFor('gpt56-ptc')`; only after success change the final marker to `installed`; 13. verify the random staging marker still carries this invocation's token, then remove that staging id. A successful final copy is the publication commit point. The final id is never automatically removed after that point, even if final validation or marker replacement reports an error. Both the final and staging trees remain for diagnosis, with the final marker still `validated` rather than falsely `installed`. ## Failure and cleanup authority Before publication: - a template read failure performs no authoring write; - a staging copy rejection performs no cleanup; - a staging resolve/containment failure occurs before the ownership marker and leaves the unpredictable staging id for manual inspection rather than risking deletion; - after the marker exists, cleanup requires an exact staging id and token match; - a final-id copy race preserves the winner and removes only token-owned staging; - cleanup failure produces an `AggregateError` containing both the installation and cleanup errors. After publication: - the final id is never removed automatically; - final validation failure preserves both complete copies; - successful final install plus staging-cleanup failure remains a successful install with a warning and a removable staging residue. No path-based API can provide a perfect compare-and-delete primitive against a malicious same-user process. The unpredictable UUID staging id and token, exact root/path/realpath checks, marker verification, and absence of final-id deletion reduce cleanup authority to the directory created for this invocation. The security boundary does not attempt to defend user files from another process already acting with the same OS account. ## Per-file replacement The local writer creates an exclusive temporary file in the destination directory, renames it over the target, applies owner-only mode, and removes failed temporaries. On Windows it retries brief `EACCES`, `EBUSY`, and `EPERM` rename failures with bounded delays. Replacement is atomic per file, not one transaction across composition, metadata, and marker. Staging plus whole-directory final `copy()` ensures the fixed final id is never exposed as an in-progress edited tree. The DSH atomic-write package is not resolvable from a linked external Bundle under the rc.8 Profile layout without introducing a duplicate runtime dependency, so this narrow implementation uses only Node built-ins and is covered on the Windows and Ubuntu Node 20/22 matrix. ## Existing-id, marker, and update policy Any existing final `gpt56-ptc` is preserved, regardless of trust, contents, or marker: - no adoption; - no overwrite; - no automatic repair; - no deletion; - no package-driven update. A recognized `installed` marker changes logging only. Its hashes record the original template baseline; they are not an integrity proof and a mismatch is expected after legitimate user edits. Marker presence never authorizes a future write or removal. `installing` and `validated` markers on an existing final id are treated as conflicts and preserved. Package updates therefore do not refresh the installed copy. To adopt a newer template, the user explicitly backs up changes, removes that one custom preset through DSH's preset manager, and restarts while the Bundle is installed. ## Template layout `presets/gpt56-ptc/agent.cordis.yml` is a self-contained installation template derived from the official DSH `code` preset in `@deepseek-ai/dsh` `0.1.0-rc.8` with two intentional changes: 1. the scoped `@deepseek-ai/dsh-persona` text is replaced by `src/persona.md`; 2. `preset.yml` receives project-specific display metadata. Every official tool, goal, compaction, plan, delegation, workflow, web, and Code Mode row is retained. `@deepseek-ai/dsh-agent-tool-presentation` remains exactly `mode: code`. The template contains no package-relative plugin path, so the final copy remains mountable after the Bundle package is removed. ## Stable-prefix and prompt contract The project excludes automatic model routing, model changes within a session, Native/PTC switching, `ctx.tools.presentAs()` adaptation, per-turn `ctx.tools.restrict()` trimming, and task-specific prompt rewriting. The persona contains `{{model}}` and `{{cwd}}`, so sessions naturally differ by selected route and workspace. After rendering, the persona and complete Code Mode tool surface remain fixed for that Agent's lifetime. The compact persona emphasizes smallest coherent scope, real acceptance evidence, invalidation after corrections, targeted verification, immediate stopping, ordered writes, concurrent independent PTC reads, and reviewer boundaries. Its communication contract leads with concrete outcomes, prefers everyday words and direct cause-and-effect, explains necessary technical terms on first use, rejects unexplained jargon and empty management language, and still preserves exact file names, commands, API names, and errors when they are actionable. Small exact-name clauses add stronger minimality for Sol, implementation-first bounded slices for Terra, and narrow reconciliation for Luna without routing or SDK mutation. ## Lifecycle - First successful Bundle activation: validates staging, publishes, and validates one final `user` preset. - Repeated activation or hot reload: observes the final id and preserves it byte-for-byte. - User edits: remain user-owned and are never overwritten by the Bundle. - Bundle update: does not refresh the custom preset. - Bundle disposal or uninstall: removes only the Host installer row; it does not remove the preset. - New sessions after uninstall: can still resolve the custom preset. - Existing sessions: retain the composition generation they already joined. - Explicit preset deletion: removes the user snapshot through DSH's preset manager; an installed Bundle can recreate it on the next Host start. ## Safety The preset cannot weaken Host sandbox or approval policy. The Host installer performs no network access, credential access, model call, provider configuration, or arbitrary user-root traversal. Writes are restricted to a random staging directory that has passed exact root/path/realpath checks. The final directory is created only by official whole-directory `copy()` from validated staging. Pre-existing final ids stop before any write, and no uninstall path calls `remove()`. ## Compatibility policy Compatibility is pinned to DSH `0.1.0-rc.8` because the copied Code composition and `list()`, readonly `roots`, `copy()`, `resolve()`, `remove()`, and `standingKeyFor()` contracts are version-sensitive. Validation requires: 1. static, documentation, installer, containment, collision, and failure-injection tests on Node 20 and 22; 2. package-content inspection; 3. installation through the exact native DSH CLI; 4. Profile config dump inspection; 5. clean-home `trust: user`, resolved-path, file-hash, and two-stage standing-mount validation; 6. repeat activation and user-edit preservation; 7. Bundle removal followed by independent preset resolution and mount; 8. representative Sol, Terra, and Luna behavioral tasks. A DSH upgrade that changes any of these contracts requires an explicit compatibility change and full revalidation, not a blind version-range expansion.