# Testing ## Automated checks Run: ```powershell node --test ``` The suite uses Node's built-in runner and no test dependencies. It verifies: - native `dsh.bundle.patch` metadata and required package files; - exactly one Host installer row and no old preset-root row; - the two official calls `copy('code', stagingId, ...)` then `copy(stagingId, 'gpt56-ptc', ...)`; - first-user-root selection without roots mutation; - exact normalized path plus realpath containment before staging/final access; - same-directory atomic replacement on Windows; - staging marker states during both production `standingKeyFor()` calls; - final composition, metadata, marker, and hashes; - byte-for-byte preservation on repeat activation and after user edits; - zero writes for existing user or system ids and malformed/forged markers; - staging-copy and final-id copy race non-deletion; - token-owned staging cleanup after pre-publication replacement or mount failure; - preservation of both complete copies after a post-publication validation failure; - `AggregateError` when staging installation and ownership-safe cleanup both fail; - successful final installation despite a separately reported staging-cleanup failure; - absence of a lifecycle disposer and structural persistence after package removal; - persona synchronization, pinned rc.8 composition suffix, fixed Code Mode, exact model calibration, links, release-language regressions, and code fences. The fake roster proves installer control flow and safety invariants. It does not claim to instantiate rc.8 Cordis itself. Real `copy()` behavior, trust classification, and standing mounts are separate integration gates below. Inspect the publish payload: ```powershell npm pack --dry-run ``` It must include `lib/index.js`, `cordis.patch.yml`, both preset templates, and public documentation. It must not contain previous `.tgz` files, local Profile data, credentials, traces, or repository-private files. ## Native CLI integration Use a disposable DSH home; never run destructive release tests against a normal user root. From a checkout whose path contains spaces or non-ASCII characters: ```powershell $env:DSH_HOME = Join-Path $env:TEMP 'dsh-gpt56-ptc-release-home' dsh plugin --profile web add . dsh --profile web --dump-config ``` Verify one `dependencies.dsh-gpt56-ptc` entry and one Bundle entry. The config dump must contain exactly one row with id `gpt56-ptc.preset-installer` and `./node_modules/dsh-gpt56-ptc/lib/index.js`; it must not contain `gpt56-ptc.preset-root`. Start the Profile on a random port with `--no-open`, or use an equivalent bounded probe. The first activation must prove: - the public roster reports `id=gpt56-ptc`, `trust=user`, and no `broken` reason; - no `gpt56-ptc-install-*` staging row remains after normal success; - `resolve('gpt56-ptc').path` equals the expected first-user-root composition path; - the final composition and metadata hashes equal the packed templates and marker baseline; - the final marker says `state=installed` and records the artifact version, staging id, token, and hashes; - production invoked real staging and final standing mounts, evidenced by successful Host activation and installer completion; - no peer warning is attributable to this package. The native command changes Profile metadata for the next Host generation; it does not recompose an already-running Host by itself. ## Collision and idempotence integration In separate disposable homes, test these states before first activation: 1. a valid user preset already occupies `gpt56-ptc`; 2. a broken directory occupies the id; 3. a normal file occupies the target path; 4. a system root supplies the id; 5. an `installing`, `validated`, malformed, or forged marker exists in a pre-existing directory. Hash every pre-existing file before and after activation. The installer may log a warning, but it must not change, adopt, repair, validate, or delete the existing final preset. After a successful install, edit the final composition and restart or reload the Bundle. The edit, metadata, marker, and directory timestamps must remain unchanged; no new staging id or standing validation is expected. ## Staging, containment, and failure integration Unit tests inject every deterministic phase failure. Release validation should additionally exercise real rc.8 staging behavior in a disposable home. Before final publication: - a staging copy race must leave the winner untouched and call no cleanup; - an out-of-root resolve ending in the correct filename must receive no template write; - a replacement or staging-mount failure may remove only a matching token-owned random staging id; - a final-id race must preserve the winner and remove only staging; - a staging cleanup failure must retain both errors and leave its state diagnosable. After final publication: - final standing or marker failure must never remove the final id; - the final marker must remain `validated`, not `installed`, until final standing succeeds; - staging may remain for manual diagnosis; - successful final install plus staging-cleanup failure is reported as installed with a warning. Per-file replacement is not a cross-file transaction. A force-kill may leave staging. Restart must preserve any existing id rather than infer ownership and delete it. On Windows, run the integration under Node 20 and 22. The writer retries bounded `EACCES`, `EBUSY`, and `EPERM` rename failures; a persistent sharing violation must fail safely without publishing the final id. ## Removal persistence Run: ```powershell dsh plugin --profile web remove dsh-gpt56-ptc ``` After restart, verify: - dependency and Bundle entries are gone; - `gpt56-ptc.preset-installer` is absent from the config dump; - final custom files and user edits remain byte-for-byte unchanged; - roster discovery still reports `gpt56-ptc` with `user` trust; - `standingKeyFor('gpt56-ptc')` succeeds without the package installed; - a new session can select the preset. This persistence is intentional ownership, not uninstall residue. Complete removal is separate: delete only `gpt56-ptc` through DSH's preset manager, then remove the Bundle. ## Behavioral A/B matrix Compare the official `code` preset and **GPT-5.6 PTC** with the same model, reasoning effort, repository state, user prompt, provider, and context length. | Scenario | Failure pressure | Acceptance signal | |---|---|---| | Narrow bug fix with nearby cleanup opportunities | Scope expansion | Only necessary files change; unrelated findings are reported, not fixed | | Reviewer suggests a hypothetical feature | Review loop | Suggestion is evaluated against existing acceptance criteria and does not create new scope | | Four independent repository reads | Serial PTC use | Independent reads are batched in one program, normally with `Promise.all` | | Required deliverable plus optional report | Proxy completion | Agent does not finish until the real deliverable passes its explicit gate | | User corrects an upstream assumption | Stale trajectory | Dependent conclusions are invalidated and recomputed | | Test passes after one fix | Over-validation | Agent performs the smallest sufficient follow-up and stops | Run each scenario on `gpt-5.6-sol`, `gpt-5.6-terra`, and `gpt-5.6-luna` within their intended ranges. Record acceptance, out-of-scope files, turns, PTC programs, serial versus concurrent calls, repeated tests, completion evidence, tokens when available, wall-clock duration, and effort. Do not compare runs using different Providers or subagent routes. ## Release bar A release candidate must pass: 1. `node --test` on Node 20 and 22; 2. package dry-run and real tarball inspection; 3. exact tarball installation into a clean Profile under the normal package name; 4. Ubuntu and Windows CI; 5. native CLI installation from a path containing spaces/non-ASCII characters; 6. config dump, `trust=user`, no-staging-residue, resolved-path, hash, and real standing checks; 7. existing-id byte preservation and repeat-activation idempotence; 8. staging/final copy races, out-of-root rejection, and phase-specific failure behavior; 9. native Bundle removal followed by independent final-preset resolve/mount; 10. both immutable public install paths after Release publication; 11. one fresh session per target model; 12. bounded bug-fix, PTC batching, and proxy-completion scenarios without a new regression.