Merge remote-tracking branch 'origin/master' into fix/remove-badge
This commit is contained in:
+4
-2
@@ -63,7 +63,7 @@ Calls that stay un-evented (registry registration → explicit call → await):
|
||||
A trigger/menu/pick pipeline with zero knowledge of "commands":
|
||||
|
||||
- The service holds only the source registry (`SlashSource{trigger: '/'|'@', name, order?, candidates, onPick, matchSpace?, matchEnter?}`; (trigger,name) unique; the optional `order` sorts the roster — lower first, default 0, ties keep registration order — and that sorted roster is both group order and polling order) and `sessionOf(sctx)`. Implementing a match hook IS the declaration of participation in space/enter adjudication; the pipeline polls in roster order, the first non-undefined answer wins, and no claimant means the default sink. matchSpace is synchronous (space fires mid-keystroke; hot cache only); matchEnter is asynchronous (it may await the source's own warmup, and a warmup failure rejects).
|
||||
- The controller holds the single authoritative hit (span included; retained for Space after the menu closes), the per-session menu store, the candidate-fetch generation, keyboard arbitration (combobox mode: focus stays in the textarea, ↑↓/Enter/Escape are intercepted and all pass the IME composition guard, with the single exception Shift+Enter unconditionally going first), and pick orchestration (outcome → self-dispatched bail events); a `dismiss()` verb backs MenuView's injected `onDismiss` (a pointer down outside both the menu and the surrounding composer card closes the menu; MenuView also localizes group titles through the `slash.menu` locale namespace and clamps its height to the viewport space above the composer via ui-primitives' `useAnchoredMaxHeight`); at each session scope's birth it runs `warm(projection)` once over the source roster — within that scope the projection holds only the stable sessionId, with no published/capability transitions; the scope disposer tears down the controller.
|
||||
- The controller holds the single authoritative hit (span included; retained for Space after the menu closes), the per-session menu store, the candidate-fetch generation, keyboard arbitration (combobox mode: focus stays in the textarea, ↑↓/Enter/Escape are intercepted and all pass the IME composition guard, with the single exception Shift+Enter unconditionally going first), and pick orchestration (outcome → self-dispatched bail events). `toggleSource(name, syntheticHit)` is the chrome-launch path: it seeds only that registered source over the caller's textarea selection and publishes `launcher = name` until close; ordinary typed tracking clears the launcher and restores the full trigger roster. Both paths render the same MenuView and execute the same `onPick` chain. A `dismiss()` verb backs MenuView's injected `onDismiss` (a pointer down outside both the menu and the surrounding composer card closes the menu; MenuView also localizes group titles through the `slash.menu` locale namespace and clamps its height to the viewport space above the composer via ui-primitives' `useAnchoredMaxHeight`); at each session scope's birth it runs `warm(projection)` once over the source roster — within that scope the projection holds only the stable sessionId, with no published/capability transitions; the scope disposer tears down the controller.
|
||||
- Trigger-detection word boundaries (`user@host` and URL `/` never trigger) and the guard tiers (plain: `/` everywhere + `@` inline / claimed: `/` suppressed, `@` live / frozen: none) are the frozen pure core.
|
||||
|
||||
### hub / facade: the resident shell and the strict-session input body
|
||||
@@ -101,7 +101,7 @@ skill/@subagent references skip the placeholder + occurrence identity chain —
|
||||
- `conversation.input.dock` — the stacked strip above the input (QueueDock's read-only queue list lands here), ordered by `order`.
|
||||
- `conversation.composer.dock` — the stats band on the composer's top edge.
|
||||
- `conversation.input.left` / `conversation.input.right` — the tool-row left and right regions.
|
||||
- `conversation.input.plan` / `conversation.input.model` (single) — the tool row's two named control seats; the bar passes only `locked` (owner props), each stays empty until its owning plugin registers, no placeholder fallback.
|
||||
- `conversation.input.plan` / `conversation.input.model` (single) — the tool row's two named control seats; the bar passes only `locked` (owner props), each stays empty until its owning plugin registers, no placeholder fallback. The plan seat stays empty while inactive because the shared Command source owns entry; an effective plan target renders the warn-state `Plan ×` status button, whose only action is `/plan off`.
|
||||
- `conversation.hero.workspace` (root scope) — the Workspace picker shared by the no-session and blank Hero; a pick reuses or creates the target blank session through `connectWorkspace`, moving the draft where necessary before switching current.
|
||||
|
||||
### Testing discipline
|
||||
@@ -122,6 +122,8 @@ The state machine's entire behavior is covered by pure-JS unit tests (event sequ
|
||||
| Space adjudication also claiming execute-kind commands | The misfire defense: after a space the whole line is an ordinary prompt; irreversible side effects keep explicit entry points only |
|
||||
| A generic tokenPattern decoration mechanism | Structured occurrence records replace pattern scanning |
|
||||
| A placeholder select resident in the tool row | Named seats stay empty until registration; a placeholder clashing with the real implementation is two sources of truth |
|
||||
| An always-visible Plan on/off toggle | The shared Command source already owns entry; a second entry point turns a status seat into redundant mode chrome |
|
||||
| A second plus-menu component/controller, or an Add/File group above Command | It would duplicate async candidates, keyboard highlight, focus retention, and pick state; the plus control is only a source-filtered launcher for the existing MenuView, and this scope has no file capability |
|
||||
| All references through U+FFFC chips (the pre-Decision-21 line) | Plain text + derived decoration carries zero identity state; the literal text IS the model projection, sparing undo/clipboard any special cases; the chip chain is kept for scenarios needing indivisible atomicity |
|
||||
|
||||
## Consequences
|
||||
|
||||
Reference in New Issue
Block a user