projmux 0.15.0 → 0.15.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/docs/agent-message-replies.md +49 -0
- package/docs/agent-workflow.md +166 -9
- package/docs/architecture.md +10 -0
- package/docs/claude-coordination-endpoints.md +15 -0
- package/docs/cli-guide.md +49 -6
- package/docs/cli.md +15 -15
- package/docs/codex-generation-pool.md +5 -0
- package/docs/codex-stored-qualification.md +45 -0
- package/docs/column-profiles.md +14 -9
- package/docs/heterogeneous-dialogue-canary.md +23 -0
- package/docs/keybindings.md +85 -0
- package/docs/operational-diagnostics.md +14 -0
- package/docs/replacement-contract.md +53 -12
- package/docs/session-restore.md +43 -3
- package/docs/troubleshooting.md +64 -3
- package/package.json +5 -5
package/docs/agent-workflow.md
CHANGED
|
@@ -27,8 +27,18 @@
|
|
|
27
27
|
|
|
28
28
|
## Maintained Test List
|
|
29
29
|
|
|
30
|
+
- Installed recovery receipt identity: `TestInstalledRecoveryReceiptMatchesPublicControlTurnIdentity` reproduces the public handler's quoted turn receipt versus the lifecycle snapshot's unquoted ID, then requires the fixture to decode the exact receipt and record only its validated `expectedTurn` before waiting. `TestInstalledRecoveryReceiptRejectsAmbiguousOrMalformedIdentity` requires one expected action label, one exact thread and one bounded opaque turn ID, decodes double-quoted fields with `strconv.Unquote`, and refuses missing/duplicate/unknown fields, wrong threads/actions, malformed/truncated/oversized identities and extra output. No stdout payload, completion inference or input retry is added.
|
|
31
|
+
|
|
32
|
+
- Managed recovery first-input admission: `TestObserverReadyControlStartPreservesOwnedReadAdmissionAndFreshness` runs the real repo broker host, session, observer and control handler with a deterministic broker clock and owned reader. It reproduces current authority/status-ready followed by the one-second `lifecycle-retry` refusal with zero turn writes, pins the exact boundary, and requires the admitted read to observe new state before any start. Retired control still writes zero. The installed matrix waits for the same exact authority/control tuple to remain ready for that existing interval before the recovered survivor's first input, inside its unchanged 90-second authority deadline; the ledger records `waiting-read-admission`. This is fixture pacing, not a fresh-state receipt or a retry of an attempted input. `TestInstalledRecoveryAdmissionRequiresStableExactControlBeforeFirstInput` resets that wait on identity, broker/connection/binding/control, unknown/not-startable, or clock reversal changes. No product admission, freshness or timeout policy changes.
|
|
33
|
+
|
|
34
|
+
- `make test`: `TestCodexNativeObserverForeignThreadSameTurnWritesNoRegistryProgressOrDiagnostics` waits for the observer's startup-ready callback after the initial progress/diagnostic flush, validates the complete baseline, then requires exact equality after a foreign-thread event. A following accepted lifecycle marker proves the foreign event was consumed; synchronization uses no sleep or expanded timeout.
|
|
35
|
+
|
|
36
|
+
- `make test`: Stored Codex version-pair qualification diagnostics (C-3) read the qualification store independently of the generation journal. `TestDoctorStoredCodexQualificationWithoutJournal` requires the saved pair and verdict even without a journal or readable Registry. `TestDoctorStoredCodexQualificationTextJSONSupportParity` covers saved, absent, corrupt, filename/receipt pair mismatch, unreadable store, measured refusal, and unbacked acceptance fixtures across text, JSON, and support `doctor.json`; the existing gate supplies qualification readiness. `TestQualificationStoreListPreservesPairOrderAndLoadVerdicts`, `TestQualificationStoreListDistinguishesAbsentDamagedAndPairMismatch`, and `TestDoctorStoredCodexQualificationKeepsValidSiblingsVisible` pin deterministic enumeration, unchanged Load judgments, invalid filename visibility, non-regular file refusal, and valid sibling retention. `TestDoctorStoredCodexQualificationReadOnlyArgvAndState` requires zero execution argv and byte/mode/mtime-identical receipt/journal state across repeated diagnoses; `TestDoctorStoredCodexQualificationSupportRejectsNonDiagnosticStrings` keeps unvalidated strings redacted. Receipt schema v2 and its lack of expiry remain unchanged.
|
|
37
|
+
|
|
30
38
|
- `make test`: Replacement guarantee Phase 1 makes `make install` finish the replacement it starts, for the one long-lived role that ships a drain. It adds a second entry condition to the drain the broker runtime already had -- the runtime's own image having been unlinked -- and a bounded termination condition for it. It adds no wire frame, no refusal token, and no way to end a process: the whole of the action is a socket handshake and the runtime decides. `TestBrokerRuntimeDrainsWhenItsOwnImageWasReplaced` holds the vintage trigger in both directions -- a runtime on the installed image is not drained, a superseded one is, live bindings keep delivering and keep control authority through the drain, a new bind is refused by name so the drain stays finite, the answer is read once rather than per session, and an idle superseded runtime closes as soon as it is asked. `TestReplacementRolePoliciesMatchTheContractDocument` holds the per-role disposition table and [replacement-contract.md](replacement-contract.md) equal in both directions and requires every census role to carry a stated decision. `TestReplacementSessionClientIsNeverADrainTarget` fixes the one entry that is a decision rather than an observation: the operator's attached session is report-only, and a fleet of nothing but attached sessions past the cutoff still produces no drain target. `TestReplacementDrainCutoffIsTheAdoptedValueAndBound` pins the adopted 24h cutoff -- truncation rate 9.5%, 13 of 137 residual processes by identity -- fixes the exclusive boundary, and rejects every spelling that would disable the bound. `TestInstallReplacementPassOutcomesAreFixedByFleetAndRequest` pins each fleet-and-request combination to its closed outcome token and its counters, including the refusal that says which door was closed. `TestInstallReplacementNeverFailsAnInstall` holds the property every post-publication step needs. `TestInstallReplacementOutcomeRecordCarriesNoProcessIdentity` and `TestInstallReplacementNoticeSpeaksOnlyWhenAnActionFollows` keep pid, path, and argv off the new record and the new terminal line. `TestDoctorReplacementProcessRowCarriesTheCutoffAndThePassAccount` holds the `L2` row: the bound it judged against, how many processes are past it, and what the last pass did, with an absent pass distinguished from a pass that found nothing. `TestReplacementPathEndsNoProcess` is the scope guard over the acting half -- no `os/exec`, no signal, no `Ensure` -- and `TestReplacementMeasurementPathEndsNoProcess` still holds the measuring half.
|
|
31
39
|
|
|
40
|
+
- `make test`: Replacement guarantee Phase 2 makes report-only routes and delete refusals point at runnable commands. `TestReplacementRoutesNameARunnableAction` requires every per-role action step to be a `projmux` command the CLI catalog resolves to a non-refusal, non-`internal` verb, or an event from the closed lifecycle set, and proves the check rejects unknown, refusal-parent, literal-operand, and `internal` commands; `TestReplacementRolePoliciesMatchTheContractDocument` now also holds the `Operator action` column and the event table equal to code in both directions. `TestPaneDeleteLiveMirrorRefusalNamesTheExactUIDRegistryOnlyForm` pins full refusal strings: a name-selected MissingRuntime Pane, Offline Agent, or zero-Pane Offline Agent names the typed resource's exact `projmux delete pane|agent uid:<uid> --socket-path <server>` `--dry-run`/`--yes` form, while exact-uid-without-evidence, evidence-less Pane, Running Agent, and Failed Agent refusals carry no pointer. `TestDeleteByNameRefusalPointsAtARunnableUIDCommand` reaches both refusals through the real route and resolver and runs the named dry-run command with zero Registry writes.
|
|
41
|
+
|
|
32
42
|
- `make test`: Replacement completion and restorability Phase 0 adds a read-only `projmux doctor` table only. [replacement-contract.md](replacement-contract.md) fixes the two axes, the closed per-layer reason-token vocabulary, and the closed signal-key inventory; nothing on this path changes install, update, or generation-pool behavior. `TestDoctorReplacementLayerVerdictsAreFixedByInputCombination` pins every reachable evidence combination of all three layers to its replacement verdict, restoration verdict, and governing token; `TestDoctorReplacementUnknownVerdictsNameTheEvidenceGap` requires each `unknown` to name which reading was silent and rejects an unreachable gap. `TestDoctorReplacementEveryReasonTokenCarriesARecoverableDiscriminant` is the negative gate: zero rows carrying a token with no discriminant. `TestDoctorReplacementSignalValuesCarryNoPathProcessOrFreeFormText` holds the serialization rule that lets the discriminant into `--json` -- every value is a counter or a closed token, and a path-shaped value becomes `unclassified`. `TestDoctorReplacementReasonTokensMatchTheContractDocument` and `TestDoctorReplacementSignalKeysMatchTheContractDocument` hold the document and the code constants equal in both directions and reject a published token no evidence reaches. `TestDoctorReplacementDarwinReportsUnsupportedPlatformForImageAndProcessLayers` fixes the `/proc`-less platform branch to `unsupported-platform` with `unknown` on both axes, with no device. `TestDoctorReplacementQualificationMissingMakesGenerationPoolNotRestorable` fixes `qualification-missing` to `not-restorable`. `TestDoctorReplacementCensusSeparatesRegistryRunningFromLiveProviderSession` reproduces the 2026-09-08 sample as a fixture: a Claude Pane's recorded process handle and a Codex Pane's composite authority are different discriminants, a Running Agent with neither is `unobservable` rather than live, and the row stays count-only. `TestDoctorRendersReplacementTableInDefaultRunAndSectionFilter` requires the table on an unfiltered run, under `--section replacement`, and in `--json`; `TestDoctorReplacementSectionCreatesNothing` runs the section against an empty home and requires it to stay empty.
|
|
33
43
|
|
|
34
44
|
- `make test`: Replacement guarantee Phase 4 names the long-lived process roles that were behind the `other` bucket and makes residual survival countable per process. It adds classification and reading only: no process is ended, started, signalled, or restarted anywhere on this path. `TestProjmuxProcessRoleNamesEveryChildIncludingTheOnesItCannotName` is the route-to-role table, including the reachable roles added here (`session-client`, `agent-endpoint`, `usage-watcher`), the `--role shell` value that must *not* read as an attached session, and the unnamed remainder. `TestProjmuxProcessRoleOrderKeepsTheUnnamedRemainderLast` holds the census shape and requires every named role to be reachable from some argv. `TestReplacementProcessRolesMatchTheContractDocument` holds the role vocabulary and [replacement-contract.md](replacement-contract.md)'s `Process role vocabulary` table equal in both directions, the same guard the reason tokens and signal keys already carry. `TestDoctorReplacementProcessRowNamesTheResidualRoles` requires the `L2` row to carry `residual.role.*` in census order and to omit a role with no residue rather than print a zero. `TestProjmuxProcessVintageRecordsTheStartInstantIdentityIsKeyedOn` pins the identity key the ledger deduplicates on and requires the count-only projection `projmux doctor` renders to stay byte-identical. `TestInstallResidueSurvivalCountsProcessesNotObservations`, `TestInstallResidueSurvivalKeepsEachProcessAtItsOldestObservedAge`, `TestInstallResidueSurvivalRecordedStartInstantsCompareExactly`, `TestInstallResidueSurvivalReconstructedStartsAbsorbTheirOwnSecondOfSlack`, and `TestInstallResidueSurvivalDoesNotChainAcrossNearSimultaneousStarts` fix `projmux internal install-residue --survival`: both bases, the one-second ambiguity of a start reconstructed from an age, and the bound that keeps that ambiguity from chaining a burst of starts into one process. `TestInstallResidueSurvivalCarriesNoProcessIdentity` is the negative audit for the new report, and `TestInstallResidueSurvivalRouteAnswersOrSaysWhyItCannot` separates the census path, which must never fail an install, from the survival path, which owes a reader its reason. `TestReplacementMeasurementPathEndsNoProcess` is the scope guard: the four files of the measurement path may not acquire process termination, signalling, or restart, because this layer is one edit away from turning a census into an unplanned drain.
|
|
@@ -40,6 +50,11 @@
|
|
|
40
50
|
- `make test` / `make test-integration` / `make test-e2e`: Columnar profiles Phase 1 changes only the CLI default projection. Registry plural reads use `KIND NAME STATUS ACTIONS`; runtime reads use identity/containment/classification, and the seven list routes accept explicit `-o wide`. [Column profiles](column-profiles.md) records the exact matrix and diagnostic recovery. `TestColumnCatalogCompletenessBijectionAndExactProfiles` compares typed field declarations to surface capabilities, rejects orphan/duplicate IDs and fixes all nine compact/wide orders and aliases; `TestColumnConsumersHaveNoIndependentHeaderLiteralAuthority` audits all four consumers. `TestColumnProfilesExactOutputAndSnapshotParity` pins whole default/wide output, structured/scalar byte digests and both explicit picker-wide entry frames in `column-profiles.golden`; its production observation fixture includes live, offline, missing-root and ControlSession-owned resources and proves one Registry read, exactly one four-query tmux observation, zero writes and zero sibling-server calls for every mode. ACTIONS is compared directly with the existing navigation projector and fixed eligibility examples. `TestColumnActionsReuseUnavailableSnapshotAndEmptyListsStayEmpty` pins unavailable-server actions and empty list bytes. `TestColumnProfilesDoNotSelectFromWidthAndWideIsUnbounded` checks 80/120 widths and long Hangul context/session values; `TestWideOutputIsScopedToColumnarListReads` rejects wide on every other canonical route. Existing age, session reference, context, termination, selector, JSON and picker layout tests retain their assertions through the explicit wide recovery surface where necessary. The integration and E2E exit-reconciliation probes explicitly use `get panes|agents -o wide` and retain their TERMINATION/evidence and Registry-write-free assertions. Phase 2 below owns the subsequent picker default/control and bound retirement; CLI, row identity/order/search and provider semantics retain these contracts. Isolated piped CLI smoke compares default/wide/JSON/scalar bytes and read/write counters at 80/120 columns before and after installation.
|
|
41
51
|
|
|
42
52
|
- `make test` / installed opt-in smoke: Codex generation-pool Phase 2 keeps a state domain bounded to two dark private endpoint generations and keys each Broker by the canonical durable `stateDomainID + endpointGenerationID`. `TestGenerationEndpointKeyRoundTripTable`, `TestBrokerEndpointIdentityValidityMatchesDurableMetadataRef`, and `TestGenerationPoolStateTableKeepsPreparingDarkAndBounded` pin key/schema vocabulary parity, third-generation zero effect, and ready-Preparing create admission at zero. `TestGenerationPoolReconnectIsGenerationLocalAndCrossRouteWritesZero`, `TestGenerationPoolBrokerRestartRestoresExactBindingsAndFencesOldRuntime`, `TestGenerationPoolBrokerRestartPreservesSparseBindingEpochLedger`, `TestGenerationPoolFailedRestartRetryKeepsLedgerExactAndFencesOldRuntime`, `TestGenerationPoolRestartFenceRejectsBindingThatMissedTheSnapshot`, and `TestGenerationPoolRestartFenceRefusesControlAndWriteUntilExactSwap` use independent fake servers and semantic barriers to pin sibling reconnect isolation, same-thread cross-route typed refusal/provider write zero, exact/idempotent including sparse binding-ledger restore, fresh broker-runtime fencing, failed-restart retry, and the bind/control/write-vs-restart races. `TestPrivateGenerationHostLaunchProofTableAndLeaseRetention`, `TestPrivateGenerationHostLivePIDSocketExecutableDriftKeepsLifecycleAtZero`, `TestEveryQualifiedBundleArtifactIsMandatoryBeforePublish`, and `TestLaunchBoundaryBundleDriftRefusesPublicationAndCleansExactChild` pin the closed server/TUI/helper bundle, immutable leased argv, Phase-2-closed lease release, distinct endpoint-host versus broker runtime authority, pre-publication revalidation, and PID/process-group/socket-change-time/executable proof with lifecycle mutation zero for every drift, including immediate socket inode reuse. `TestPrivateGenerationHostCloseWaitsForOwnedSessionDescendants`, `TestPrivateGenerationHostCloseProcessSessionBarrierStateTable`, and `TestOwnedGenerationProcessCleanupSignalsExactSessionAndWaitsForDescendantExit` pin the exact `Setsid` group signal and the leader-exit plus inherited-session-EOF semantic barriers without a fixed sleep; the private-root tests retain outside-root, symlink, and mode mutation zero. `TestInstalledPrivateGenerationHostDualListenerSmoke` is opt-in and runs exact leased 0.152.0/0.152.1 private listeners with inherited `TMUX`/`TMUX_PANE` absent, two initialized runtimes, distinct private process groups, ambient/default socket/PID identity unchanged, and descendant-complete exact owned cleanup. Deletion ledger: zero canonical test symbols deleted or renamed; single-default broker, Phase 0 qualification/bundle, and Phase 1 composite-fence/projection tests retain their unique boundaries. Scope audit: current pointer/drain, Agent create/resume, foreign adoption, Settings/background UX, consumer projection, and unrelated cleanup remain unchanged.
|
|
53
|
+
- `make test` / `make test-integration` / installed managed recovery: `TestRecoveredBrokerRetiredBarrierCannotRepublishAuthority`, `TestDefaultBrokerEndpointRequiresProbeWireAndRouteAgreement`, `TestRecoveredDefaultBrokerRebindsExactAuthorityAndControlConsumers`, and `TestRecoveredGenerationAuthorityRejectsStaleEndpointAndActivation` cover default socket probe/initialize/version agreement, current barrier publication, exact surviving Agent/Pane/activation/thread endpoint CAS, current control consumers, old-runtime epoch-1 refusal, old writes zero, and stale/unknown/Draining refusal. `TestRecoveredBrokerConcurrentOpenSharesOneCurrentView`, `TestRecoveredBrokerOpenWaiterHonorsCancellation`, `TestRecoveredBrokerCloseCancelsPendingRouteAndEnsure`, and `TestEnsureCancellationDuringStartupLockNeverLaunches` verify shared publication, cancellable queued Open, bounded Close during route/Ensure, and no launch after startup-lock cancellation. `TestRecoveredDefaultBrokerRefusesNewRollingJournalBeforeSameEndpointReopen` verifies typed read-only admission refusal before probing or reopening the same endpoint. Existing broker disconnect, runtime replacement, owned lifecycle cancellation, and Phase 0 usage timing tests remain required. `TestInstalledManagedCodexAuthorityRecoveryMatrix` takes only an explicit `PROJMUX_CODEX_RECOVERY_INPUT` JSON file: private root, exact installed binary/SHA/source head/tree, two read-only release mounts, protected private auth input, explicit model and ten fresh validation inputs, host namespace IDs, and evidence path. It uses real installed projmux, real tmux, official managed daemon/proxy, and the repo Go client for baseline 0.151.0, upgrade 0.154.0, and three same-version restarts; one survivor and a new control complete actual turns in every row. Its content-free ledger retains failures and submission counts; it never replays work. Before each create/turn input, the same verified selection guard used by the zero-input diagnostic records exact fixture shim/release evidence and refuses a fallback CLI before incrementing submissions. `TestInstalledRecoverySelectionRefusalKeepsSubmissionsAndProviderCallsZero` reproduces execution-denied shim PATH fallback and pins create/turn refusal with zero inputs; `TestInstalledRecoverySubmissionRecordsSelectionBeforeExactlyOneInput` pins evidence-before-input ordering and rechecks every later sample. Run `go run ./internal/testutil/codexinstalled/cmd/managed-preflight </absolute/input.json>` first to verify the same general fixture helper with official start/version/stop, PID birth/artifact/socket/executable checks, and no real inputs or auth. `TestManagedRecoveryColdStartRequiresExactAbsentState`, `TestManagedRecoveryVersionMissingClassificationIsExact`, and `TestManagedRecoveryCleanupNeverFallsBackAfterUnknownStart` cover exact initial ENOENT plus owned absent state, unknown-result refusal, and zero fallback stop/signal/removal after unresolved ownership. Both runners refuse shared namespaces, ambient managers, and missing init reapers. Each turn waits for exact control publication and a successful read-only status response as well as registry authority. The matrix's unique tmux server has a fixture-private default-name socket alias for outside-tmux public commands; cleanup verifies the exact socket and waits for normal owned process exit. Linux managed conformance is opt-in and separate from Darwin compile/CI and generation qualification.
|
|
54
|
+
- Managed recovery failure evidence: `TestInstalledRecoveryReadinessReachesProductionControlThroughCanonicalAlias` reproduces the readiness fixture's unsupported capability spelling before any tmux/control call and requires readiness to resolve `agent turn start`, then issue status only through the production exact control consumer. It tests baseline and later current authority through the outside-tmux default alias, canonical logical socket and exact physical socket/PID proof; the public turn-start handler consumes the same route/epoch. Empty optional Codex `SessionID` remains empty while the nonempty ThreadID stays exact. `TestInstalledRecoveryReadinessAndTurnRefuseCanonicalAliasDriftBeforeControl` requires both readiness and turn start to make zero control calls on route drift. `TestRecoveryErrorDistinguishesNoBrokerRefusalAndRedactsUnknownContent` requires `RefusalNone`/generic errors to stay unclassified without a false broker label, while known typed codes remain useful and unknown content is redacted. `TestRecoveryFailureEvidenceRetainsPartialIdentityWithoutContent`, `TestRecoveryReadinessDistinguishesRefusalsAndOnlyRequestsStatus`, and `TestRecoveryObserverEvidenceFiltersIdentityVocabularyAndContent` preserve each attempt/created UID before completion, bounded partial Registry and exact tmux/control observations, and terminal process/observer evidence without provider content. Unknown error/message/approval fields are omitted or classified; diagnostics never submit a turn. `TestCleanupEvidenceRetainsErrorsWithoutRetryOrFalseSuccess`, `TestCleanupEvidenceReadsOnlyOneStatForValidatedProcIdentity`, `TestCleanupStatProjectionRejectsMalformedOrDifferentPIDWithoutContent`, and `TestOwnedProcessObservationErrorRetainsCauseWithoutContent` cover both harnesses' cleanup evidence: closed stage/operation, numeric errno, validated proc PID/leaf and at most one bounded later stat birth/state snapshot. Failure diagnostics retain the original error; their optional later snapshot grants no cleanup authority or false success and never rereads environment/argv or retains raw errors/process contents. `TestOwnedProcessesPermissionDeniedZombieRemainsNonemptyResidual` reproduces environment EACCES followed by an exact zombie stat. Only after a verified official lifecycle and rechecking the same private PID/mount/network namespaces with an init reaper may the general fixture retain two matching bounded zombie stat observations as an explicit `unreaped-residual`, distinct from an `owned-executable` and never signal authority. `TestOwnedProcessesPermissionFailuresRemainErrorsUnlessExactPrivateZombie`, `TestResidualAdmissionRequiresRecordedPrivateLifecycleProof`, `TestOwnedProcessesResidualRequiresNormalReapingBeforeCleanup`, and `TestOwnedProcessesFailedCensusCannotClearEarlierResidual` require live/unknown permission failures, malformed/disappeared/reused stat, and changed namespace proof to remain errors; known residuals block cleanup until a successful later census proves normal reaping. Existing drain deadlines remain unchanged. `TestCleanupResidualHistoryRetainsUnreapedEvidenceAfterNormalDrain` pins both installed ledgers retaining bounded PID/birth/state/parent residual history even after the inventory becomes empty; evidence overflow refuses rather than dropping observations.
|
|
55
|
+
- Installed command failure evidence: `TestInstalledCommandFailureCapturesOnceWithoutOutputOrFalseOutcome` verifies one fixture command invocation, numeric exit capture, inherited tmux environment removal, unchanged successful output, and zero raw stderr/stdout/argv in failure ledgers. Both installed runners save bounded `commandFailure`; the matrix also attaches it to the current attempt without changing submissions or completion counts. `TestInstalledCommandFailureProjectionRequiresBoundedKnownCLIShape` accepts only closed turn-start response/message pairs or established CLI wrapper prefixes, validates and discards resource-selector recovery suffixes, and refuses multiline/control-byte/unknown/oversized content. Stderr capture drains at a fixed 4096-byte memory bound. `TestInstalledCommandFailureRetainsUnknownOutcomeAfterReadinessAndControl` exercises the public Cobra bridge and exact control handler: status readiness can precede a failed fresh state read, a failed wire call, or an error recording an accepted turn. These are boundary fixtures, not proof of any actual failed invocation's cause. Every failure retains `outcome=unknown`; there is no retry, partial-output success, or provider mutation inference.
|
|
56
|
+
- Zero-input managed connection diagnostic: `TestInstalledManagedCodexConnectionDiagnostic` accepts only an absolute `PROJMUX_CODEX_CONNECTION_INPUT` JSON file with private root, exact binary/SHA/source head/tree, two read-only releases, host namespace IDs and external evidence path. It proves the same real tmux/Registry route, then official manager ownership and production default Current/shared/owned initialization and Close for 0.151.0 and 0.154.0. There are zero Agents, threads and provider inputs; no Bind, thread read/start/resume or turn call. `TestConnectionDiagnosticInitializesAndClosesWithoutProviderOperations` and `TestConnectionDiagnosticRefusesModelAuthAndProviderInputFields` enforce those limits. `TestManagedSelectionShimAndProbeFollowCurrentLinkWithoutVersionCache` isolates the fixture environment producer and production PATH manager-probe consumer across a current-link change using explicitly synthetic manager responses: CLI, managed and manager-evidence versions follow the link, attached versions remain empty, and a running-manager/absent-wire contradiction refuses attach and lifecycle mutation with unknown ownership. `TestConnectionSelectionEvidenceDistinguishesShimReleaseAndDrift`, `TestConnectionFailureProbeCannotReplaceCurrentRefusalWithLaterHealth`, and `TestConnectionHealthEvidenceRejectsUnboundedProviderStrings` retain exact fixture shim/selected-release paths and hashes, state domain, and closed health/CLI/managed/running/wire versions. A failed connection gets one bounded later read-only probe, explicitly separate from the failed Current observation; later readiness never replaces that failure or retries Current. Unexpected selection refuses before another CLI invocation. This diagnostic does not replace the actual survivor matrix. Run with a private TMPDIR outside CODEX_HOME (for example `/artifact/tmp`) to avoid official CLI PATH-helper warnings. `TestExplicitInputIsBoundedAndCannotTraverseOrFollowSymlinks` covers the shared regular JSON input reader: absolute clean path, parent directory capability, no final symlink, maximum 64 KiB.
|
|
57
|
+
|
|
43
58
|
- `make test` / installed opt-in smoke: Codex generation-pool Phase 3 routes prompted and payload-free native create through one exact current `stateDomainID + endpointGenerationID`, then keeps resume, message/reply/approval, lifecycle observation, and TUI argv pinned to the durable Agent ref even after admission-current changes. `TestCodexNativeCurrentChangePinsExistingAgentAndAdmitsNewCreateOnlyToNew`, `TestCodexNativeResumeRouteUsesDurableEndpointAndRefusesLegacyOrDraining`, `TestOfflineCodexResumeRechecksDrainingInsideTransactionBeforeProviderWrite`, and the Agent-control action table pin old/new cross-wire zero, locked-transaction lifecycle revalidation, typed missing/Draining refusal, and provider/Registry first-write zero. `TestGenerationRoutedBrokerEpochPublishesItsExactRuntimeAuthority`, `TestCodexNativeEndpointRouteTransportShapeIsClosed`, `TestDefaultCodexStateDomainIdentityUsesExactCanonicalCodexHome`, and the broker transport tests require real generation-keyed broker runtime authority, default/private transport XOR, and canonical content-free state-domain identity; a changed `CODEX_HOME` never reattaches a stored Agent. `TestNativeResumePickerRowsPreserveExactGenerationThreadAndSource`, `TestNativeResumePickerDuplicateVisibilityUsesKnownOwnerOrRefusesAmbiguous`, and `TestCodexResumePickerPinnedValueShapeIsClosed` freeze source/domain/generation/state in each native row value, visibly mark handover/unavailable rows, refuse duplicate visibility without a durable owner, and keep rollout rows unable to carry partial native authority. `TestInstalledIsolatedGenerationPinnedEmptyPromptCreateSmoke` is opt-in through `PROJMUX_CODEX_PHASE3_SMOKE_ROOT=/tmp/<isolated-root>` and runs the installed binary against a fixture-owned unmanaged direct endpoint plus unique Registry/tmux roots; it first bootstraps the fresh generated app config through the installed public `config apply` path with no live isolated server, then accepts only the exact tuple's closed Phase-7 result: durable-ready keeps the historical payload-free Agent↔Pane↔thread↔endpoint, zero-turn, pinned-TUI, broker, obligation, ambient-mutation-zero, and cleanup assertions, while typed not-ready preserves one exact Failed Agent/thread/endpoint with Pane/TUI/plain fallback zero and an unresolved exact-UID retry with second Agent/thread/lane zero. Installed Codex does not subscribe the broker until the first real input materializes the rollout, so the successful pre-turn row keeps native authority unavailable instead of adding dummy content; the provider-recorder integration owns first-real-input same-thread/one-turn proof without requiring ambient auth. Each observation records its exact CLI/app-server/platform/route tuple and is not a version-family guarantee. Phase 5 old-endpoint stop, successor same-thread resume, endpoint-ref CAS, Pane relaunch, retirement, lease release, and foreign adoption remain out of scope.
|
|
44
59
|
- `make test` / `make test-integration` / private installed observation: Codex generation-pool Phase 4 owns explicit crash-resumable `plan|apply|resume|abort`, at-most-once admission-current, and old-generation drain. `TestRollingUpgradeStateMachineKeepsPhase5EffectsAtZeroAndReceiptsAtMostOnce`, `TestRollingUpgradeStateSpaceProperty`, and `FuzzRollingUpgradeValidStatesNeverContainPhase5Effects` pin monotonic receipts and all seven Phase-5 effects at zero, including `leaseRelease`. `TestCoordinatorExactPhase0TuplePreflightRefusesBeforeEveryMutation` re-opens both complete leases read-only and pins exact bundle/version/RoleTUI plus same-domain, direct-socket, and non-overlapping private/state/lease-root topology before any physical start. `TestCoordinatorResumeAfterLaunchBeforeProofReusesOneCandidateAndLeavesNoDuplicate`, `TestCoordinatorAbortFencePreventsStalePlannedResumeFromLaunching`, `TestCoordinatorAbortAndAdmissionRaceNeverStopsCurrent`, `TestCoordinatorEveryFailpointCrashRestartConvergesAtMostOnce`, and `TestRollingJournalAtomicWriteCrashHooksRestartWithoutDuplicateEffects` cover coordinator death after supervisor launch, all ten declared coordinator failpoints, both journal atomic-write crash hooks, exactly-once candidate-start/admission/drain/handover convergence after restart, the durable abort fence, and deterministic Abort-vs-admission schedules without fixed sleeps. `TestCoordinatorCandidateReadyAbortCleansExactCandidateAndKeepsSevenPhase5EffectsZero`, `TestCoordinatorLaunchBeforeProofAbortCleansRecoveredCandidateWithoutPhase5Effects`, `TestRemoveCandidateSocketRefusesUnknownOrReboundIdentityWithoutUnlink`, `TestCleanupDurableCandidateAfterSupervisorExitRemovesOnlyOwnedSocketAndReceipts`, and `TestCleanupDurableCandidateRecoversOnlyExactUnlockedOrphanGuard` pin exact candidate cleanup, retained bundle lease, unlocked no-socket orphan-guard recovery, and locked/foreign/rebound mutation zero. `TestExactRoleTUIArtifactRefusesWrongAbsolutePathAndPostVerifyDrift`, `TestCoordinatorWrongAbsoluteTUIPathNeverCommitsAdmission`, and `TestCoordinatorTUIDriftAfterReadyProofFailsInsideAdmissionBarrier` require the exact single RoleTUI lease artifact at publication and commit. `TestCoordinatorTwoSlotThirdUpgradeRefusesWithEveryMutationSurfaceAtZero`, `TestCoordinatorRetainedRetiredRoutesDoNotConsumeThePreparingSlot`, and `TestCoordinatorAbortedOperationRefCannotBeReplayed` close capacity/replay consistency. `TestAgentResumeDrainingGenerationFailsClosedWhenHandoverRequesterIsUnconfigured` tables both Draining and HandoverPending with an unconfigured requester, while `TestAgentResumeDrainingGenerationReusesOneGenerationWideOperationRef`, `TestCoordinatorRepeatedDrainingResumeReusesOneGenerationHandoverOperation`, and `TestDrainingOldCodexAgentKeepsExactTurnControlTUIAndPaneBinding` cover exact operation-ref reuse and direct old-generation turn/control without endpoint/TUI/Pane mutation. `TestPrivateRollingAdmissionReceiptRendersAllSevenPhase5EffectsAtZero` and opt-in `TestInstalledPrivateRollingAdmissionReceipt` cover content-free receipts, private process groups, ambient/default read-only observation, exact old Draining thread read plus successful no-turn-compatible listing, payload-free new Current create/read, assertion-safe exact target teardown, and ambient-preserving cleanup. Deletion ledger: zero canonical tests deleted or renamed and zero Phase 0–3 boundary suites merged; the canonical graph baseline only adds the four explicit upgrade leaves. Phase 5 effects remain zero in the unchanged Phase-4 receipt and are implemented only by the distinct linked handover journal.
|
|
45
60
|
- `make test` / `make test-integration` / opt-in installed private observation: Codex generation-pool Phase 5 owns `agent app-server handover plan|apply|resume|abort` and the generation-wide `stop → resume → snapshot-all → endpoint CAS → same-Pane relaunch → terminal retirement → lease release` journal. `TestGenerationHandoverOrdersStopResumeSnapshotCASRelaunchTerminalLease`, `TestGenerationHandoverCannotCASUntilEverySnapshot`, and `FuzzGenerationHandoverNeverAcceptsUnsafeReceiptOrder` pin monotonic per-effect intents, the global snapshot barrier, and terminal lease ordering. `TestCoordinatorGenerationWideOrderingAndEveryFailpointResumeConvergesWithoutDuplicateEffects`, `TestCoordinatorRecoversExactSameGenerationBeforeHandoverAndCrashRetryIsIdempotent`, and `TestCoordinatorUsesQualifiedFallbackWhenExactSameGenerationRestartIsUnavailable` cover every coordinator effect gap, journal-authoritative repeated Apply, same-generation-first cold recovery, and exact-qualified fallback without a fixed sleep. `TestExternalOwnersRemainAwaitingOwnerStopWithLifecycleArgvZero`, `TestIncompleteManagedOldRouteBlocksBeforeEveryEffect`, `TestSuccessorPreloadedTargetStopsBeforeOldStop`, `TestPlanIgnoresSameGenerationIDFromAnotherStateDomain`, `TestAppliedNoTurnChoiceIsForwardOnlyAndCannotClaimAuthorityRestored`, and the abort-fence tests pin the ownership matrix, exact state-domain tuple, reversible-only abort, explicit no-turn choice, pre-stop loaded-thread refusal, and foreign lifecycle argv zero. Production-effect tests revalidate the pinned Agent/Pane/runtime/generation/thread tuple before successor absence, old stop, resume, snapshot, and same-Pane relaunch; `TestHandoverResumeReceiptSurvivesSuccessorRestartWithoutSecondResumeWire` pins the content-free operation-qualified at-most-once resume receipt. `TestInstalledPrivateJournaledGenerationHandover` is opt-in through `PROJMUX_CODEX_PHASE5_SMOKE_ROOT=/tmp/<isolated-root>` and uses exact private 0.152.0→0.152.1 binaries plus isolated XDG/tmux roots for the public handover and no-turn negative. Enforcement ledger: prompt/turn/approval resend, provider-content replay/inspection, duplicate same-thread ownership, automatic no-turn migration, foreign kill/adopt, live-old same-thread resume, Phase-6 consumers/Doctor, and unrelated cleanup remain zero. Deletion ledger: zero canonical tests deleted or renamed; Phase 0 qualification, Phase 1 lifecycle fencing, Phase 2 host/pool, Phase 3 generation-pinned routing (including the empty-prompt migration receipt), and the Phase-4 seven-effect-zero suite retain their unique symbols and boundaries; the command graph adds only four handover leaves.
|
|
@@ -52,6 +67,9 @@
|
|
|
52
67
|
- `make test` / `make test-integration` / `make test-e2e`: Window anchor and primary-shell separation Phase 2 closes the role/live consumer table. `TestAnchorAwareCreatePaneAndAgentUseExactLiveShellAnchorDetached`, `TestAnchorAwareCreatePaneAndAgentUseExactLiveAgentAnchorDetached`, `TestAnchorAwareCreatePaneAdoptsNewShellAsEmptyDefaultWithoutReplacingShellAnchor`, the paired resume tests, and the explicit-Pane/popup precedence tests pin detached exact-Window outcomes and create-time default-shell adoption. `TestAnchorAwareCreateRefusesDeadAndCrossWindowAnchorsWithZeroWrites` and `TestRegistryTopologyMaterializationRefusesDeadAnchorWithoutAlternateLivePaneInference` prohibit alternate-live-Pane inference. `TestRegistryTopologyMaterializationAgentAnchorLazyDefaultShellAndRepeatNoop` plus the installed isolated real-tmux Agent-only Window fixture pin the plan-visible lazy shell, preserved Agent anchor/Pane uid, exact default owner/ref graph, smoke-root socket containment, and repeat no-op. `TestFocusKindOnAnOfflineTargetExitsTwoAndMaterializesNothing`, `TestFocusKindMovesTheClientToAnAlreadyLiveTarget`, and `TestControlOwnedRegistryKeepsMaterializeGreen` cover strict read/navigation-only focus and the Project/ControlSession root boundary.
|
|
53
68
|
- `make test` / `make test-integration` / `make test-e2e`: Window anchor and primary-shell separation Phase 3 keeps canonical Pane/Agent delete and clean exit independent from explicit Window deletion. Registry-order sibling choice, optional-empty default shell, Offline Agent retention, and same Window UID/name remain pinned for non-last Pane deletion. Project runtime stop Phase 1 supersedes the old last-Pane replacement boundary: an exact clean last-Pane receipt waits for its matching `window-unlinked`, then deletes only the Window subtree with zero replacement allocation. Explicit `delete window --yes` uses the same root-preserving shape: a non-last primary reanchors to its existing sibling and a last Window leaves the Project uid/root/reservation with empty `primaryWindowRef`; only explicit `delete project` unregisters the root. Unknown, killed, unpaired, foreign, stale, missing-server, and empty observations retain zero Window-delete authority.
|
|
54
69
|
- `make test` / `make test-integration` / `make test-e2e`: Window anchor and primary-shell separation Phase 4 closes projection and startup over final-v2 desired state. `TestSnapshotProjectionFinalV2RefsAndOpenFreshGolden`, `FuzzSnapshotProjectionIsScopedValidAndIdempotent`, and `FuzzOpenFreshKeepsOnlyCanonicalProjectShell` pin metadata-bearing and legacy snapshot projection, Agent-anchor/default-shell policy, target-subtree replacement, source-snapshot preservation, and fixed points. `TestProjectFreshStartPruneScope` preserves an existing canonical Project/Window/shell UID chain and exact transaction-level Registry bytes across repeated Open fresh, while `TestProjectFreshStartAgentAnchorCreatesExactMinimumShellAndRepeatsNoop` covers its one permitted shell allocation; `TestRestoredOfflineAgentAnchorContinueConvergesLazyShellAgentAndRepeatNoop` covers offline restore through lazy default-shell/Agent materialization. `TestAuthorshipPromotionPreservesSiblingProjectSocketAndOtherHostDesiredState` pins exact-socket positive convergence while sibling-socket and other-host-only desired refs/status plus Registry order remain byte-identical. The isolated smoke covers snapshot/Open fresh closed repeats with the exact UID chain, lifecycle Window survival, create/resume/materialize/focus, failure/repeat paths, and exact-socket sibling isolation.
|
|
70
|
+
- `make test`: Install handover Phase 1 keeps every Window anchor writer inside the validator's anchor predicate. `TestWindowAnchorEligibilityPredicateBranches` pins the membership, role, and managed-Agent-Pane clauses of `windowAnchorEligibility`; `TestDeletePaneReanchorSkipsReleasedAgentPaneForEligibleShell`, `TestTransitionAgentReleasingAnchorPaneMovesAnchorToEligiblePane`, `TestAnchorWritersCloseOnNewDefaultShellWhenNoPaneIsEligible`, and `TestAttachAgentPaneMovesAnchorFromPreviousBindingToNewManagedPane` cover delete reselection, termination release with an empty `paneRef`, the default-shell close with preserved ineligible rows, and rebind including the snapshot-projection Offline binding; `TestAnchorWritersPreserveValidationOverRandomWindowConfigurations` (seed 20260913, 512 iterations) requires `Validate` after every writer; `TestTopologyAgentContinueAdmitsTerminatedAnchorAgentWithEmptyPaneRef` keeps the terminated anchor Agent out of the `still records a current paneRef` refusal.
|
|
71
|
+
- `make test`: `TestStampProjectSnapshotSkipsUnboundPanesInRuntimeIDDuplicateCheck` pins that snapshot save's Pane runtime id duplicate check skips only a `MissingRuntime`=True/`RuntimeUnbound` Pane: its retained tmux id reused by a live Pane stamps the live Pane's UID, leaves the unbound Pane's `Status.Activation.RuntimeID` intact and absent from the snapshot, while two live Panes, a False condition, or another reason sharing the id still refuse with `share runtime id`.
|
|
72
|
+
- `make test`: `TestStampProjectSnapshotSkipsUnboundWindowsInRuntimeIDDuplicateCheck` pins that snapshot save's Window runtime id duplicate check skips only a `MissingRuntime`=True/`RuntimeUnbound` Window: its retained tmux id reused by a live Window stamps the live Window's UID, leaves the unbound Window's `Status.RuntimeID` intact and absent from the snapshot, while two live Windows, a False condition, or another reason sharing the id still refuse with `Registry Windows ... share runtime id`.
|
|
55
73
|
- `make test` / `make test-integration` / `make test-e2e`: Codex native control plane Phase 3 projects a closed, content-free app-server lifecycle into Agent interaction, badges, attention, and notifications. Unit and fuzz event sequences pin exact thread/turn/item/request approval identity, waiting-plus-unresolved gating, resolution and leave-waiting clears, successful completion once, failed/interrupted non-completion, and old-epoch/foreign-identity writes at zero. Fake proxy tests pin observation-only server requests with no approval response, snapshot convergence, invalidation-before-fallback ordering, reconnect replacement, and all Codex hooks writing zero through pending/healthy/invalidating authority. Settings and delivery tests pin the independent `approval_required`/`response_complete` Notify/State only/Quiet matrix across app-server and hook-fallback epochs, explicit raw fallback-only precedence, exact non-Notify queue clearing, raw hook-byte preservation and no inference, mixed multi-Pane source/reason/epoch diagnostics, Quiet aggregate-badge suppression, and content-free `describe agent` rows. Isolated tmux integration and e2e cover exact Registry/Pane/generation/thread binding, native/fallback/reconnect behavior, queue/desktop outcomes, sibling containment, and a privacy/scope inventory that excludes prompt/control, progress/diff, catalog/session-state, provider configuration, schema, and release changes.
|
|
56
74
|
- `make test` / `make test-integration` / `make test-e2e`: Codex native control plane Phase 7 admits only bounded scalar progress from the exact current app-server turn. The adapter drops plan explanation/step text, diff bytes and paths after a 256 KiB header-only scan, and every item body while mapping only the installed-schema discriminator into the ten-value activity set. Unit and fake-clock properties pin 99 plan steps, 999 changed-file headers, 32 opaque dedupe ids, deterministic dropped/unknown/overflow counters, identical/out-of-order write zero, and at most four non-terminal Registry writes per Agent per second. Adapter-to-reducer-to-Registry/read/UI tests pin exact activation turn attribution, KO/EN 80/100/120-cell rendering, read-time-only Window counts, and immediate zero-history clear on completed/interrupted/failed turn, generation replacement, disconnect/invalidation, Offline, and Failed; unavailable native progress leaves the existing interaction UI unchanged. Privacy inventories reject prompt, reasoning, step, command/tool/file/path/name/output, diff body/hash, model, and effort fields across the reducer input, durable Agent status, describe/Inspector projection, tmux options, and diagnostics.
|
|
57
75
|
- `make test`: Codex native control plane Phase 0 keeps the app-server wire in `internal/integrations/agents/codexappserver` and pins the headerless JSON-RPC JSONL frame bound, monotonic request IDs, out-of-order response routing, initialize/initialized lifecycle, typed notification delivery, context-bounded request and initialized-notification writes, local cancellation with ignored late responses, and connection replacement with no goroutine leak. A fake stdio proxy matrix closes healthy, missing/disconnected, unsupported `-32601`, malformed, and timeout outcomes into exactly one of available/unsupported/unavailable/timeout/protocol-error, while Doctor, support-report redaction, and the Settings no-op state row expose only source/reason/version/endpoint-kind/connection-state. Negative source and argv audits keep daemon mutation, login, config writes, remote transport, all existing Agent/hook/resume/usage consumers, giant provider interfaces, and Settings source controls at zero.
|
|
@@ -134,6 +152,7 @@
|
|
|
134
152
|
This v4 row supersedes the automatic short-name, direct-owner reservation, and stored-presentation assertions in the earlier historical Registry observation and selector entries; those entries continue to document the defects and seams that produced the current tests, not the current wire contract.
|
|
135
153
|
- `make test-e2e`: Project-wide naming closure Phase 2 automatic-name witnesses against real tmux. L06 `create-materialize` registers alpha with an explicit `--name alpha` and beta with no `--name` at all, then proves the automatic Project name is the exact created uid: beta's uid is read back through the read-only `get projects -o json` projection selected by beta's exact root -- never by listing order, and never by re-issuing the create, whose reuse projection a later Phase owns -- the root-selected uid is confirmed to be the Project bound to that exact root, `describe project uid:<uid> -o name` equals the uid byte-for-byte, and the create result line is `project/<uid> created` rather than any semantic stem; every later beta reference in that scenario is therefore a `uid:` reference, because the automatic name is no longer the word `beta`. L12 `first-open` proves the same for an implicitly registered Project, then separates the two mirrored fields whose v4 values coincide: `@projmux_project_name`, `@projmux_project_uid`, and `@projmux_project_path` are each asserted on the freshly opened `work-gamma` session, and because an automatic name *is* the uid there, two explicit `rename project uid:<uid>` round-trip steps on the inherited absolute socket make the fields diverge -- the name mirror follows every address change while the uid mirror, the path mirror, and the session name stay exactly where they were, with the failure message naming which of the three drifted. L07 `binding-convergence` adds the cross-kind half: an alpha Window and an alpha Pane both named `shared` coexist in the one root and `describe window shared -o uid` / `describe pane shared -o uid` each return their own exact uid. L06 also proves the automatic Agent name is the exact Agent uid -- the payload-free `create codex` shortcut allocates exactly one new `agent-<uid>` identity rather than reusing the provider-named first Agent, a `--` payload reaches the provider and never the name, no numeric suffix exists to append, and an explicit `--name` colliding with the one human-chosen Agent name in the owning root is still exit 2 with zero writes and no new pane. L14 `registry-navigation` keeps its imported shell Pane automatically named and renders it offline, which is covered by the compact-default picker contract below.
|
|
136
154
|
- `make test` / `make test-e2e`: Columnar picker Phase 2 supersedes the naming Phase 2 NAME/RESOURCE workaround. `TestPickerCompactFullUIDAndHangulFits80Columns` fixes the compact `KIND NAME STATUS ACTIONS` first frame inside 75 cells with full UID names, Hangul context and real action lists; only repeated provider/phase and role display adornments move to wide. `TestPickerCompactNativeFramePreserves76CellRegression` keeps the prior 66-cell fixture and the observed 76-cell clipping regression, proves the latter clips under the real renderer pipeline, then checks every full compact field after picker-local one-cell spacing (63/73 cells). `TestPickerWideNativeFrameViewportMatrix` runs the same native frame/scrollbar/pointer pipeline at 80/120/180/184 columns: the historical 142-cell row clips through 180 and is complete at 184; wide retains its two-cell gap. `TestPickerWideRetainsUnboundedValuesAndDetailRecovery` checks full NAME/RESOURCE/REASON/raw-target values, per-field row detail recovery and Runtime CLI semantic parity. `TestPickerProfilesUseExactCatalogFieldOrder` pins both catalog projections. `TestColumnPickerProfileSettingsAndNativeStateParity` covers the two canonical catalog actions, default Alt-W and a plain single-key Settings override, effective footer keys, query/selected-value restoration, compact-wide-compact transitions, reopen reset and zero keymap writes. `TestColumnPickerToggleDoesNotObserveOrWriteAgain` exercises both command loops, including empty filtered results, and proves unchanged row cardinality/order/search plus no extra tmux observation or runtime writes. L13 and L14 drive both toggles through attached real tmux clients and retain exact popup-process completion and zero-Registry-write checks. Installed isolated 80x24/120x30/180x40 plus 184-column smoke observes compact visibility, expected narrow wide clipping and detail/JSON recovery. The historical 142-cell Registry and 120-cell Runtime rows are representative measurements, not arbitrary-data upper bounds; current actions and free text may widen them. The former picker truncation helpers and all NAME/RESOURCE/RUNTIME/REASON bounds are removed; the source PROGRESS policy, footer rendering, provider vocabulary, CLI/JSON/scalar projections and identity authority are unchanged. [Column profiles](column-profiles.md) describes the open-lifetime control and recovery contract.
|
|
155
|
+
- `make test` / `make test-integration` / `make test-e2e`: Default resource AGE Phase 0 extends only the four Registry CLI compact lists to `NAME STATUS ACTIONS AGE`. `TestGetListDefaultAgeMatchesWideAtFixedClock` compares default/wide cells on the same row and injected clock for every kind, covering second/minute/hour/day boundaries, long ages, future creation stamps, missing `createdAt`, and repeated reads. `TestResourceTableDefaultAgeUnavailableIsEmpty` keeps absent resources and absent clocks as empty AGE cells in both profiles. `TestGetListDefaultProjectionIsColumnar`, `TestResourceTableColumnsAreTheCanonicalContract`, and `TestGetReadFamilyResolvesEveryKindWithListCardinality` pin the default table/header contract. `TestColumnProfilesDoNotSelectFromWidthAndWideIsUnbounded` retains AGE at COLUMNS 40/80/112/120 with byte-identical default output; resource CLI tables retain content width and can wrap on narrow terminals. `TestColumnProfilesExactOutputAndSnapshotParity` changes only four compact golden sections and freezes wide, JSON, metadata, scalar and runtime output; `TestColumnCatalogCompletenessBijectionAndExactProfiles` preserves the other three surfaces. Existing empty-list and scoped-row guards remain active. Integration and E2E compact recovery assertions accept the fourth AGE column. AGE still uses the existing `resourceAgeCell` and `i18n.FormatDuration` calculation.
|
|
137
156
|
- `make test` / `make test-integration` / `make test-e2e`: Route-implied kind omission changes only the four Registry CLI compact lists to exact `NAME STATUS ACTIONS`. `TestColumnCatalogCompletenessBijectionAndExactProfiles` and `TestGetListDefaultProjectionIsColumnar` reject compact KIND reinsertion and wide/mixed KIND removal. `TestCompactResourceKindOmissionPreservesScopedRowsAndRecovery` covers all four routes with unscoped, all-projects, Project, Window and exact-Pane selectors where supported, including empty results, ordered UID sets, full NAME/STATUS/ACTIONS parity and wide/JSON kind recovery. Each fresh read runs `assertColumnReadCounters` (one Registry load, four existing tmux queries, zero Registry transactions/writes and zero sibling calls). `TestColumnProfilesExactOutputAndSnapshotParity` keeps the wide/JSON/metadata/scalar/runtime byte goldens and ACTIONS snapshot fixed; only four compact golden sections change. `TestMixedPickerProfilesRetainKindCells` verifies every mixed Registry/Runtime row retains KIND in both profiles; the existing toggle, query/selection, 80-column and detail-recovery guards remain active. Integration checks the restored Window's compact/wide/JSON cells; L06 repeats four-kind nonempty/empty default/wide/JSON recovery on real tmux and compares Registry bytes. This stdout change moves NAME, STATUS and ACTIONS one position left and can break positional parsers; wide and JSON retain kind.
|
|
138
157
|
- `make test`: Resource timestamps surfacing Phase 0 timestamps in read surfaces: the registry has always stored `metadata.createdAt` on every resource, `Condition.firstObservedAt`/`lastTransitionAt` on every observed condition, and `Agent.status.lastTransitionAt` on every Agent, and `-o json` has always emitted them -- but no human-facing surface printed a single one of them, so `describe pane` carried zero time rows and the columnar `get` carried no `AGE`. Both now render, and nothing new is collected: no tmux query, no schema field, and no second relative-time implementation. The plural reads gain an `AGE` column, last on all four kinds because that is the one column whose width moves with the clock and last is the only position where growing it cannot walk an owner-chain column sideways; it is rendered through `i18n.FormatDuration`'s compact form, the same single implementation `notify list` already renders its own AGE through. `internal/app` pins the arithmetic as a boundary table asserted from both sides of every unit rollover (`59s`/`1m`, `59m`/`1h`, `23h`/`1d`, up to `900d`), plus the three cases that render an empty cell rather than a number -- a uid that has left the registry, a resource stored before `createdAt` was stamped whose zero Time would otherwise date it to year 1, and a caller that passed no clock -- and a whole-table golden spanning `9s`/`47m`/`6h`/`11d` in one read, which is also the alignment case because the widest cell sets the column. Determinism is stated as a two-sided claim rather than a single assertion, since only the pair is falsifiable: the same injected clock twice must be byte-identical (which a renderer ignoring the clock would also satisfy) **and** a clock advanced three days must produce a different table (which a renderer reading `time.Now` would fail), so only a renderer reading the passed-in clock and nothing else survives both. The clock reaches exactly one projection: `writeResourceProjection` takes it as an explicit parameter and the singular call sites (`get pane`, `describe`, `rename`, and the create fan-out, whose default projection is the `<kind>/<name> created` line and never the table) pass the zero Time, which `resourceAgeCell` renders as no age at all rather than as "created exactly now". `describe` gains absolute UTC instants instead: a `CreatedAt` row beside the identity rows on all four kinds, `PhaseSince` under an Agent's phase, and the second half of a condition's stored pair (`lastTransitionAt` beside the `firstObservedAt` that was already there), each omitted when the registry file predates the field so a pre-`createdAt` registry keeps its exact current block. The timestamp machine-consumer contract is frozen the whole way: `-o uid|name|ref|none|metadata` remain byte-identical, and the durable portion of plural `-o json` remains exact around the later Columnar Phase 0 context sibling -- both current whole documents are pinned rather than substring-matched, so a timestamp key anywhere still reddens. The Columnar track's `describe pane` byte-golden moves by exactly one row and keeps its own purpose intact: what it guards is that the columnar table is reachable only with `list` true, and a header line or a padded column in a singular route still reddens it.
|
|
139
158
|
- `make test`: Settings IA re-cut Phase 0 full navigation cutover: the visible Settings tree is declared once in `internal/app/settings_nav.go` and frozen by `internal/app/testdata/settings-nav-tree.golden`, so an IA change is a golden diff rather than a shape spread across the section loops. Structural tests prove the catalog is a tree (unique ids, resolvable parents, a scope root at the top of every path), that every control hangs off exactly one owning `[View]` and that only a View owns children (row-affordance exclusivity), and that each rendered picker value maps onto exactly one navigation node whose owning loop the closed reachability table actually handles (control-owner cardinality); the drift guard runs in both directions, so a section loop cannot grow a row the golden does not show. The removed-path negative guard proves `Labs`, the separate `Theme` root, `Project recipe` and `Effective merge view` are neither rendered, nor catalogued, nor routable through `runSection` — the retired handlers, action metadata, and i18n entries are absent rather than hidden redirects — and the legacy-copy guard rejects the retired vocabulary (`AI Settings`, `Project Picker`, `Project Root`, `Workdirs`, `Enabled agents`, `Default split mode`, `Resume picker`, `Session State`, `Kill Session`, `New window`, `Hook quiet policy`, `Delivery sources`, `Labs`, `Usage HUD`, `Path icon`, `Notify icon`, …) across navigation labels, rendered rows and keymap display labels, in both locales. Display renaming is proven display-only: the keymap action IDs (`new-window`, `Sidebar:KillSession`, `ai-split-right`, …), the `sessionstate:`/`project-hooks:`/`live-resources:`/`statusbar-decoration:`/`workdir:`/`projdir:`/`switch:`/`keymap:`/`theme:` action spellings and their owner contracts are all unchanged behind the renamed rows. Keybinding navigation is category-based: an exhaustiveness test requires every catalog action to carry exactly one explicit category (never an ID-prefix inference), every surface action to sit in the sidebar/picker category with a display label for its surface, one display label per action, and each action to render exactly once across the rendered categories, while the category rows carry their members' action IDs, labels, chords and state so search still crosses the category boundary. The action detail projects the product semantics the target IA asks for — target kind, result kind, placement and anchor — and pins that every interactive right/down split declares the explicit current-Pane anchor and a right/down placement, that `Create <Provider> Agent` is always-new, and that resume names the existing `Offline`/`Failed` Agent it rebinds. Navigation is proven side-effect free (opening the root, every section and every container writes no config and runs no tmux command), every `[State]` row carries the catalogued passive value so Enter can never fall through, and the promoted rows keep their old state at the new route (Resources reads the same `live-resources` file it read from Labs, the project automation policy the same `project-hooks` file, Theme the same global `[theme]` block through `Appearance > Theme`). The pinned Project item view keeps Project identity separable (display name, unique name, uid, bound root, condition, missing-since, runtime) and offers same-uid remediation through the canonical `rebind project` route instead of re-pinning, with the unregistered-path case rendering a disabled rebind row carrying its reason. The Agent Usage HUD ownership guard keeps `agent usage` canonical: no Settings row spells a `Usage` resource or a `get usage` read, and `docs/settings-ia.md` names the owner.
|
|
@@ -169,6 +188,8 @@
|
|
|
169
188
|
- `make test` also covers keybinding surface tier catalog rules, action-centered `keymap.toml` `keys = [...]` multi-alias parsing/writing, quoted internal `Surface:Action` tables, legacy popup action ID aliases, canonical popup toggle names, AI split popup-vs-direct action labels, generated tmux config multi-alias rendering, global/direct conflict detection, surface-scoped native picker command conflict detection, Settings Keybindings list/search/detail surface-aware picker-local labels, compact action-list state copy, flat single-key/sequence action detail rows, key detail remove/test/replace rows, one visible Add binding flow, and one typed binding surface; the unified native recorder's 0–4 stroke reducer, length-driven single-versus-sequence save, empty Enter/Backspace no-op, last-stroke pop, Esc zero-mutation cancellation, four-stroke cap, continuous native byte-stream comma draft rendering with canonical space-form results, conflict retry, and one-reader/no-event-leak lifecycle; capture/typed comma-or-legacy-space normalization and byte-identical save/apply output, atomic single↔sequence replacement, comma list/detail/diagnostic display with space route/disk/runtime parity, and negative guards against the retired Add sequence, Record next stroke, selectable stroke-remove, and Sequence Editor authoring routes; the reserved Enter/Escape/Tab/Backspace/Delete/navigation base-key classifier across tmux aliases and modifiers, identical capture/typed/final-save rejection before schema/file/config/live-tmux writes, later-printable and first-stroke/raw/conflict parity, shipped PlainChord/PlainChords/PrefixChord/Sequences protected-action inventory, reasoned whole-editor read-only rendering, forged dispatch/direct-helper no-write, retained delivery tests/navigation, and existing schema-v2/default/runtime parse-render-bind parity; collapsed Troubleshooting entry copy, Settings delivery diagnostics that split logical key/raw bytes/tmux received key while distinguishing missing, ambiguous, adapter-needed, and delivered states, safe direct key pool and risky/reserved diagnostic-only copy, Projmux-owned Ghostty/Windows Terminal advanced delivery copy, raw escape/CSI-u/xterm modified/UserKey/UserSequence rejection from primary keymap storage, Labs compatibility redirect to the Keybindings root, existing macOS capture/add-key flows, unsafe raw capture, reset behavior, stale guide docs guards, and welcome/runtime footer copy that avoids hardcoded launch-key guides.
|
|
170
189
|
- `make test` also covers known retired live no-prefix cleanup for the old `C-t` pane-label binding: cleanup renders before current binds, explicit current `C-t` reassignment wins, repeated apply is byte-idempotent, and unrelated bindings remain unchanged. `TestTmuxApplyRetiresStalePaneLabelChordAndMigratesKeymapOnce` additionally pins that the first apply migrates the keymap to `schema_version = 2` and the second writes no bytes and leaves exactly one backup.
|
|
171
190
|
- `make test` / `make test-integration` / `make test-e2e`: keymap multi-stroke Phase 0 pins v2 `sequences` parse/render/merge, marker-only v1 migration with pre-v2 backup and rollback, repeat no-op bytes, deterministic two-to-four-stroke trie/table generation, shared prefixes across standalone/app actions, duplicate/strict-prefix/single-first-stroke conflict rejection, rejection of the undeliverable `C-m`/`C-i`/`C-[` spellings a terminal reports as `Enter`/`Tab`/`Escape`, unsafe and picker-local/command/output/default-sequence negatives, apply-ordered retire of the recorded roots/tables strictly before `source-file` (the generated config records that state but never removes it, because a `run-shell` loop is not ordered against a sourced file), native modified-stroke transport allowlisting without independent dispatch, and zero-write config/live failure ordering. The isolated real-tmux paths prove single dispatch for shared-prefix `mouse.toggle`/`window.create`, Escape and unknown continuation cancellation to `root` with zero raw pane input, terminal and native `send-keys -K -c` logical-stream parity, repeated apply idempotence, sequence removal cleanup, and unchanged single-chord behavior.
|
|
191
|
+
- `make test` / `make test-integration` / `make test-e2e`: Orphaned Registry Window Phase 2 managed close keys route the app config's `prefix x` and `prefix &` through canonical delete. `TestManagedDeleteKeyBindingsRenderMirrorGuardedCanonicalRouteWithStockFallback` pins the app-scoped `pane.delete`/`window.delete` catalog actions and their exact `if-shell -F "#{@projmux_pane_uid}"`/`"#{@projmux_window_uid}"` bindings: the mirrored branch is only `internal tmux delete-confirm`, the else branch is tmux 3.6's stock `confirm-before` body byte for byte, and the standalone snippet keeps both keys stock. `TestManagedDeleteKeymapChangeAndDisableReachGeneratedConfig` moves and disables them through `keymap.toml` `prefix`, adds a root key through `keys`, rejects two managed actions on one prefix key, and proves a vacated stock key is unbound and then re-bound to tmux's stock body before any managed bind. `TestManagedDeleteCatalogSurfaceRowsMapBothDirections` ties `catalog.pane.delete`/`catalog.window.delete` to `mutationKillPane`/`mutationKillWindow` in both directions. `TestTmuxDeleteConfirmIssuesOneLocalizedPromptToTheExactClient` issues exactly one en-US/ko-KR `confirm-before -b -t <client>` whose command is the Pane menu Kill route or `internal tmux window-delete` with the press-time anchor, performs zero deletes before the answer, and resolves to one guarded route and one runtime ledger row; `TestTmuxManagedDeleteIntentsRefuseMalformedArgvWithZeroTmuxCalls`, `TestTmuxWindowDeleteIntentReportsCanonicalResultToTheExactClient`, and `TestTmuxWindowDeleteIntentRefusalIsShownWithoutRawFallback` cover the canonical Window intent. `TestDefaultCatalogManagedDeleteConfirmParity` holds en/ko parity for the Registry deletion and the Agent-does-not-return-on-Continue impact. `TestGeneratedWindowLifecycleActionsReachTypedHandlersWithoutRawManagedVerbs`, `TestGeneratedCatalogMutationAndNavigationArtifactsHaveOneSurfaceRow`, and `TestFullRenderedTmuxConfigsHaveClosedGeneratedMutationSurfaces` now admit `kill-pane`/`kill-window` only as those exact stock bodies, counted per rendered config including a close-key override config. The integration smoke reads both applied `list-keys -T prefix` bindings. The e2e pane-menu leg presses `C-b x`/`C-b &` with `send-keys -K` on the attached client for a managed Pane, an unmanaged Pane, a managed Window, a stale-mirror Window refusal, and the Project's last Window. Raw-kill `killed` retention, Continue, and teardown tests are unchanged.
|
|
192
|
+
- `make test` / `make test-integration` / `make test-e2e`: Orphaned Registry Window Phase 3 routes tmux's stock menu Kill entries for managed resources through canonical delete. The app config unbinds and replaces tmux's stock `prefix <`, `MouseDown3Status`, `M-MouseDown3Status` Window menus and `prefix >`, `M-MouseDown3Pane` Pane menus; the standalone snippet keeps all five stock. `TestManagedStockMenusRenderInAppConfigOnlyAfterUnbindingTmuxStock` pins that scope, unbind-before-bind, the unchanged `MouseDown3Pane` in both configs, and that a keymap-assigned `prefix <` still wins. `TestManagedStockMenusKeepTmux36ItemsExceptManagedRoutes` parses tmux 3.6's stock menus spelled as literals and requires every generated item to equal them except Kill (`if-shell -F "#{@projmux_window_uid}"` to `internal tmux window-delete` with no `delete-confirm`, or `"#{@projmux_pane_uid}"` to the Pane menu Kill route, each with tmux's stock `kill-window`/`kill-pane` as the else branch), Rename (`internal tmux window-rename`), New At End (`internal tmux window-create`), Horizontal/Vertical Split (`internal tmux pane-menu split-right|split-down`), and the removed Respawn and New After. `TestManagedMenuKillCarriesTmuxKillOnlyAsTheMirrorAbsentBranch` holds all six Kill items, including `MouseDown3Pane`, whose unmanaged Kill now runs tmux's kill instead of refusing. `TestManagedWindowMenuRunsTheCatalogCreateAndRenameCommands` ties New At End and Rename to the catalog renderer and proves the Rename prompt template is `##`-escaped: measured on tmux 3.6, a menu item is format-expanded when the menu opens, and an expanded `%N` Pane handle in a `command-prompt` template is a response placeholder. `TestGeneratedPaneMenuArtifactsHaveOneClosedSurfaceRow` maps every item of all six menus to exactly one `window-menu.*`/`pane-menu.*` surface row and back, admits `swap-window`/`swap-pane`/`resize-pane` only as the exact stock presentation items and `kill-window`/`kill-pane` only as the Kill else branch; `TestFullRenderedTmuxConfigsHaveClosedGeneratedMutationSurfaces` counts those per rendered config. `TestGeneratedPaneMenuGolden`, `TestGeneratedPaneMenuOmitsRawTmuxMutationVerbsAndRespawn`, `TestTmuxPrintConfigBindsPaneContextMenu`, and the `TestBrightPhase2GeneratedConfigByteIdentity` digests change only for the Kill guard and the new menus. The run-shell ledger adds a `window-menu` surface. The integration smoke reads the applied `list-keys` of the five menus and `MouseDown3Pane`. The e2e pane-menu leg drives the real menus on the attached client with `send-keys -K` and SGR right-clicks: `prefix <` New At End, `MouseDown3Status` Rename and Kill on a non-current managed Window, `M-MouseDown3Status` Kill on an unmanaged Window with the Registry unchanged, a stale-mirror refusal with no raw kill, `prefix >` Horizontal Split and `M-MouseDown3Pane` Kill on a non-active managed Pane, `MouseDown3Pane` Kill on an unmanaged Pane, and a second Project's last Window leaving a zero-Window Project.
|
|
172
193
|
- `make test` / `make test-integration` / `make test-e2e`: keymap multi-stroke Phase 1 Settings authoring pins one shared 1–4 stroke Add/replace recorder, picker-local sequence exclusion, en-US/ko-KR locale and navigation golden reachability, shared reserved-key policy with first-plain rejection and later-plain acceptance, typed/captured canonical v2 keymap and generated-config byte parity, length-driven single/sequence add and atomic cross-kind replace plus strict-prefix conflict recovery, saved/prepared/running-session reporting including no-live-tmux recovery, native-macOS-on/off versus Linux/WSL logical authoring parity with transport differences confined to Delivery diagnostics, and zero keymap/generated-config/live-server mutation from navigation, cancellation, Backspace editing, or delivery tests.
|
|
173
194
|
- `make test`: Settings IA re-cut Phase 3 versioned keymap action-ID migration. The action catalog carries a `CanonicalID` beside the runtime `ID`, and `keymapActionManifest` derives the exhaustive old→canonical table from it, so `TestKeymapManifestCoversEveryCatalogActionExactlyOnce` fails on any action without a v1 spelling or any manifest row that resolves to no action, `TestKeymapCanonicalIDsAreUniqueAndDistinctFromLegacyIDs` rejects a canonical id that duplicates another action's canonical or legacy id, `TestKeymapRetiredIDsAreDisjointFromTheManifest` keeps retired ids out of the rename table and requires a remediation for each, `TestKeymapCanonicalIDsUseTheDottedSchema` pins the dotted lower-case shape and that the writer quotes it, and `TestKeymapDispositionIsExactlyOnePerTable` proves every table gets exactly one of canonical/coalesce/preserve-unknown/retired-remediation. Parser coverage adds the root `schema_version` marker with duplicate, forward-version and unknown-root-key refusals, and rejects an unquoted dotted table because that is a nested TOML table rather than a dotted key (`TestKeymapV1FileParsesAndRoundTrips`, `TestKeymapRejectsUnquotedDottedTableAndFutureSchema`). `TestKeymapMigrationPreservesEffectiveBindings` migrates a fixture carrying a custom multi-alias, `keys = []`, a transport-dependent additive alias, a legacy `plain` and a legacy `prefix` and requires the merged chord table to be identical before and after. The apply half is covered by `TestKeymapMigrationCoalescesIdenticalDualTables`, `TestKeymapMigrationRefusesConflictingDualTablesWithZeroWrites` (no keymap write, no backup, no tmux call), `TestKeymapMigrationPreservesUnknownTables`, `TestKeymapMigrationRepeatRunIsAByteWriteFreeNoOp` (unchanged bytes *and* unchanged mtime), `TestKeymapMigrationOnAbsentFileIsANoOp`, `TestKeymapMigrationBackupIsDigestNamedExclusiveAndReused`, `TestKeymapMigrationRefusesToClobberAForeignBackup`, `TestKeymapMigrationFailsClosedWhenTheDirectoryIsReadOnly`, `TestKeymapMigrationPreservesFileModeAndSymlinkTarget` (writes through the link, keeps 0600), `TestKeymapRollbackRestoresV0` and `TestKeymapRollbackRefusesACorruptBackup`. Convergence and the write boundary are pinned by `TestSettingsKeySaveConvergesAV0KeymapToV2`, `TestSettingsKeySaveAbortsWhenMigrationConflicts` (Schema/Saved/Prepared/Running-session stages), `TestTmuxApplyRefusesToApplyWhenTheKeymapMigrationFails`, `TestTmuxApplyNoReloadMigratesWithoutTouchingTheServer`, `TestConfigRenderReportsMigrationOnStderrAndWritesNoKeymap` (the preflight never reaches the generated artifact on stdout) and `TestReadOnlyRoutesNeverRewriteTheKeymap`, which drives the real dispatcher against an isolated HOME/XDG for `help`, `version`, `get`, `describe`, `agent usage`, `doctor --help`, both `config render` artifacts and `update apply --dry-run`. `TestUpdateDryRunPreviewsTheMigrationStageWithoutPromisingADiff` requires the preview to name the stage and leak no canonical id, and `TestPostUpdateApplyArgsAlwaysReachTheNewBinary` pins that `--no-apply` becomes `config apply --no-reload` so an installer suppresses the reload without skipping the migration. `TestKeymapAndRegistrySchemaMarkersAreIndependent` and `TestKeymapMigrationFailureLeavesTheRegistryUntouched` keep the keymap `schema_version` domain separate from the resource registry `apiVersion`/`schemaVersion` envelope, with separate backups and no shared transaction.
|
|
174
195
|
- `make test`: Go updater exact-target atomic replacement. `update apply` on the `go` backend no longer runs `go install` and then converges with the path it resolved beforehand: it stages a scratch `GOBIN` beside the active executable, publishes into it, checks the artifact is a regular executable file, replaces the exact active executable through the same `atomicBinaryReplacer` the github-release backend uses, and runs the post-publication `config apply` against that replaced target. `TestUpdateApplyGoReplacesTheExactActiveExecutable` requires the target file to hold the published bytes for both `apply` and `--no-apply` and names the replaced path in the output; `TestUpdateApplyGoPublishesIntoAScratchGobinBesideTheTarget` pins that the publication carries exactly one environment entry — an absolute `GOBIN` that is a sibling of the target, so the user's real `GOBIN` is never written and the rename stays within one filesystem; `TestUpdateApplyGoRefusesArtifactsThatAreNotRegularExecutables` covers a missing artifact, a directory, a symlink and a non-executable file, and requires the target untouched, the scratch removed, and no post-publication convergence; `TestUpdateApplyGoCleansScratchAndLeavesAUsableBinaryOnEveryFailure` walks a missing toolchain, a failing `go install`, a failing replacement and a failing convergence, requiring the recovery command in every message and either the old or the new binary at the target, never a partial write; `TestUpdateApplyGoDryRunReplacesNothing` pins the preview lines and zero execution; and `TestRunUpdateExternalWithEnvLayersOverTheCallerEnvironment` holds the memoization boundary by requiring `PROJMUX_PROJDIR` to reach the child alongside the `GOBIN` override. `TestUpdateApplyRunsGoUpgradeInPublicationOrder` and `TestUpdateApplyRunsGoUpgradeNoApply` keep the published stage order unchanged.
|
|
@@ -252,6 +273,8 @@
|
|
|
252
273
|
- Picker focused unit coverage includes native picker item/action mapping, direct native routing with no backend selector, stale selector env/file non-observation without lookup/delete/rewrite/propagation, native title-focused filtering, numeric selection, shared close actions including raw native custom actions, fuzzy-score reference fixtures, AI picker title chrome and stable search-key ordering, Settings title chrome and root section order, Settings Labs without picker source or hidden keybindings rows, compact multi-line metadata gutters with one-column-indented metadata, proportional native scrollbar thumb rendering, native row width clamps that preserve ANSI resets and Korean/wide-cell frame geometry with matched scrollbar/no-scrollbar row budgets including Settings > Appearance AI badge preview rows and parent long emoji preview rows, native app-background and semantic selected/muted/accent/warning/critical role coverage for fallback/effective themes across content padding, empty no-footer rows, footer rows, scrollbars, split-preview gaps, reset-to-padding continuation, and Korean Settings > Appearance AI badge style chips/prompt/emoji rows, multiline partial next/previous item row rendering with rendered-row scrollbar units, fixed split-preview and sidebar list viewports with scrollbar tracks, native Up/Down and Ctrl-N/Ctrl-P navigation wrap with empty-list safety and PageUp/PageDown/Home/End clamp regression coverage, native mouse down/follow-drag/release behavior, deferred native row updates that preserve filter/selection state and can repeat from event triggers, preview tab/control normalization before width clipping, optional native frame titlebars without same-line rule fill and with title/chip gap inheritance guards, titled Alt-1 sidebar chrome, statusbar-preserving sidebar popup height, compact project sidebar popup sizing, cheap Alt-1 first-paint rows with deferred git/window/attention/preview enrichment, fixed three-line Alt-1 sidebar row geometry across cheap/enriched paints, bulk switch existing-session classification with per-candidate fallback, and notify sidebar title/popup sizing.
|
|
253
274
|
- Picker/setup lifecycle coverage includes deferred native key-reader stop and repeated reopen cleanup, plus per-probe controlling-TTY cleanup and timeout-then-next-key reads without stale goroutines stealing input.
|
|
254
275
|
- Doctor focused unit coverage includes tmux required/stale behavior on every host, Windows `stty` skip behavior, and tmux bell fallback diagnostics.
|
|
276
|
+
- `make test`: Codex endpoint diagnostics C-1 is enforced by `TestDoctorCodexEndpointMismatchExactActivationSet` (mismatch/match/mixed/empty and installed-CLI skew), `TestDoctorCodexEndpointMismatchIncludesBoundNonRunningActivation` (current activation scope), `TestDoctorCodexEndpointMismatchSignalsEnumerationGaps` (missing/orphaned/conflicting activation, foreign/opaque endpoint and unavailable observations), and `TestDoctorCodexEndpointMismatchDoesNotGuessPrivateGenerationRouting` (version-shaped private IDs and unknown pool routing). `TestDoctorCodexEndpointMismatchTextJSONSupportParity` and `TestDoctorCodexEndpointMismatchPartialEnumerationParity` require exact Doctor UID sets, support-hashed identity parity, visible partial enumeration, 2026-09-09 n=1 observed risk with undetermined causality, and no mismatch block for a complete matching census. `TestDoctorCodexEndpointMismatchSupportAllowlistIsScoped` preserves support redaction. `TestDoctorCodexEndpointMismatchReadOnlyArgvAudit` exercises the production Doctor/support probe against an isolated failing proxy, requires visible incomplete enumeration and only `app-server proxy`/`app-server daemon version` argv, and preserves the Codex state tree; it never reaches live app-server, broker, or supervisor processes.
|
|
277
|
+
- `make test`: Codex endpoint diagnostics C-2 is enforced by `TestOperatorRecoveryGuidanceOwnershipMatrix`: unmanaged current, skewed, and unknown-version endpoints name `codex app-server daemon bootstrap` and the observed `pid` backend's need to bootstrap again after reboot; managed and unknown ownership omit that prescription, with readiness/refusal/recovery codes unchanged. `TestDoctorCodexRecoveryGuidanceTextJSONSettingsSupportParity` requires Doctor's bounded sentence and the existing Settings/Doctor JSON/support recovery code to agree without a schema change. `TestOperatorRecoveryGuidanceReadOnlyArgvAndState` exercises repeated Doctor/Settings/support triggers against an isolated ready unmanaged proxy, allows only `app-server proxy` and `app-server daemon version` argv, and preserves Codex state byte-for-byte; recovery execution argv is zero. `TestProductSourceHasNoSharedDaemonStopRestartOrKillArgv` also forbids bootstrap argv in the product source. The reboot observation makes no claim about other backends' boot persistence.
|
|
255
278
|
- Shell focused unit coverage includes canonical typed Project/ControlSession bootstrap followed by the non-creating foreground route `tmux -L projmux -f <generated config> attach-session -t =<session> [-c <cwd>]`; disappearance after preflight fails closed instead of letting `new-session -A` provision outside the plan. Generated tmux config callbacks, native key-broker platform policy, runtime overrides, and nested-socket guards remain covered.
|
|
256
279
|
- `make test` also covers npm retire/staging path canonicalization for the resolved projmux executable so generated tmux config and hooks never embed a `node_modules/.projmux-<hash>` directory, plus error-suppressed attention and rebalance-panes hooks.
|
|
257
280
|
- `make test` also covers the public config spelling: `projmux config edit [--get|--set <mode>]`, `config render standalone|app`, and `config apply` forward raw argv to their manual leaf handlers; flags, unknown tokens, streams, handler errors, and side effects stay on those handlers. `make install` and every update path emit `projmux config apply`, while generated plumbing uses only the hidden `internal` namespace.
|
|
@@ -270,7 +293,8 @@
|
|
|
270
293
|
|
|
271
294
|
- `make test` / `make test-integration` / `make test-e2e`: Registry-first control plane Phase 8 termination evidence transport binds a managed process's real exit to the Pane it ran in. `internal/core/metadata` adds the per-materialization `status.activation` generation and the optional `status.lastTermination` receipt on Pane and Agent, and its tests pin the closed classification vocabulary (exit 0 is `normal` and never `intentional`; non-zero and signal are `abnormal`), the generation guard across replaced generations, deleted Panes, a shell Pane claimed by an Agent and an Agent that no longer binds the Pane, the byte-identical duplicate no-op, intent recordable only by `source: control-action` and sticky against the signal a deliberate delete causes, the operation-id-scoped withdrawal that refuses to clear another operation's receipt, the generation-guarded runtime handle, and a registry stripped of both additive blocks that decodes, validates, re-encodes byte-identically, and rejects a receipt for a Pane that never carried a generation. `internal/app` adds the hidden `internal supervise` route: the argv builder terminates its own flags with `--` so an operator payload spelling `--pane-uid` cannot be re-read as one, a shell Pane with no command of its own is supervised over tmux's documented `default-command`/login-`default-shell` rule read from the same exact server, and every failure to construct a supervisor -- an unresolvable binary, an unreadable tmux default, a Pane with no generation -- returns the caller's original command so the pane still starts with no receipt rather than not starting. The route's tests pin the recorded wait status for clean exit, non-zero exit, and signal with the matching `128+signum` exit status, a registry that cannot be written costing the evidence and never the pane's own status, a stale receipt reported and dropped, a usage refusal that starts no child, and a launch failure reported as a launch failure rather than a termination. `runSupervisedChild` is exercised against real `sh` children for all three wait statuses and for argv/cwd/environment parity. Create, create-window, create-agent, `agent resume`, and the topology materializer each issue their own generation before the launch argv is built, and a route-level table proves every launched pane quotes the generation the Registry stored for it, that a fan-out never repeats one, and that a receipt from the process a resume replaced changes nothing. `delete window|pane|agent` gains `--socket`/`--socket-path` and now resolves exactly one server from those flags or the inherited absolute `$TMUX`, refusing outside tmux instead of falling back to `-L projmux` -- which supersedes the `-L projmux` inventory the Window and Pane/Agent deletion entries above describe -- and it commits its intentional receipt in its own transaction before the first live mutation, withdrawing it again on every refusal that leaves the processes running. The integration smoke records real shell exit 0, exit 7, and a signal death on an isolated exact socket and reads the receipts back out of an isolated Registry; the e2e smoke drives the same lifecycle against a real tmux server and proves an isolated `delete agent`/`delete pane` dry-run and apply touch only the socket they were given, leaving a sibling socket and the default socket unchanged.
|
|
272
295
|
- `make test` / `make test-integration` / `make test-e2e`: Agent clean-exit and Continue replay policy Phase 0 records Project-stop provenance without changing replay. `TestProjectStopInterruptionPrewriteSelectsOnlyExactRunningAgentsAtomically` requires every and only then-Running Agent-owned Pane in the exact Project to receive matching generation/operation `interrupted/control-action` evidence in one Registry commit. `TestProjectStopFailureCompensatesOnlyWhenExactSessionIsProvedLive` pins same-operation compensation after a proved-live failure and retention after an apply error whose exact Session is proved absent; the existing external-HUP supervision rows remain `killed/supervisor`, and `TestInterruptedControlActionIsCurrentGenerationStickyAgainstLateSupervisorHUP` prevents a delayed HUP receipt from overwriting Project-stop authority. `TestCanonicalV2MigratesToV3WithoutInformationLoss` and `TestCanonicalV2ToV3PublishesOneLosslessBackupReportAndRepeatsNoop` pin the schema 2→3 lossless transform, exact versioned backup/report, one-time write, and newer-schema downgrade refusal. Describe renders classification/source/generation as separate fields and `get` includes all three in its termination cell. Continue planning, explicit resume, Open fresh, snapshot projection, provider argv, and public hooks remain unchanged in this producer-only Phase.
|
|
273
|
-
- `make test` / `make test-integration` / `make test-e2e`:
|
|
296
|
+
- `make test` / `make test-integration` / `make test-e2e`: Continue recovery diagnostics Phase 1 is enforced by `TestTopologyRecoveryTypedReasonDecisionSites`, `TestTopologyRecoveryMixedReasonsReachJournal`, `TestTopologyRecoveryStartupCommittedSummaryAndJournal`, `TestTopologyRecoveryPublicPreviewRepeatAndLockReplan`, `TestTopologyRecoveryFailureNeverRecordsPlannedSuccess`, `TestTopologyRecoveryWriterDisplayFailureAndNoClient`, `TestTopologyRecoverySnapshotRetainsSeparateAuthority`, and `TestTopologyRecoveryReportArchiveIncludesSuccess`. The diagnostics package tests `TestTopologyRecorderCommittedCountsAndOnce`, `TestTopologyRecorderFailureAndInvalidCounts`, and `TestTopologyEventClosedShapes` hold the exact ten reason codes, same-run reason totals, count/event isolation, privacy, and writer failure ownership. Startup tests cover 0/1/9 committed resumed/skipped counts, nine long Korean names, en-US/ko-KR summaries within 220 valid UTF-8 bytes including ellipsis, retained stderr details, public log/report, and no foreign-server display without a client. `TestTopologyRecoveryCanonicalContinueReportsAfterCommit` exercises the canonical zero-Window/no-topology fallback through the real session transaction, requiring no precommit success and exactly one 0/0 success or commit-failure outcome; `TestTopologyRecoverySwitchDoesNotDuplicateMaterializerOrSnapshot` protects existing reporting ownership. L10/L11 retain verified same-run safe events and their exact bounded summary as unique recovery JSON artifacts. L10 reads public materialize results through diagnostics log after each evidence-matrix execution and repeat; L11 reads the actual startup invocation after external HUP, mixed normal/interrupted recovery, and nine missing refs, preserving explicit-resume/snapshot authority and live-open bypass with no duplicate event.
|
|
297
|
+
- `make test` / `make test-integration` / `make test-e2e`: Retained-Project Continue resumes exact stored conversations after unplanned stops. `TestTopologyAgentContinueEligibilityMatrix` covers interrupted/killed/abnormal/unknown/no-receipt × Running/Offline/Failed/Pending with actual exact-resume or zero-launch assertions; intentional and normal remain excluded. `TestTopologyAgentContinueRejectsInvalidActivationEvidence` and `TestTopologyAgentContinueTerminationPairingAndShape` require legal receipt provenance and wait status, matching Agent/Pane evidence, current managed generation/owner, Running's exact paneRef, and Offline/Failed's unique retained activation when evidence is absent. `TestTopologyAgentContinueResumePreparationMatrix` fixes missing/blank/malformed/mismatched refs, normalized IDs, unsupported/disabled providers, missing cwd, and prepare errors at fresh 0 with a reason. `TestRegistryTopologyMaterializationReplaysStoredAgents`, `TestRegistryTopologyContinueLaunchesInterruptedBOnceAndRetainsCleanA`, and `TestClosedProjectStartupContinuesUnplannedStops` require independent shell/Window recovery, abnormal Failed recovery, retained excluded UID/ref/evidence, and repeat duplicate/Registry-write 0. `TestRegistryTopologyContinueRechecksEvidenceUnderLock`, existing owner-guard/binder rollback tests, `TestRegistryTopologyContinueKeepsUnresumableAgentAnchorRefusal`, and `TestRegistryTopologyMaterializationAgentAnchorLazyDefaultShellAndRepeatNoop` retain current ownership and rollback boundaries. `TestTopologyAgentSnapshotKeepsFreshFallback`, `TestExplicitSnapshotRestoreRetainsAgentReplayAuthority`, and `TestExplicitSnapshotRestoredOfflineAgentAnchorConvergesLazyShellAgentAndRepeatNoop` preserve explicit snapshot fresh fallback and exact resume. L10 requires raw Window/server HUP exact resume 1 and deterministic abnormal/Failed, unknown, absent-receipt, intentional/normal, and managed-stop ref-less cases; L11 requires startup HUP resume 1, clean launch 0, managed-stop exact resume 1, repeat 0, and independent explicit resume/snapshot/Fresh parity. Both smokes use isolated HOME/XDG/TMUX_TMPDIR, remove inherited tmux routing, and clean only queried contained sockets. Receipt producers/schema/sticky intent, quit/delete/stop, provider stores/transcripts, prompt/turn/approval replay, and public hooks are unchanged.
|
|
274
298
|
|
|
275
299
|
- `make test` / `make test-integration`: the delete result names the socket the invocation resolved. Phase 8 made `delete window|pane|agent` resolve one exact server from `--socket`/`--socket-path` or the inherited `$TMUX`, but left the result line printing a constant `socket=-L/projmux`, so every delete against any other server reported the wrong target -- and that line is exactly what an operator audits after a destructive command. `explicitTmuxTarget.label()` renders the flag and value the route actually used, a table pins all three resolutions (explicit name, explicit absolute path, inherited client) and fails if the default app socket appears in a result that did not name it, and the isolated integration smoke asserts the reported socket is the run-unique one -- which is the whole assertion, because a fallback would print `-L/projmux` instead, and a separate "must not contain" check would collide with the isolated socket's own `projmux` prefix.
|
|
276
300
|
|
|
@@ -289,7 +313,7 @@
|
|
|
289
313
|
|
|
290
314
|
- `make test`: Declarative contract stabilization Phase 2 adds the Registry materialization invariant audit to `projmux doctor` as the `registry` section, present in the default report and in `--section registry`, in both text and `--json`. The audit is the consumer predicate rather than a second opinion about it: every Registry Project is planned through the shipped `planRegistryTopology` with no observed sessions, and `refusalScope` supplies the fatal/skipped split, so `TestDoctorRegistryInvariantAuditReusesTheMaterializePredicate` fails if the reported counts ever diverge from the planner's own refusals over the same Registry. After schema v2, `TestDoctorRegistryInvariantAuditReportsTheFieldFailureStructure` proves deleting a Window's last shell installs a canonical replacement and therefore emits no skipped-Window finding; the remaining gone-root Project is still reported as `registry.materialize.fatal.project`. `TestDoctorRegistryInvariantAuditStatesTheZeroCase` requires a clean Registry to report `registry.materialize.clean` and the number of Projects planned without `--verbose`, because a silent clean audit is indistinguishable from a section that never ran, and `TestDoctorRegistryInvariantAuditGoldens` pins the zero and N section output in text and JSON. `TestDoctorRegistryInvariantAuditWritesNothing` runs the production zero-write snapshot read under an isolated `HOME`/`XDG_STATE_HOME`/`XDG_CONFIG_HOME` on a machine that never created a Project and requires an unchanged filesystem tree and no state directory; `TestDoctorRegistryInvariantAuditNeverReachesATmuxServer` pins that the runner handed to the planner refuses every call, and `TestDoctorRegistryInvariantAuditDegradesWhenTheRegistryCannotBeRead` keeps an unreadable Registry a `registry.materialize.unavailable` finding rather than a failed diagnostic. `TestSupportReportCarriesRegistryInvariantCountsWithoutReasonsOrPaths` requires the archive's `doctor.json` to carry the same codes, kinds, and counts and neither the planner's reason wording nor the fixture's absolute paths, and `TestDoctorRegistryInvariantCodesStayInsideThePublishedInventory` keeps every emitted code and remediation inside `doctorFindingCodeInventory`/`doctorFindingRemediationInventory` so nothing reaches a support archive as an opaque hash. The audit performs no repair, schema migration, or display-layer diagnosis, and adds no second diagnostic command.
|
|
291
315
|
- `make test` / `make test-integration` / `make test-e2e`: Declarative contract stabilization Phase 3 raises the Registry envelope to schema v2 and ships the atomic v1 → v2 invariant repair. `TestRegistryV2GenerationMigrationGoldens` labels the 0.10/0.11/0.12 source generations and pins raw SHA-256 bytes for every source/output pair while comparing generated output directly to the raw golden bytes and asserting repair and information-loss counts, identity/name/owner/name-reservation preservation, Agent conversation-pointer preservation, graph validity, and a no-op second pass. `TestV1MigrationCreatesCanonicalShellChainForAZeroWindowProject` covers additive opaque Window/Pane creation, and `TestValidV2CanonicalAnchorRoundTripsWithZeroDiff` fixes a valid anchor at zero diff. `TestEveryFirstMigratorLeavesDurableV012RepairAndLossEvidenceOnce` drives normal `Load`, `Update`, and explicit `Migrate` as the first writer and requires one private report adjacent to the exact versioned backup, with that backup's absolute path/SHA-256 and exact repair/loss detail; returned paths match the durable pair where the API returns evidence, and the next migration pass writes zero Registry, backup, or report bytes. Failure-injection rows require a report published before Registry staging to be removed on every failed ordering. `TestMigrateRejectsAnInvalidCurrentRegistryWithZeroWrite` prevents a current-version no-op from bypassing validation, and future/unversioned envelopes remain byte-identical refusals with no evidence report. `TestV012MigrationLeavesNoMaterializeRefusals` runs the shipped materialize predicate over the repaired 0.12 sample and requires zero fatal and zero skipped items plus the exact Project → Window → direct shell Pane chain. Current-schema validation globally enforces that chain, and last-shell deletion installs a replacement bare shell. Phase 15 consumes this canonical anchor as the only identity retained by `Open fresh`; schema-v2 validation remains the pre-commit refusal boundary for an invalid anchor.
|
|
292
|
-
- `make test` / `make test-e2e`: Declarative contract stabilization Phase 5 moves the generated `MouseDown3Pane` Horizontal/Vertical Split and Kill entries onto managed resource intents. The generated-config byte golden fixes the exact `internal tmux pane-menu --client #{client_tty} <action> #{pane_id}` actions, and a negative audit requires zero `split-window`, `
|
|
316
|
+
- `make test` / `make test-e2e`: Declarative contract stabilization Phase 5 moves the generated `MouseDown3Pane` Horizontal/Vertical Split and Kill entries onto managed resource intents. The generated-config byte golden fixes the exact `internal tmux pane-menu --client #{client_tty} <action> #{pane_id}` actions, and a negative audit requires zero `split-window`, `respawn-pane`, and `Respawn` literals in that menu (since Orphaned Registry Window Phase 3 its one `kill-pane` is tmux's stock item as the mirror-absent branch of Kill). Unit tables prove both split directions emit one `agentPaneIntent` with the exact clicked `%N` in `anchorPaneID`, so `createFromIntent` and the popup-origin `anchoredActiveTargetLookup` remain the only scope and mutation definitions; Kill resolves through the same anchor and calls canonical `delete pane`, preserves its full output, and displays its summary on the originating client. Injected create and delete refusals are displayed on that client and trigger no fallback mutation. Respawn is removed from the generated menu and its internal action is rejected; no managed respawn/replace intent is introduced. The isolated real-tmux leg strips inherited `TMUX`/`TMUX_PANE`, uses a run-unique `TMUX_TMPDIR` and socket, audits the installed `MouseDown3Pane` binding and selects Split/Kill actions through a real `display-menu` on an attached client, verifies split uid/Registry visibility and canonical Kill removal/result, and validates then records the exact socket cleanup target under its smoke root.
|
|
293
317
|
- `make test` / `make test-integration` / `make test-e2e`: Declarative contract stabilization Phase 6 makes termination evidence survive the exit boundary without taking the Registry lock. The supervisor writes one bounded JSON row, framed by leading and trailing delimiters in a single `O_APPEND` call to `termination-receipts.jsonl`; the leading delimiter terminates any prior process's partial tail. Controller convergence reads the append snapshot outside the Registry transaction, absorbs generation-guarded receipts before absence projection, tolerates malformed/partial rows without disabling later convergence, and relies on duplicate/stale receipts as no-ops rather than truncating or garbage-collecting the journal. `TestSupervisorReceiptPrewriteDoesNotWaitForRegistryLock` proves the prewrite never enters a deliberately blocked Registry update, `TestMalformedTerminationJournalRowCannotDisableConvergence` pins recovery from a truly unterminated tail, and `TestInvalidTerminationJournalRowCannotDisableLaterValidReceipt` proves a well-formed but contract-invalid row cannot poison later valid evidence. The generated hooks use three distinct reasons: `pane-exited` carries exact `#{hook_pane}` and reobserves only the matching stored activation handle; `pane-killed` carries no invented pane and retains whole-host reobservation; `window-unlinked` carries exact `#{hook_window}` as explicit event evidence while retaining whole-host fresh reobservation. Phase 6 had no persisted runtime/liveness mapping; Phase 3 now persists only the exact last-positive Window owner handles required for causal teardown. `TestLifecycleHookRoutesCarryExactPaneAndWindowEvidence` and `TestWindowUnlinkedRecordsKillEvidenceWithoutPersistedRuntimeState` pin the Phase 6 boundaries and kill-window evidence recording. `TestPaneKilledCoalescedBehindExactPaneExitWidensEveryLaterPass` pins that a narrow pane-exited lease holder widens after any coalesced event and stays whole-host through its final no-op verification, so a kill or different-pane event cannot be acknowledged under the first Pane's selector. `TestPaneExitedAbsorbsLateSupervisorReceiptAfterUnknownProjection` covers the fast-exit ordering where runtime-created first records unknown: exact pane-exited still treats later journal absorption as work, refines the released same-generation Agent's evidence to normal or killed, and repeats with zero transactions; `TestLateSupervisorRefinementNeverFollowsAResumedBinding` keeps a new non-empty Pane binding strictly outside that exception. The closed classification vocabulary adds `killed`: only a supervisor's SIGHUP wait status may claim it, it means external kill rather than intent, and a same-generation `control-action/intentional` receipt remains sticky when the resulting HUP arrives. `TestHookWaitStatusReceiptDecisionTableIsClosed` covers pane exit, pane kill, standalone window kill, last-pane clean exit, paired control receipt, and evidence-free absence; `TestTerminationPairingRejectsUnentitledClaims` proves supervisor cannot claim intent, control action cannot claim observed outcomes, and reconcile can claim only unknown. `FuzzTerminationEventSequencePreservesCanonicalDeleteAndHookRows` fixes the authority boundary over arbitrary event order: canonical delete removes the Pane row and every repeat is byte-identical, while hook-driven observation changes evidence/status, clears the Agent binding, preserves Pane/Agent rows, and a repeated reconciliation opens zero transactions.
|
|
294
318
|
|
|
295
319
|
- `make test`: Phase 6 kill/reap race enforcement keeps external-kill evidence from settling as unknown merely because tmux's 50ms hook beat the supervisor append. `TestPaneKilledWaitsPastHookDelayForSupervisorReceipt` delays the SIGHUP receipt past 50ms and requires killed evidence; `TestPaneKilledWaitRefinesRacingUnknownWithDelayedSupervisorReceipt` starts from a racing reconcile/unknown and requires the same killed refinement. `TestPaneKilledReceiptWaitIsBoundedBeforeUnknownProjection` proves a genuinely receipt-free kill waits only for the fixed bound and then remains honest unknown. Phase 2 extends the same lock-free bounded wait to the exact `pane-exited` activation only: `TestExactPaneExitedReceiptWaitIsBoundedBeforeUnknownProjection` proves a receipt-free timeout still retains the resource with honest unknown evidence, while integration/e2e prove a racing same-generation normal supervisor row enables deletion. The wait reads only the exact-host inventory, Registry snapshot, and lock-free journal before convergence; it takes no Registry write lock, invents no intent, keeps exact pane exit narrowed to its `%N`, and leaves kill/window paths whole-host. At the process boundary, `TestRunSupervisedChildRetainsRelayedHUPEvidenceWhenChildExits129` proves a provider that catches a successfully relayed HUP and exits 129 still records external-kill evidence, while `TestRunSupervisedChildDoesNotInferHUPFromExit129` proves the same numeric exit without an observed relay remains abnormal.
|
|
@@ -316,6 +340,28 @@
|
|
|
316
340
|
- `make test`: Codex native control plane Phase 8 capability and review coverage pins distinct localized default/advanced provider rows; default Codex launch with zero capability-session/readiness calls and zero `--model`/`model_reasoning_effort` overrides; advanced-only hidden/duplicate model removal, supported-effort and closed-modality normalization, boolean-only personality projection, catalog-localized semantic picker labels with provider model/effort/modality data unchanged, paginated `model/list`, connection/version epoch cache invalidation, stale picker refusal, live-session cleanup on pre-plan create refusal, the live picker-to-pre-create session refresh rejecting a removed option, and dynamic `model/list` -> exact launch argv. Advanced discovery failure returns its exact unavailable reason with zero create intents while a separate default launch remains usable. Review tests require one exact Running Agent -> owned Pane -> activation generation -> stored/live thread binding before `review/start`, use one bounded action context, reject incomplete or unknown initial turns, map only a valid initial response to provider-control-plane interaction state, and commit zero lifecycle writes for unavailable, timed-out, mismatched, or replaced bindings. The installed smoke is opt-in through `PROJMUX_CODEX_CAPABILITY_INSTALLED_SMOKE=1`; it closes the discovery context before refreshing the retained live connection. CI does not require a local authenticated Codex daemon or create a disposable provider thread.
|
|
317
341
|
|
|
318
342
|
- `make test`: Codex native control plane Phase 5 makes `account/rateLimits/read` the authoritative Codex Usage source and consumes `account/rateLimits/updated` through one single-lease, demand-bounded read-only watcher. Bucket/malformed/sparse-event goldens pin percent, reset, label, nullable identity, unknown cadence, and row-level isolation. Manager tests require an accepted native event batch to atomically replace only Codex rows, preserve other-provider/backoff state, advance the Codex throttle timestamp, and trigger zero second collector calls in the same HUD invocation. Watcher tests pin single ownership, demand-expiry heartbeat cleanup, failure backoff, sparse-update recovery after malformed events, and a private atomic native-only sidecar that never replaces last-known-good bytes with rollout/fallback provenance. The watcher launch boundary rejects `.test` and `.test.exe` executables before starting a child; the status regression runs repeated calls from the actual Go test binary with zero child starts and all usage state confined to its isolated root. Adapter/CLI/HUD/diagnostics tests keep unavailable and unsupported accounts on the existing rollout lane, all-malformed native batches on last-known-good with a closed stale reason, source/value parity across table/JSON/HUD, and an exact request inventory containing only `account/rateLimits/read` with zero login/logout/config/token mutation.
|
|
343
|
+
- `TestWatchNativeRateLimitsPeriodicReadKeepsQuietConnection`,
|
|
344
|
+
`TestWatchNativeRateLimitsNoEOFFailureIsBounded`, and
|
|
345
|
+
`TestWatchNativeRateLimitsPeriodicReadRefreshesSparseBase` use Go's virtual
|
|
346
|
+
clock to pin the initial read, fixed 30-second same-client reads, two-second
|
|
347
|
+
timeout, busy-notification independence, single pending read, native-only
|
|
348
|
+
publication, validated sparse base and malformed-result last-good retention.
|
|
349
|
+
`TestWatchNativeRateLimitsParentCancelRejectsLateProbeAndEvents` prevents a
|
|
350
|
+
canceled connection's late results or queued events from publishing.
|
|
351
|
+
`TestOwnedProxyCloseIsBoundedWhenPeerDoesNotRead` and
|
|
352
|
+
`TestOwnedProxyCloseUnblocksConcurrentWriterAndReapsChild` fill real owned
|
|
353
|
+
child pipes and require local close within one second, child reap, joined
|
|
354
|
+
reader/writers and concurrent/idempotent Close. Close never waits for a
|
|
355
|
+
WebSocket close frame or its write lock. Only the exact owned proxy is killed;
|
|
356
|
+
its upstream daemon lifecycle is unchanged.
|
|
357
|
+
`TestNativeWatcherProbeFailureUsesExistingBackoff` and
|
|
358
|
+
`TestNativeWatcherDemandExpiryCancelsPendingProbe` distinguish a failed
|
|
359
|
+
two-second probe from parent cancellation. They pin failure timestamps,
|
|
360
|
+
heartbeat removal, lease release, the existing inclusive 30-second backoff,
|
|
361
|
+
next-demand relaunch, and the 15-second demand TTL plus one-second monitor.
|
|
362
|
+
Existing cache freshness, newer-than-store, independent collector/fallback,
|
|
363
|
+
request cancellation/late-response and notification channel lifetime tests
|
|
364
|
+
remain the parity gates; heartbeat alone supplies no connection health proof.
|
|
319
365
|
|
|
320
366
|
- `make test`: Codex native control plane Phase 9 makes the compact Usage identity native-first: label goldens map healthy authoritative app-server rows to exact `Codex`, fresh rollout rows and unknown non-stale provenance to `Codex [fallback]`, and retained last-known-good rows to `Codex [stale]`; en-US/ko-KR narrow statusbar fixtures pin spacing and width. Same-snapshot HUD/table/JSON tests and operations-journal tests preserve exact percent/reset values plus typed source/fallback/stale reasons, while Claude/Antigravity labels, projection order, and Usage semantics remain unchanged.
|
|
321
367
|
|
|
@@ -472,6 +518,9 @@
|
|
|
472
518
|
- `make test`: Codex endpoint broker diagnostics dial the endpoint the runtime published. `observeCodexBrokerRuntime` used to name `DefaultEndpointKey` up front, while a managed runtime publishes under the generation-scoped key its route derives, so `projmux doctor` reported a broker that was listening as `absent / host-unavailable` -- and an operator acted on that answer by terminating a foreign app-server process. The reader now lists the discovery records the state domain actually holds, keeps only those whose announced endpoint derives back to the record that announced it, and dials that set in one stable endpoint order under a single deadline; `Dial` stays the call, because `Ensure` may create the directory, reclaim an artifact, and start a runtime, which would make a diagnostics read a side effect. `TestBrokerDiagnosticsDialTheEndpointTheRuntimePublished` is the machine's exact shape -- a live generation-scoped runtime beside a default-key lock with no socket and no record -- and requires `running`, the generation-scoped key as the observed endpoint, the answering host's runtime identity, a byte-identical state-domain file set across the read, a runtime still serving afterwards, and a second read reaching the same runtime; it fails against the default-key dial. Its mutation audit covers the connection axis and not only the file set, because a dial is itself a connection: two reads must leave zero upstream opens, an unmoved connection epoch, zero bindings and zero upstream connections reported, and host stats -- live sessions, bindings, refusals, draining, endpoint -- back at their pre-read values. `TestBrokerDiagnosticsStayAbsentWhenOnlyAnUnpublishedArtifactRemains` keeps the resting answer and its closed token: a startup lock is not a runtime and neither is a record whose announced endpoint does not derive back to its own filename, so the verdict stays `absent / host-unavailable` with zero published endpoints and no endpoint claimed. `TestBrokerDiagnosticsSelectEveryPublishedEndpointDeterministically` publishes two generations at once and pins the selection rule the reader is allowed to have: a stable ascending endpoint order, the first runtime that answers, both hosts alive after the read, and the same endpoint on a repeat read -- which generation ought to be current stays the generation pool's judgment. `doctor` now prints `Published endpoints: N` and, when one was judged, `observed endpoint: <key>` on every state rather than only on `running`, so `absent` beside a non-zero count is visibly a runtime this reader could not reach rather than a runtime that is gone.
|
|
473
519
|
- `make test`: One oversized answer no longer cycles the Codex app-server control plane. The broker multiplexes one upstream connection across every bound thread, and `codexappserver.Client.readLoop` used to treat an inbound message past the 1 MiB frame bound as a fatal connection error. `thread/read` with `includeTurns=true` returns a thread's whole transcript, so a long-lived Agent's own lifecycle snapshot crosses that bound on its own: the connection died, `Broker.revoke` suspended **every** binding at once, each observer's next epoch re-issued the same read, and the cycle sustained itself -- measured on this machine at 0.86-1.35 connection epochs per second for hours, with `bind` never dipping. The framing layer now reads an over-long message to its exact byte count and drops it, so the stream stays framed; the client answers only the requests that were waiting with `ErrPayloadTooLarge` and keeps the connection; and the broker classifies that as `indeterminate` under its own `payload-too-large` reason rather than collapsing it onto `disconnect-boundary`, because the connection survived and an operator reading the two alike looks for a broker fault that is not there. `TestClientDropsAnOversizedAnswerAndKeepsTheConnection` requires the dropped answer to reach its caller as `ErrPayloadTooLarge`, a following notification to still arrive on the same connection, and the drop to be counted. `TestClientKeepsServingRequestsAfterAnOversizedAnswer` proves the drop is request-scoped by serving the next request on that connection. `TestWebsocketStreamDropsAnOversizedMessageAndStaysFramed` reads the whole message behind a dropped one, which is what a discard that consumed the wrong byte count would break. `TestOversizedAnswerEndsOneMutationAndNotTheConnectionEpoch` holds the blast radius: five oversized answers leave the connection epoch, the disconnect count, the binding count, and a neighbour binding's live fence and stream all untouched. `TestOversizedAnswerIsToldApartFromADisconnectBoundary` keeps the two indeterminate reasons distinct. Beyond the frame bound the message is still refused, because reading it out is itself the denial of service the bound exists to stop.
|
|
474
520
|
|
|
521
|
+
- `make test` / `make test-integration`: Window teardown decision journal Phase 0 records each consumed lifecycle teardown decision at the app layer (never inside the pure core planner) as one closed `topology.teardown.decision` event. `TestTeardownReasonJournalMappingCoversEveryCoreReason` and `TestTeardownVocabularyMatchesCoreDecisionTable` read `internal/core/metadata` source for every `TeardownReason`, `TeardownAction`, and `TerminationClassification` constant and fail on any unmapped or unallowlisted value; the first also round-trips every code through the real store and every conflict reason through its unchanged error bytes. `TestTeardownDecisionEventClosedShapes` and `TestTeardownRecorderAppendsWithoutOutcomeOwnership` pin the closed shape, strict `win-`/`pane-` UIDs, rejection of the new fields on every other family, and best-effort appends that never own the top-level outcome. `TestTeardownJournalCleanLastPanePairRecordsOneDeleteWindow`, `TestTeardownJournalKilledLastPaneRecordsRetainAndKeepsRegistry`, `TestTeardownJournalCleanupRetryRecordsRetainOnce`, and `TestTeardownJournalAuthorityConflictRecordsOneRefusal` run each fixture beside an unjournaled twin and require identical results, errors, and Registry bytes with exactly one decision per evaluation; `TestTeardownJournalWindowUnlinkRecordsFirstWaitAndExhaustion` requires one `retain`/`awaiting-pane-exit` on the hook's first wait, zero during carried causal retries, and one at exhaustion; `TestTeardownJournalKillWindowShapeFirstWaitCarriesWindowPaneAndKilled` drives the real controller body for a `kill-window`-shaped Registry and requires that first record to carry the exact Window UID, Pane UID, and `killed` with unchanged Registry bytes, while `TestTeardownJournalAmbiguousUnlinkSubjectOmitsUIDs` and `TestLifecycleWindowUnlinkAwaitingSubjectOmitsAmbiguousPane` omit any ambiguous UID. The integration termination smoke asserts one `delete-window`/`window-teardown` record for the exact closed Window UID, the first-wait plus exactly one exhaustion record for a replayed unpaired `window-unlinked`, and one `awaiting-pane-exit` record with the exact Window UID for a real `tmux kill-window` whose Window row is retained. Its read-only status/viewer and automatic-path journal line-count windows, which follow hook-driven session stop/unregister/prune closes, exclude only the asynchronously appended `topology.teardown.decision` lines, so any record the measured command itself appends still fails.
|
|
522
|
+
- `make test`: Orphaned Registry Window Phase 1 records the live `$N/@N` of every Window a Project start/Continue topology replay materializes, in the replay commit itself, through the same `ObserveWindowRuntimeBinding` writer a canonical Window create uses. `TestTopologyReplayCommitsLiveBindingForEveryMaterializedWindowOnly` requires the new-session-adopted first Window and the new-window ones to carry their live pair with MissingRuntime cleared at the single replay write, while a Window outside the replay keeps its runtime ids byte-for-byte; `TestTopologyReplayUnderLiveSessionLeavesPresetLiveWindowBindingsUntouched` re-creates a raw-killed first Window under the existing session and leaves every preset-live Window row, including a wrong sentinel binding, byte-identical. `TestReplayedWindowCleanLastPaneExitAndLiveUnlinkDeleteWindowAndJournalOnce` pairs the replayed sole Pane's clean `pane-exited` with the live `window-unlinked`, deletes the Window and Pane, keeps the Project, journals one `delete-window`/`window-teardown`, and shows the stale pre-fix row shape does not pair; `TestReplayedWindowKillWindowRetainsWindowAndJournalsAwaitingPaneExitKilled` keeps a raw-killed replayed Window and journals `retain`/`awaiting-pane-exit` with `killed` and the exact Window UID; `TestReplayedWindowNonLastAgentPaneCleanExitRemovesOnlyPaneAndKeepsAgentOffline` removes only the Agent Pane and keeps the Agent Offline with its conversation; `TestPastOfflineWindowWithUnpairedTeardownEvidenceSurvivesReplayAndOtherPairs` keeps a past offline Window with MissingRuntime and unpaired evidence byte-identical across the replay and another Window's causal pair. Pairing conditions, teardown decisions, and Windows the replay does not materialize are unchanged.
|
|
523
|
+
|
|
475
524
|
## When To Update This List
|
|
476
525
|
|
|
477
526
|
- A feature moves between unit, integration, and e2e coverage levels.
|
|
@@ -672,6 +721,13 @@
|
|
|
672
721
|
now fails closed over separate core, Codex broker, and Codex app-server
|
|
673
722
|
children; the core child preserves metadata, notify, and recent-window
|
|
674
723
|
coverage, and `CIWorkflowContractTest` pins both Codex failure paths red.
|
|
724
|
+
`CIWorkflowContractTest.test_required_unit_job_runs_pinned_deadcode_without_bypass`
|
|
725
|
+
requires the existing `Unit Tests` job to run `make deadcode` with the module's
|
|
726
|
+
pinned Go tool before `make test`, preserving every required job name.
|
|
727
|
+
`test_deadcode_failure_fails_unit_and_test_aggregate` executes the workflow
|
|
728
|
+
commands with a failing scanner gate and rejects failed, skipped, or cancelled
|
|
729
|
+
Unit results in `Test`. `DeadcodeBaselineContractTest.test_stale_current_and_new_finding_are_rejected`
|
|
730
|
+
preserves rejection of new findings; neither deadcode baseline is expanded.
|
|
675
731
|
Required real-tmux L06 owns only the deterministic holder/released-before-
|
|
676
732
|
deadline/waiter convergence guarantee. Eight-way throughput and fairness stay
|
|
677
733
|
outside required acceptance in the explicit stress command documented above.
|
|
@@ -1031,6 +1087,11 @@
|
|
|
1031
1087
|
That token is deliberately not `binding-revoked`: the four close-cause tokens
|
|
1032
1088
|
answer "who closed the stream" and come from the broker epoch, and here the
|
|
1033
1089
|
stream was never closed at all.
|
|
1090
|
+
- `test/e2e/codex-lifecycle.sh` (C01) exercises its actual projection barrier on
|
|
1091
|
+
an inert fixture pane with an already-ready or later-ready level and repeated
|
|
1092
|
+
option hooks before waiting. An atomic claim shared by the level check and
|
|
1093
|
+
hook emits exactly one signal; duplicate `wait-for -S` calls would otherwise
|
|
1094
|
+
lose the pending wakeup. The existing barrier deadline is unchanged.
|
|
1034
1095
|
- `test/e2e/codex-lifecycle.sh` (C01) pins the exact disconnect token at its
|
|
1035
1096
|
disconnect projection barrier and at the reconnect-gap hook comparison. It
|
|
1036
1097
|
waited on the literal `disconnected` before, which was the bucket published
|
|
@@ -1123,6 +1184,17 @@
|
|
|
1123
1184
|
`TestAgentMessageReplyReturnsOnlyToOriginalSourceConversation` pin exact
|
|
1124
1185
|
current-Pane source authority, exact target eligibility before effects,
|
|
1125
1186
|
same-envelope retry without resend, and broker-owned reply correlation.
|
|
1187
|
+
- `TestCoordinationContentLabelsSourceClaimsForBothProviders` pins claimed,
|
|
1188
|
+
unverified source Agent/provider notices, including wrong UID/provider
|
|
1189
|
+
fixtures, while preserving exact routing metadata, untrusted payload, and
|
|
1190
|
+
peer permission and reply boundaries in both provider contents.
|
|
1191
|
+
- `TestAgentMessageSendSourceAnchorAndOmittedFallbackPreserveRouteAndPeerAuthority`
|
|
1192
|
+
pins explicit source anchors, omitted-source active Pane fallback, refusal
|
|
1193
|
+
without an anchor, and unchanged exact routes and peer authority.
|
|
1194
|
+
- `TestAgentMessageSourceAnchorCatalogHelpAndGeneratedDocsParity` pins
|
|
1195
|
+
`--source` usage and its anchor (not caller authentication) meaning across
|
|
1196
|
+
agent/message/send catalog, help, and generated CLI reference sections;
|
|
1197
|
+
`TestGeneratedReferenceMatchesTheCommandManifest` rejects stale docs.
|
|
1126
1198
|
- `TestClaudePrivateProjectionPreservesPublicBoundaryAndAmbiguity`,
|
|
1127
1199
|
`TestLiveClaudeAdapterMapsTerminalResponseKindsWithoutDelivery`,
|
|
1128
1200
|
`TestLiveClaudeAdapterRefusesPublicValidEnvelopeThatExceedsPrivateFrame`, and
|
|
@@ -1136,6 +1208,33 @@
|
|
|
1136
1208
|
terminal-safe output, activation fencing, and deterministic Registry-only
|
|
1137
1209
|
idle, timeout, and stale waits. Codex `delivered` ends at target self-claim;
|
|
1138
1210
|
it does not assert model processing or reply.
|
|
1211
|
+
- `TestCodexCoordinationPushClassifiesNativeOutcomesForSenders` and
|
|
1212
|
+
`TestCodexCoordinationPushExpiresBeforeAnyProviderCall` own the native Codex
|
|
1213
|
+
push outcome table: start success and the `turn-in-progress` steer fallback
|
|
1214
|
+
deliver as `provider-turn-push`, every known zero-write refusal code fails as
|
|
1215
|
+
`codex-turn-push-refused`, every ambiguous or unrecognised code fails closed
|
|
1216
|
+
as `codex-turn-push-outcome-unknown`, an unconfigured seam, a failed content
|
|
1217
|
+
render and an unavailable binding fail with their own causes, and a
|
|
1218
|
+
pre-dispatch deadline expires as `deadline-expired` with zero binding
|
|
1219
|
+
resolutions and zero control calls. The refusal code is the discriminator and
|
|
1220
|
+
`stale-turn` keeps its per-operation split.
|
|
1221
|
+
- `TestCodexCoordinationPushFailuresExitNonzeroWithCauseAndStatusParity` pins
|
|
1222
|
+
the sender contract: `agent message send` to a Codex target prints
|
|
1223
|
+
`ref/state/reason/action` and then exits nonzero without a usage dump when the
|
|
1224
|
+
native push did not deliver, and `agent message status` reports the same state
|
|
1225
|
+
and reason. A failed terminal store write keeps the original cause token on
|
|
1226
|
+
the receipt, and a delivered turn whose write failed projects
|
|
1227
|
+
`broker-delivery-persist-failed` with an unknown outcome; those two cases
|
|
1228
|
+
cannot reach status parity, because the store write is what failed.
|
|
1229
|
+
- `TestCodexCoordinationPushKeepsTerminalReceiptAndSkipsExtraSteer` pins no
|
|
1230
|
+
steer after a successful start, no new event or delivery change from a second
|
|
1231
|
+
push over a terminal record, and a delivered reason that names only the
|
|
1232
|
+
provider turn push, never model consumption, acknowledgement, or completion.
|
|
1233
|
+
- The offline Claude dialogue fixtures reply to a Codex source, so they now
|
|
1234
|
+
accept a terminal Codex push failure receipt from the qualification reply --
|
|
1235
|
+
the four-field `ref/state/reason/action` line for a fresh reply ref, read
|
|
1236
|
+
instead of the exit code -- because no Codex app-server exists in those
|
|
1237
|
+
fixtures.
|
|
1139
1238
|
|
|
1140
1239
|
### Heterogeneous Agent dialogue Phase 4 tests
|
|
1141
1240
|
|
|
@@ -1155,11 +1254,41 @@
|
|
|
1155
1254
|
recursive, late, or unrelated Stop publishes zero replies.
|
|
1156
1255
|
- `TestClaudeQualificationRequiresBrokerChallengeAndExplicitReply` requires a
|
|
1157
1256
|
stored original challenge, exact current source and target, a full frozen
|
|
1158
|
-
frame, and a broker-committed explicit reply before opening general
|
|
1159
|
-
|
|
1257
|
+
frame, and a broker-committed explicit reply before opening the general reply
|
|
1258
|
+
execution gate. Current qualification responses stay pending across ordinary
|
|
1259
|
+
delivery and Stop text, become qualified after the exact reply, and report
|
|
1260
|
+
helper restart after close while the execution gate refuses further actions.
|
|
1160
1261
|
- `TestClaudeExplicitReplyRejectsForeignStaleAndAlteredCorrelationBeforeCommit`
|
|
1161
1262
|
covers foreign refs, altered conversations, stale generations/incarnations,
|
|
1162
1263
|
reversed-route mismatch, and a wrong qualification response with commit zero.
|
|
1264
|
+
- `TestClaudeExplicitReplyKnownZeroManualRetryPublicReceiptsAndReload` and
|
|
1265
|
+
`TestStoreExplicitReplyKnownZeroManualRetrySurvivesReload` pin the documented
|
|
1266
|
+
[manual reply recovery](agent-message-replies.md): a known-zero failure keeps
|
|
1267
|
+
its immutable receipt, same-ref calls write zero, and a fresh corrected ref
|
|
1268
|
+
delivers once with the original conversation, reversed routes, deadline and
|
|
1269
|
+
peer authority. Public stderr and text/JSON status preserve cause and ref.
|
|
1270
|
+
- `TestClaudeExplicitReplyPartialUnknownExpiredAndStaleNeverDuplicate`,
|
|
1271
|
+
`TestStoreExplicitReplyNonzeroUnknownAndExpiredNeverRetry`, and
|
|
1272
|
+
`TestStoreExplicitReplyRetryKeepsDeadlineAndExactRoute` reject delivered,
|
|
1273
|
+
partial/unknown, pending, expired and stale retries, including store reload,
|
|
1274
|
+
false-unknown-flag and unrecognized-reason cases; Codex retry policy stays
|
|
1275
|
+
unchanged. `TestStoreExplicitReplyConcurrentAttemptsAndCapacityPreserveReceipts`
|
|
1276
|
+
permits only one concurrent new attempt and prevents capacity pruning from
|
|
1277
|
+
reopening a live reply relationship.
|
|
1278
|
+
- `TestClaudeExplicitReplyGuardRetryRetainsQualificationAndRouteFences` keeps
|
|
1279
|
+
known-zero recovery behind the existing exact qualification, provider caller,
|
|
1280
|
+
route and bounded-command gates. `TestClaudeEndpointProcessIntegration/explicit-reply-known-zero-manual-retry`
|
|
1281
|
+
runs the public CLI as the synthetic provider's real descendant: invalid
|
|
1282
|
+
content fails with stderr/ref/action, a corrected manual reply reaches the
|
|
1283
|
+
provider once, same/different-ref duplicates write zero, and independent
|
|
1284
|
+
public status processes preserve both attempts. The provider checks for
|
|
1285
|
+
unexpected queued connections before exit.
|
|
1286
|
+
- `TestClaudeExplicitReplyAcknowledgementRequiresFreshDispatchProof` refuses
|
|
1287
|
+
legacy or malformed acknowledgements without granting a push; replay replies
|
|
1288
|
+
use a distinct response kind that older callers also cannot dispatch.
|
|
1289
|
+
`TestClaudeExplicitReplyStoreRefusalsKeepCauseAndUnknownReservation` preserves
|
|
1290
|
+
bounded busy/capacity/missing/malformed store causes, frees only proven
|
|
1291
|
+
pre-write refusals, and keeps an ambiguous persistence attempt reserved.
|
|
1163
1292
|
- `TestClaudeExplicitMultipleRequestsAndHumanOverlapSelectOnlyNamedOriginal`
|
|
1164
1293
|
permits an explicit reply to B then A across human activity, rejects a second
|
|
1165
1294
|
reply to either request, and never chooses correlation by arrival order.
|
|
@@ -1216,8 +1345,10 @@
|
|
|
1216
1345
|
composite authority before send; semantic barriers replace sleeps. The
|
|
1217
1346
|
scenario requires exact UID/Pane/generation/message/conversation/reply
|
|
1218
1347
|
receipts, Agent count two, Codex provider writes zero, and pre-removal
|
|
1219
|
-
Registry/tmux/helper/socket/process residual checks.
|
|
1220
|
-
|
|
1348
|
+
Registry/tmux/helper/socket/process residual checks. Its strict Claude content
|
|
1349
|
+
fixture preserves `sourceNotice` and verifies claimed/unverified source,
|
|
1350
|
+
caller-authentication limits, and untrusted payload semantics. It does not
|
|
1351
|
+
require a provider binary, model, network, or version matrix.
|
|
1221
1352
|
- The real-provider path is opt-in through `scripts/agent-dialogue-canary-setup.py`
|
|
1222
1353
|
and `docs/heterogeneous-dialogue-canary.md`. It uses public reply-only activation,
|
|
1223
1354
|
product observer/helper-memory evidence and separate qualification/idle claims.
|
|
@@ -1811,6 +1942,22 @@ separate decision this measurement exists to inform.
|
|
|
1811
1942
|
- `TestClaudePushSourceReplacementAfterDurableHandoffWritesZero` and
|
|
1812
1943
|
`TestClaudeProviderPushFinalRouteCheckPrecedesSoleWrite` cover source/target
|
|
1813
1944
|
authority loss across durable work and the final provider pre-write fence.
|
|
1945
|
+
- `TestClaudeProviderFrameSerializedByteBoundaryAndSafeRejection` fixes the
|
|
1946
|
+
complete auth/user frame boundary at 8191/8192/8193 serialized bytes.
|
|
1947
|
+
`TestClaudeProviderPostPreservesConstructionReasonBeforeAnyRouteOrWrite`
|
|
1948
|
+
separates invalid auth/content from size rejection before route or write.
|
|
1949
|
+
`TestClaudeProviderWriteReasonsRequireOneActualWrite` distinguishes actual
|
|
1950
|
+
zero/partial writes and invalid-count/full-with-error unknown outcomes.
|
|
1951
|
+
`TestClaudeProviderRejectionReasonsSurviveHubReceiptStatusAndStoreReload`
|
|
1952
|
+
preserves reasons through helper and public receipts, terminal store reload,
|
|
1953
|
+
sender recovery text, secret exclusion, and duplicate sends with zero retries.
|
|
1954
|
+
`TestClaudeProviderRejectionResponseValidationIsClosedAndLegacyCompatible`
|
|
1955
|
+
admits canonical numeric size details and legacy reasons while rejecting
|
|
1956
|
+
inconsistent ambiguity and secret-bearing suffixes.
|
|
1957
|
+
`TestClaudeEndpointProcessIntegration/provider-frame-rejection-receipt`
|
|
1958
|
+
exercises the built binary's public send/status against the isolated provider:
|
|
1959
|
+
size/action survive, credentials stay absent, and the rejected frame adds no
|
|
1960
|
+
provider connection before the next expected message.
|
|
1814
1961
|
- `TestClaudeExplicitMultipleRequestsAndHumanOverlapSelectOnlyNamedOriginal`
|
|
1815
1962
|
requires an explicit choice of the original request; Stop text has no reply
|
|
1816
1963
|
authority regardless of human activity or pending request count.
|
|
@@ -1847,9 +1994,10 @@ separate decision this measurement exists to inform.
|
|
|
1847
1994
|
outside the disposable root, reject unsafe candidate permissions before
|
|
1848
1995
|
credential copying, and retain roots after uncertain cleanup without retry. Product `TestClaudeDialogueStream*` tests own public output parsing;
|
|
1849
1996
|
the obsolete separate canary collector is removed.
|
|
1850
|
-
- `
|
|
1851
|
-
production Store.PutReply/Claim and public
|
|
1852
|
-
including the actual `target-self-claim`
|
|
1997
|
+
- `TestClaudeDialogueCanaryAcceptsProductionStoreClaimAndPublicReceipt` validates
|
|
1998
|
+
production Store.PutReply/Claim records and current public send/status receipt
|
|
1999
|
+
JSON with the Python companion, including the actual `target-self-claim`
|
|
2000
|
+
reason and version-2 envelope, without a public claim command or serializer.
|
|
1853
2001
|
|
|
1854
2002
|
- L20 owns a real authenticated Codex broker host and keeps its observed snapshot
|
|
1855
2003
|
binding alive for the round trip; Registry-only synthetic authority is refused.
|
|
@@ -1914,6 +2062,12 @@ separate decision this measurement exists to inform.
|
|
|
1914
2062
|
`TestClaudeDialogueStreamRejectsUnknownEffectsAndBoundsState` cover transient
|
|
1915
2063
|
public JSON validation, action/result pairing, zero pre-inbound tool effects,
|
|
1916
2064
|
unknown metadata refusal and finite hook/tool state.
|
|
2065
|
+
- `TestClaudeDialogueStreamReplaysObservedFrameCorpus` replays
|
|
2066
|
+
`internal/app/testdata/claude-dialogue-observed-frames.json`, the top-level
|
|
2067
|
+
key shapes preserved from a Claude Code 2.1.263 run, through a fresh stream in
|
|
2068
|
+
each item's declared state. Items carry provenance labels and the measured
|
|
2069
|
+
verdict. A reject must stop once its recorded rule keys are removed, so any
|
|
2070
|
+
validator change that moves a recorded verdict fails with the item name and rule.
|
|
1917
2071
|
- `TestClaudeDialoguePipeEOFClosesInputButWaitsCurrentTurn`,
|
|
1918
2072
|
`TestClaudeDialoguePipeDiagnosticLossFailsClosedWithoutBusyLoop`,
|
|
1919
2073
|
`TestClaudeDialogueCleanupWaitsExactWriterAndHandlesZombieWithoutSignals`, and
|
|
@@ -1964,3 +2118,6 @@ separate decision this measurement exists to inform.
|
|
|
1964
2118
|
|
|
1965
2119
|
- `test/agent_dialogue_rpc_envelope_test.py`: pinned public JSON-RPC forms classify server requests, errors and notifications without admitting them. Exact success shape and expected ID remain mandatory; wrong/foreign IDs, unknown fields, mixed forms and malformed method/error/trace types refuse. All 64 known-field combinations and nested type branches verify the independent fixed `envelopeFacts` projection, simultaneous defect visibility and dynamic-name/value exclusion. Policy/native initialization tests propagate only those facts; audit tests reject malformed projections before writing. Real parent setup/finally tests preserve external facts before once cleanup, retain uncertain roots or failed audit writes, and produce no source effect or success receipt.
|
|
1966
2120
|
- `test/agent_dialogue_websocket_test.py`: memory-only RFC6455 upgrade/masked writes/message framing, Unicode fragmentation with interleaved control frames, cumulative bounds/EOF/deadline and malformed transport privacy; pinned full initialization with exact owned codexHome precedes framed config/read and thread/read. Canary audit tests connect upgrade refusal/socket close to once parent cleanup and external code retention. Closed substage/rejection-kind regressions distinguish connect/peer, upgrade, initialize/initialized, config/read, EOF/deadline/frame and error/ID/notification envelope rejection; unknown labels remain unknown, raw exception/RPC content is excluded, and audit failure still retains the root.
|
|
2121
|
+
|
|
2122
|
+
- `make test`: Codex recovery diagnostics retain the original request through RPC classification, catalog wrappers, bounded broker lifecycle IPC and observer fallback. `TestRequestFailureDiagnosticPreservesOriginalThroughCatalogWrapping`, `TestFailureDiagnosticIPCProjectionIsClosedAndBounded`, `TestLifecycleRPCDiagnosticPreservesCodeAndRejectsUnrepresentableCode`, `TestObserverFallbackJournalPreservesSafeFailureAndClosedStartup`, `TestObserverDiagnosticRejectedAuthorityWritesZero`, `TestObserverSessionFailurePreservesTerminalReasonAfterAuthorityRejection`, `TestAIIngestTextPreservesBoundedRecoveryDiagnosticsAndLegacyRecords`, and `TestRecoveryDiagnosticGoldenInventoryAndBounds` cover unsupported/catalog/protocol/transport causes, missing/null codes, secret/invalid UTF-8/oversized inputs, existing reason tokens, terminal session-construction fallback after a rejected authority write, bounded public text projection with legacy-row compatibility, and commit-before-journal refusal. `TestManagerEvidenceContradictionAndOwnershipMatrix` and `TestManagerEvidenceCommandFailureAndTimeout` (with `TestManagerDiagnosticDeadlineProcess`) separate independent attach and official read-only manager observations, with unknown/contradictory refusal and zero lifecycle argv. The existing startup parser, parent fallback, exact authority, Phase 0 timing/close and Phase 1 recovery tests remain required.
|
|
2123
|
+
- Opt-in installed zero-turn fixture: `CODEX_DIAGNOSTIC_INPUT=/absolute/input.json go test ./internal/app -run '^TestInstalledCodexRecoveryDiagnosticFixture$' -count=1 -v`, with inherited `TMUX` and `TMUX_PANE` unset. Input fields are `root` (new short `/tmp` directory), `binary`, `binarySHA256`, `sourceHead`, `sourceTree`, and `evidence` (outside root). The binary must come from that clean committed source. Synthetic manager/provider responses are explicitly labeled; the actual executable runs its observer and doctor against a private Registry, exact private tmux socket and real bounded broker IPC. `TestCodexDiagnosticProxyProcess` is the read-only synthetic subprocess helper. The fixture never uses authentication, starts a turn, resumes a live session, or mutates a manager. It checks journal/doctor agreement, the actual public `diagnostics agent-hook` JSON and text consumers (including a labeled synthetic legacy row), old startup parsing, version/ownership refusals, output bounds and exact socket cleanup, then removes its private root. Evidence retains the public JSON records and text lines alongside observer rows and doctor reports. Run the identical fixture against the candidate and the isolated merged-main install; preserve the input, binary/source/tree hashes and evidence JSON.
|
package/docs/architecture.md
CHANGED
|
@@ -242,6 +242,16 @@ Resources and ownership:
|
|
|
242
242
|
session observation, and no replacement allocation. The requested Window and
|
|
243
243
|
all descendants are removed exactly; only explicit Project deletion removes
|
|
244
244
|
the owning root itself.
|
|
245
|
+
Every in-place anchor writer uses the one eligibility predicate `Validate`
|
|
246
|
+
enforces: same-Window ancestry, `shell` or `agent` role, and an Agent Pane
|
|
247
|
+
only while it is its owner's `status.paneRef`. Delete reselection picks the
|
|
248
|
+
first eligible Pane in Registry order; a termination that releases the
|
|
249
|
+
anchoring Agent's binding moves the anchor in the same mutation; a rebind
|
|
250
|
+
moves an anchor on the previous binding Pane onto the new managed Pane.
|
|
251
|
+
Ineligible retained Agent Pane rows are skipped, never selected or deleted,
|
|
252
|
+
and when no eligible Pane remains the anchor lands on a shell allocated
|
|
253
|
+
through the default-shell path. A non-Running Agent still carries an empty
|
|
254
|
+
`paneRef`: the anchor moves, the binding is never kept for it.
|
|
245
255
|
|
|
246
256
|
Home and root kinds:
|
|
247
257
|
|