projmux 0.12.2 → 0.13.0

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.
@@ -1,164 +1,80 @@
1
1
  # Session Restore
2
2
 
3
- Session snapshots store tmux layout metadata and replay recipes for shell,
4
- startup, and supported agent panes. Manual CLI actions remain available through:
3
+ Session snapshots are explicit desired-state inputs for one Project. They are
4
+ not tmux replay scripts and they are not Registry backups. Snapshot save keeps
5
+ the existing v1 schema and storage behavior.
5
6
 
6
7
  ```sh
7
- projmux get snapshots [--session <name>]
8
+ projmux get snapshots [--session <snapshot-session>]
8
9
  projmux create snapshot
9
- projmux restore snapshot --dry-run [--session <name>]
10
- projmux restore snapshot [--session <name>]
11
- projmux delete snapshot --session <name>
10
+ projmux restore snapshot --session <snapshot-session> [--project <ref> | -p <ref>] --dry-run
11
+ projmux restore snapshot --session <snapshot-session> [--project <ref> | -p <ref>] --yes [--client /dev/pts/N]
12
+ projmux delete snapshot --session <snapshot-session>
12
13
  ```
13
14
 
14
- Snapshots preserve source metadata, not a resolved display label. Window records
15
- keep `window_name`; pane records keep the user label, raw `pane_title`, recipe
16
- fields, AI topic and manual-ownership metadata (`@projmux_ai_topic` and
17
- `@projmux_ai_topic_manual`), and resume metadata when available. There is no
18
- `display_label` field in the snapshot schema. After restore, pane borders and
19
- app window tabs are display-time tmux policy: the app config derives both from
20
- the active pane's visible label expression, while raw shell or terminal titles
21
- remain metadata that may change independently. Branch names continue to appear
22
- in the statusbar git segment; branch-based shell title overwrites are not the
23
- canonical Projmux window naming source.
24
-
25
- The primary inspection surface is `Projects > Sessions > State`. It shows a
26
- read-only overview first: latest snapshot status, named snapshots, window ->
27
- pane structure, cwd, recipe, and agent resume health. Mutation belongs one
28
- level deeper in explicit actions; the overview does not immediately save,
29
- delete, preview, or restore.
30
-
31
- Project Session State actions are scoped to the project-derived session
32
- identity, not the currently attached tmux session. `Save latest snapshot`
33
- captures the live project session when that session exists. `Save named
34
- snapshot` captures the same live project session into a project-local named
35
- snapshot and stores cwd values with portable project-root placeholders. Closed
36
- project sessions disable save actions with the live-session reason. `Preview
37
- restore` prints the read-only dry-run restore plan for the project snapshot, and
38
- `Delete snapshot` requires a confirmation picker before removing the project
39
- snapshot. Destructive restore execution remains outside Settings in this slice.
40
-
41
- Agent panes in Settings and restore dry-run previews show resume metadata
42
- health next to the pane recipe. `available` means a resume id is present and
43
- recent enough for replay, `stale` means the stored id exists but the metadata is
44
- missing or older than the snapshot policy, and `unavailable` means projmux
45
- cannot safely resume that agent pane from the snapshot. Confidence is derived
46
- from the metadata source: direct session ids and hook ingest are high
47
- confidence, transcript/log fallbacks are medium confidence, and missing or
48
- unknown sources are low or none. The old statusbar Session State shortcut has
49
- been removed; use `Projects > Sessions > State` or the canonical snapshot CLI
50
- for inspection/actions.
51
-
52
- Session snapshots capture each pane's user-owned `label` separately from its
53
- raw `title` and agent recipe `topic`. Older snapshots decode with an empty
54
- label and no manual topic ownership; no title/topic equality heuristic is
55
- applied. Replay explicitly sets or clears the label, startup recipe fields, AI
56
- agent/topic/ownership/resume fields, and finally the raw title on the pane id
57
- returned by tmux creation. It does not derive a target or identity from pane
58
- order, a visible title, or equality between saved fields.
59
-
60
- Agent restore direct-starts supported resume commands when creating fresh tmux
61
- panes, matching the `projmux create agent` launch shape: the wrapper prepends the
62
- agent binary directory to `PATH`, changes to the saved cwd, then execs
63
- `codex resume <id>`, `claude --resume <id>`, or
64
- `agy --conversation <uuid>`. It does not copy the saved topic into OSC or raw
65
- tmux title state; replay restores the final raw title only from `Pane.Title`.
66
- Antigravity restore
67
- uses only the stable statusline `conversation_id` or hook `conversationId`
68
- metadata captured as the pane resume id; missing or non-UUID Antigravity ids
69
- render as `resume unavailable` rather than falling back silently to a shell
70
- recipe. This avoids typing agent resumes with
71
- `tmux send-keys`. The restore wrapper is still a non-interactive shell command
72
- tail, so it does not replay the original pane's interactive shell startup,
73
- environment, shell functions, aliases, or live process state. Startup recipes
74
- continue to use their saved `send-keys` command replay, and shell recipes only
75
- restore cwd/layout.
76
-
77
- This live capture lane remains distinct from resume-picker disk discovery and
78
- has high confidence (`hook`/`session-id`). When an Antigravity picker row starts
79
- a pane, its source is captured too: a UUID verified by an exact regular
80
- `conversations/<uuid>.db` through `last_conversations` or workspace-bearing
81
- summarized metadata has medium confidence, while a legacy `history.jsonl` row
82
- has low confidence. Preview and doctor report that source/confidence as stored;
83
- they do not claim that the upstream cache exposes complete history. Disk
84
- discovery does not replace an existing live hook source, and it never opens a
85
- conversation database or reads prompt/transcript content.
86
- Bounded Session State agent-pane previews place resume health before the full
87
- resume id, topic, and title so status, confidence, and source remain visible;
88
- the underlying snapshot and unbounded preview model retain those identity and
89
- context fields unchanged. Non-agent pane preview ordering is unchanged.
90
-
91
- Settings > Session State is global settings only: global auto-save, auto-save
92
- interval, and storage/retention policy. It does not show the current
93
- snapshot tree. Delete for current-session snapshots and destructive restore
94
- execution stay deferred until those actions have a dedicated safe policy for
95
- existing or non-empty live sessions.
96
-
97
- Named snapshots may currently be backed by legacy project files in
98
- `<project>/.projmux/layouts/*.toml`. They reuse the same window, pane, cwd, and
99
- startup recipe concepts as session snapshots, but the user-facing restore model
100
- is still `Latest snapshot`, `Named snapshot`, or `Project topology`. The legacy
101
- files are imported read-only by Project open
102
- when building `Named snapshot` candidates; new primary surfaces should describe
103
- the restore unit as a snapshot, not as a separate layout or preset feature.
104
-
105
- Project open from the Alt-1 sidebar defaults to opening a closed project as its
106
- `Project topology`: the same explicit Registry materialization engine the public
107
- `reconcile resources --materialize-project` route uses rebuilds every Registry
108
- Window and Window-owned shell Pane under their existing uids, and the client
109
- moves only after that converges. A refusal or failure reports the exact stage and
110
- leaves the client where it was. A directory with no Registry Project, and a
111
- Project with no Registry Window, still start as a single default session.
112
- `Settings > Session State > Sidebar startup picker` is an opt-in toggle;
113
- when it is on, closed project open advances inside the sidebar to the native
114
- `Start project` step. Rows are ordered `Latest snapshot`, named snapshot rows,
115
- `Project topology`, then `Back`; a snapshot row stays entirely on the snapshot
116
- engine, so the two sources are never mixed in one open. `Latest snapshot` is the auto-saved snapshot that
117
- keeps changing as auto-save runs. `Named snapshot` is a fixed, user-named
118
- snapshot and is not updated by auto-save. Rows include saved-at date/time
119
- metadata when available. `Back` returns to the project list without creating,
120
- replaying, or opening a session. After the startup mode is selected, project
121
- automation trust is evaluated if needed. For a named snapshot with a startup
122
- `command`, projmux rejects symlink artifacts, reads the selected layout once,
123
- and authorizes the SHA-256 of the exact bytes used to parse the in-memory
124
- restore plan. The trust prompt names the layout file and shows terminal-safe
125
- command previews. Config absence and `PROJMUX_PROJECT_HOOKS=off` do not bypass
126
- this layout gate; commandless layouts keep their existing prompt-free restore
127
- behavior. Approval continues the selected path, while deny/cancel/error aborts
128
- before session or pane creation, snapshot replay, or `send-keys`. Project-owned
129
- layout names, descriptions, window names, agent topics, and command previews
130
- escape terminal control characters before rendering. The Alt-1 sidebar does
131
- not render trust approve/deny rows inline:
132
- before trust is requested, projmux snapshots the sidebar query/selection
133
- context and hands the selected open continuation to a detached tmux job. That
134
- job closes the sidebar popup state for the client and opens the shared `Trust
135
- project automation` popup as a client-scoped decision surface, so no code relies on
136
- the self-closing sidebar popup process continuing after `display-popup -C`.
137
- Deny/cancel or trust-popup errors return to the sidebar near the same
138
- query/selection with a visible status message; only a missing/invalid context
139
- may fall back to a closed popup plus tmux message. Existing sessions switch
140
- directly without a startup picker or trust gate.
141
-
142
- Default `projmux shell` no longer opens a compatibility startup picker and no
143
- longer accepts startup selector flags for snapshot restore. It always
144
- follows the normal empty attach path after resolving the target app session name
145
- and startup directory. Use `Settings > Session State > Sidebar startup picker` for
146
- interactive Latest snapshot / Named snapshot / Project topology selection.
147
-
148
- ## Operational diagnostics
149
-
150
- Selected Session State mutations leave one local, best-effort terminal outcome
151
- in the bounded operational journal. Manual and popup save, Project Settings
152
- latest/named save, manual/Settings/prune delete, and actual project-startup
153
- latest/named replay are covered. Restore preview and `--dry-run` remain
154
- read-only. Successful autosave, disabled/not-due/fresh autosave no-ops, and
155
- nested snapshot store/replay calls do not write an outcome; an actual autosave
156
- failure writes one safe error even under `--quiet`.
157
-
158
- The outcome contains only a closed operation/source and aggregate window,
159
- pane, recipe, or deleted-item counts. It never contains a snapshot or project
160
- path, snapshot content/name, pane cwd/command, agent resume/conversation/session
161
- ID, or arbitrary metadata. Diagnostics append failure never changes save,
162
- restore, delete, or quiet-autosave behavior. See
163
- [operational-diagnostics.md](operational-diagnostics.md) for the complete event
164
- schema and retention/privacy contract.
15
+ Restore requires an exact snapshot and an exact, closed target Project. The
16
+ dry-run validates both inputs and prints replacement, deletion, preserved-UID,
17
+ and lost-conversation-pointer counts with zero Registry, tmux, and snapshot writes.
18
+ Snapshot Project/Window/Pane metadata is checked against the exact target owner
19
+ chain. A UID held by another root, a cross-kind UID reuse, a Project mismatch,
20
+ or conflicting owner metadata refuses before commit. The ordinary Project-open
21
+ trust authorization must also approve the exact target root before the Registry
22
+ transaction begins.
23
+
24
+ After `--yes`, one atomic Registry transaction replaces only the target
25
+ Project's descendant Window/Pane/Agent graph and its descendant name
26
+ reservations. The Project UID, root, trust metadata, unrelated Projects,
27
+ ControlSessions, and source snapshot bytes are preserved. Metadata-bearing
28
+ snapshots reuse their exact target-subtree UIDs and preserve a surviving
29
+ final-v2 Agent or shell anchor plus a surviving direct default shell.
30
+ Metadata-free legacy snapshots reuse target descendants positionally, select
31
+ the first valid Window-local Pane as the role-agnostic anchor, select the first
32
+ direct shell as the optional default, and mint identities only for missing
33
+ items. An Agent-only Window is valid with an empty default. Repeating the same
34
+ projection is a Registry zero-diff.
35
+
36
+ The committed Registry is then converged by the ordinary Project materializer.
37
+ For a restored offline Agent-anchor Window, `Continue project` visibly plans a
38
+ lazy default shell, creates the Window from that shell, and stages the Agent on
39
+ its retained anchor Pane UID. A successful repeat writes neither Registry nor
40
+ topology. Agent recipes use the canonical provider launch/resume path. Stored startup
41
+ commands are not directly executed by snapshot restore. A runtime item refusal
42
+ does not roll the Registry back: desired state and the source snapshot remain
43
+ available for another `Continue project`, and the refusal is reported as an
44
+ item notice. If an explicit client is supplied, the final observable step is
45
+ `switch-client -c` to the Project's declared session even when the background
46
+ continuation has no inherited `TMUX` variable.
47
+
48
+ ## Project startup
49
+
50
+ A closed Project has exactly two actions:
51
+
52
+ - `Continue project` opens the current Registry desired state with the ordinary
53
+ materializer. A retained graph keeps its Project, Window, Pane, and Agent
54
+ UIDs. A zero-Window Project keeps its Project UID and atomically receives one
55
+ new canonical Window and shell UID before materialization.
56
+ - `Open fresh` atomically replaces the same-root graph with a new Project UID
57
+ and one new canonical Window/shell UID chain. It does not archive or retain
58
+ the old generation.
59
+
60
+ Esc/cancel returns to Projects; it is not an action row. Picker failure falls
61
+ back to the non-destructive `Continue project` action.
62
+
63
+ `Open fresh` never deletes or overwrites autosave or named snapshot files. It
64
+ preserves the root, Git/worktrees, trust decision, and all unrelated Registry
65
+ graphs while changing the Project identity. A rejected commit retains the
66
+ exact old Registry preimage. Repeating `Open fresh` replaces identity again;
67
+ each successful result has exactly one Project claiming the root.
68
+
69
+ ## Snapshot contents and diagnostics
70
+
71
+ Snapshots keep window names, pane cwd/label/title, shell/startup/agent recipes,
72
+ AI topic ownership, and provider resume metadata when available. Resume health
73
+ in preview is `available`, `stale`, or `unavailable`; confidence derives from
74
+ the stored source. Snapshot inspection never reads provider transcript or
75
+ conversation database content.
76
+
77
+ An approved projection restore records one safe Session State outcome with
78
+ aggregate Window/Pane/recipe counts and source `manual`. Paths, commands,
79
+ snapshot content, and provider conversation identifiers are never included.
80
+ Dry-run remains read-only and records no mutation outcome.
@@ -33,28 +33,49 @@ step, never a silent no-op.
33
33
 
34
34
  ## Global
35
35
 
36
- - **Projects** — Project discovery, pins, and sidebar policy. Settings manages
37
- discovery and pinning; the runtime picker UI keeps the name `Project Picker`.
36
+ - **Projects** — Project discovery, pins, and sidebar policy, as three separate
37
+ collections with three separate authorities: discovery roots are scan sources,
38
+ Pinned Projects are Registry Project uids, and Candidate Pins are paths no
39
+ Project claims. Settings manages discovery and pinning; the runtime picker UI
40
+ keeps the name `Project Picker`.
38
41
  - `Primary discovery root [View]` — effective/saved/source state, then
39
42
  `Use current directory`, `Enter path`, `Clear saved root`.
40
43
  - `Additional discovery roots [View]` — the collection owns the two add rows;
41
- each saved root is an item View that owns `Remove discovery root`.
42
- - `Pinned Projects [View]` — each pin is an item View showing the Project's
43
- display name, unique name, uid, bound root, condition, missing-since and
44
- runtime separately. A `MissingRoot` Project is never hidden, deleted, or
45
- re-pinned under a new identity: the item offers `Rebind Project root`, which
46
- calls the canonical `rebind project` route and keeps the same uid. Settings
47
- performs no heuristic uid merge and no automatic prune.
48
- - `Project Sidebar [View]` — `Closed Project startup` chooses between using
49
- the stored Project topology and asking for a Snapshot. `Use Project
50
- topology` materializes every Registry Window and Window-owned shell Pane of
51
- that Project under their existing uids and only then moves the client; it is
52
- not an empty session, and the startup picker names that row `Project
53
- topology` for the same reason. `Ask for Snapshot or Project topology` adds
54
- the `Latest snapshot` and `Named snapshot` rows, which stay on the Session
55
- State snapshot engine — the two sources are never mixed in one open. Neither
56
- choice resumes an Agent or executes a stored `Pane.spec.command`. The saved
57
- file keeps its `sidebar-startup-picker` spelling.
44
+ each saved root is an item View that owns `Remove discovery root`. These are
45
+ scan roots: adding one never registers a Project, and scanning one never
46
+ does either.
47
+ - `Pinned Projects [View]` — managed pins only. Each pin references a Registry
48
+ Project uid and is an item View showing the Project's display name, unique
49
+ name, uid, bound root, condition, missing-since and runtime separately, all
50
+ projected from the Registry on every render. Because the pin is a uid rather
51
+ than a path, a rebind, a rename, and a vanished directory all keep the same
52
+ pin: a `MissingRoot` Project is never hidden, deleted, or re-pinned under a
53
+ new identity, and the item offers `Rebind Project root`, which calls the
54
+ canonical `rebind project` route and keeps the same uid. Settings performs no
55
+ heuristic uid merge and no automatic prune.
56
+ - `Candidate Pins [View]` — pinned paths that no Registry Project claims. A
57
+ candidate has exactly the two affordances a candidate has: `Register as
58
+ Project`, which forwards to the canonical `create project --root` route for
59
+ that one exact path, and `Unpin candidate`, which removes the preference and
60
+ leaves the directory alone. Nothing here adopts a path automatically.
61
+ - `Project Sidebar [View]` — holds the two Projects sidebar policies:
62
+ `Runtime diagnostics [Choice]` chooses `When needed` (the read-time default
63
+ with nothing saved) or `Always` for the sidebar's Runtime row. `When needed`
64
+ keeps the row for a refused runtime class or for an observation that could
65
+ not be taken, and withholds it otherwise; `Always` is the shipped
66
+ every-render behavior. The choice moves one row on one surface: the Registry
67
+ view still carries the complete Runtime row and class tally, the Sessions and
68
+ Recent Windows links are unchanged, and `projmux runtime diagnostics` and
69
+ `get runtime` never read it. An unrecognized saved value applies the default
70
+ without writing and shows an invalid source.
71
+ `Closed Project startup` optionally shows exactly two actions.
72
+ `Continue project` materializes the Project's current Registry desired state
73
+ and then moves the client. `Open fresh` confirms exact counts,
74
+ atomically replaces the old Project graph with a new Project UID and a new
75
+ canonical Window/shell UID pair, and leaves exactly one same-root claimant
76
+ before ordinary materialization. Esc returns to Projects. Neither action
77
+ deletes or rewrites snapshots, root, Git, or worktree data. The saved file
78
+ keeps its `sidebar-startup-picker` spelling.
58
79
  - **AI** — `AI` is a product category, never an addressable resource.
59
80
  - `Default launch target [Choice]` — an Agent Provider, a Shell Pane, or
60
81
  choose-at-launch. It is a keybinding/picker preference and does not weaken
@@ -118,9 +139,11 @@ step, never a silent no-op.
118
139
  `Weekly` only. Parent off states gate effective visibility without rewriting
119
140
  saved child values. Provider/window rows show saved, effective, and source.
120
141
  `Project`, `Clock` and `Settings launcher` are direct visibility Toggles. These global
121
- presentation values default on and report saved/default source; hiding the
122
- Settings launcher removes only its mouse chip, not the CLI or keybinding
123
- entry. `Resources` remains one enablement Toggle backed only by
142
+ presentation values default on except Codex `5h`, which defaults off to
143
+ keep the ambient HUD compact; every row reports saved/default source and an
144
+ explicit saved `on` restores Codex `5h`. Hiding the Settings launcher
145
+ removes only its mouse chip, not the CLI or keybinding entry. `Resources`
146
+ remains one enablement Toggle backed only by
124
147
  `live-resources` (default off): off removes its segment and sampler/cache
125
148
  mutation. Notifications and every Agent Usage visibility depth remain
126
149
  presentation-only and do not disable their underlying producers, cache,
@@ -210,8 +233,9 @@ an explicit `TMUX_SPLIT_TARGET_PANE` or from `#{pane_id}` — and not as a
210
233
  `metadata.uid`, because no keybinding handler reads a uid mirror and a raw pane
211
234
  id is never a canonical uid. The two properties the row does assert are the ones
212
235
  that hold: the target is explicit and pinned at press time, and it is never the
213
- Window's persisted `spec.primaryPaneRef`. Automation that omits an anchor uses
214
- `spec.primaryPaneRef` and never silently recovers a stale reference from the
236
+ Window's persisted compatibility shell ref. Automation that omits an anchor
237
+ uses `spec.defaultShellPaneRef` when present and otherwise
238
+ `spec.anchorPaneRef`; it never silently recovers a stale reference from the
215
239
  focused Pane. `Create <Provider> Agent` always creates a new
216
240
  Agent and `Open Agent Resume Picker` only resumes an existing Offline or Failed
217
241
  Agent; the two are separate actions with separate result kinds and are never
package/docs/statusbar.md CHANGED
@@ -31,8 +31,9 @@ row 1 [#S] #{pane_current_path} <git> CPU 12% MEM 41%  %H:%M
31
31
  Usage HUD` independently. Agent Usage HUD is a View whose `Visible` parent
32
32
  contains Claude/Codex/Antigravity provider Views; each provider has its own
33
33
  `Visible` plus explicit supported windows (Claude/Codex: `5h`, `Weekly`;
34
- Antigravity: `Weekly`). Every leaf defaults on. Parent off preserves saved
35
- children, and returning it on restores them. When only one HUD is visible, its
34
+ Antigravity: `Weekly`). Every leaf defaults on except Codex `5h`, which
35
+ defaults off; saving it as on explicitly restores that window. Parent off
36
+ preserves saved children, and returning it on restores them. When only one HUD is visible, its
36
37
  sole range receives the full `#{client_width}` budget and the absent range and
37
38
  alignment are not emitted. When both are hidden, tmux collapses to one line
38
39
  with `status on`,
@@ -252,6 +253,13 @@ bind-key -n MouseDown1Status if-shell -F "#{==:#{mouse_status_range},window}" \
252
253
 
253
254
  ## Usage element drop order
254
255
 
256
+ The compact Codex provider identity is native-first. An authoritative healthy
257
+ app-server snapshot renders as `Codex`; only degraded lanes are qualified as
258
+ `Codex [fallback]` or `Codex [stale]`. Unknown non-stale provenance uses the
259
+ conservative fallback label. These labels are locale-invariant, including on
260
+ en-US and ko-KR narrow rows. The full Usage table, JSON, and diagnostics retain
261
+ the raw source and closed reason; the statusbar label is presentation only.
262
+
255
263
  The usage segment does not pick a whole-segment tier. It starts from its
256
264
  richest render and sheds **one optional element at a time** until the result
257
265
  fits its budget. The order below is the drop order; index 1 goes first.
package/docs/testing.md CHANGED
@@ -17,10 +17,30 @@ and humans run the same entrypoints.
17
17
  `test/install/smoke.sh`. It validates `make install`, atomic binary
18
18
  replacement into an isolated install dir, `tmux apply`, and post-install
19
19
  `notify reconcile` initialization with a fresh HOME/XDG state tree.
20
- - `make test-e2e` builds the same Docker image and runs
21
- `test/e2e/linux-smoke.sh`. It validates a minimal real-tmux workflow:
22
- sessions, panes, config sourcing, reply-state notify reconciliation, focus
23
- notify fallback, and status notify rendering.
20
+ - `make test-e2e` prepares one attempt-local immutable product binary, then
21
+ runs four isolated Linux real-tmux fixtures plus the Codex lifecycle and npm
22
+ staging fixtures. The required inventory is `L01`-`L19`, `C01`, and `N01`;
23
+ every fixture has its own HOME/XDG/tmux/socket/evidence roots and every
24
+ consumer records the same binary SHA. `E2E_SCENARIO=<ID>` selects one exact
25
+ stable scenario for replay.
26
+ - `make test-e2e-contract`, `make test-e2e-reliability`, and
27
+ `make test-e2e-shards` validate typed attempt evidence, bounded semantic
28
+ waits/owned cleanup, and exhaustive four-shard isolation without rerunning
29
+ the full product matrix.
30
+ - `make test-e2e-coverage` validates
31
+ `test/e2e/ags-oedr-manifest.json`: executable scenario markers and shard
32
+ assignments must match all 21 rows with orphan count zero. A matrix may move
33
+ out of real-tmux E2E only when its checked-in entry names executable lower
34
+ positive, negative, and fixed-point evidence and retains a real-boundary
35
+ sentinel. The manifest/orphan half is a prerequisite of `make test-e2e`,
36
+ while the referenced lower test runs in both this coverage target and the
37
+ required unit-test job.
38
+ - `make security` runs the exact three Security groups in parallel locally:
39
+ Go vulnerability/security, Go static quality, and repository policy.
40
+ `make security-serial` is the parity control and `make security-contract`
41
+ checks scanner/rule/baseline identity, PR-range/full-history secret scans,
42
+ cache miss-to-hit convergence, privacy-safe artifacts, and the fail-closed
43
+ aggregate. CI exposes their stable aggregate as `Test`.
24
44
  - `make deadcode` runs `go tool deadcode` (pinned via the go.mod tool
25
45
  directive) over the module and reports unreachable functions, filtering out
26
46
  the intentional/MUST-KEEP baseline in `.deadcode-allowlist.txt`; it fails
@@ -43,6 +63,62 @@ The test container disables networking during `docker run`. The image build may
43
63
  use the network to fetch the pinned base image and apt packages, but suite
44
64
  execution should not need network access after the image is built.
45
65
 
66
+ ## Layered E2E Evidence
67
+
68
+ The AGS-OEDR manifest is the source of truth for which layer owns each
69
+ guarantee. Its `A/G/S` fields describe the scenario contract and `O/E/D/R`
70
+ identify the owner, enforcement, detection, and recovery boundary. The
71
+ coverage audit reads the actual `smoke_contract_begin` markers and
72
+ `linux-shards.tsv`; documentation-only rows cannot satisfy it.
73
+
74
+ L19's plural-read context/selector table is the first evidence-backed move.
75
+ `TestPluralReadContextSelectorMatrix` executes all 60 cells twice at the app
76
+ layer, covering exact positive sets, foreign-scope refusal, and read-only
77
+ fixed-point behavior with zero Registry transaction/write/model change. L19
78
+ still drives five representative sentinels through the built binary on the
79
+ queried exact real-tmux socket below its owned smoke root. Lower-layer parity
80
+ therefore owns the combinatorial table; E2E still owns transport, origin, and
81
+ socket/root containment.
82
+
83
+ Merged main evidence is closed by the same manifest without adding stable IDs.
84
+ L17 links the simultaneous/coalesced exact-generation exit unit tests and the
85
+ integration marker to its real-hook replay: both dead/mirrored Panes disappear,
86
+ Agents become resumable Offline with cleared pane refs, siblings survive, and
87
+ the repeat is Registry-byte-identical. L18 links the closed foreground
88
+ `run-shell` producer ledger and integration transport marker to its attached
89
+ client replay: success is silent or one bounded exact-client message, no
90
+ view-mode overlay appears, and origin PID, focus, and Registry identity remain.
91
+ The two lifecycle boundaries merged at `3322b5f7` stay on existing IDs rather
92
+ than expanding the inventory. L17 links exact clean last-Pane plus
93
+ Window-unlinked causality, zero-Window Project retention, stale-resume refusal,
94
+ sibling reanchor/containment, and byte-identical replay to the Project-stop
95
+ marker. L19 separately links ControlSession last-Window descendant cleanup,
96
+ root retention, zero replacement allocation, sibling containment, and
97
+ fixed-point replay to its own marker. The shared integration marker closes the
98
+ real last-Pane transport boundary. The audit fails when any linked guarantee,
99
+ exact lower test inventory/symbol/selector, or executable integration/E2E
100
+ marker is missing, misspelled, or duplicated.
101
+
102
+ Lifecycle commit `dcffa5da` remains inside L11. Its closed evidence row links
103
+ the retained/zero-Window lifecycle table, managed runtime stop, Continue, and
104
+ always-new Fresh lower tests to the existing lifecycle integration completion
105
+ and the L11 attached-client marker before pass. Authority commit `de52d15d`
106
+ remains inside L17. Its row links creator-Registry admission, journal-path and
107
+ CLOEXEC handshake tests to the immediate-exit integration/E2E markers, and
108
+ also closes the focused fresh-root repeat harness plus the read-only
109
+ owner/queue observation and product-terminal controller marker. These rows add
110
+ no scenario ID: the audit still requires exactly 21 stable scenarios and fails
111
+ closed if either source commit, guarantee set, lower selector, supporting
112
+ marker, or marker-before-pass edge drifts.
113
+
114
+ The required result hash accepts exactly one `begin` followed by one typed
115
+ `pass` for every expected stable ID. A terminal `fail`, `cancel`, or
116
+ `unattributed` class, a terminal without its begin row, and an interrupted
117
+ unterminated attempt all keep the aggregate red. `cancel` remains a schema
118
+ value for an explicitly observed cancellation; the shell harness does not
119
+ invent cancellation evidence from a signal whose semantic cause it cannot
120
+ attribute.
121
+
46
122
  ## Host-Only Checks
47
123
 
48
124
  The Docker suites do not replace checks that depend on a real host terminal,