@timurproko/a1 0.2.7-dev.808 → 0.2.7-dev.810
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/README.md +4 -2
- package/dist/app/session-shell/dialog-coordinator.d.ts +42 -0
- package/dist/app/session-shell/dialog-coordinator.js +133 -0
- package/dist/app/session-shell/dock-chrome.d.ts +34 -0
- package/dist/app/session-shell/dock-chrome.js +109 -0
- package/dist/app/session-shell/exit-notice.d.ts +1 -1
- package/dist/app/session-shell/exit-notice.js +1 -1
- package/dist/app/session-shell/extension-surface.d.ts +30 -0
- package/dist/app/session-shell/extension-surface.js +105 -0
- package/dist/app/session-shell/input-surface-switch.d.ts +36 -0
- package/dist/app/session-shell/input-surface-switch.js +85 -0
- package/dist/app/session-shell/login-interaction.d.ts +27 -0
- package/dist/app/session-shell/login-interaction.js +91 -0
- package/dist/app/session-shell/prompt-submission.d.ts +48 -0
- package/dist/app/session-shell/prompt-submission.js +276 -0
- package/dist/app/session-shell/resident-tab-coordinator.d.ts +41 -0
- package/dist/app/session-shell/resident-tab-coordinator.js +120 -0
- package/dist/app/session-shell/response-copy-transport.d.ts +13 -0
- package/dist/app/session-shell/response-copy-transport.js +16 -7
- package/dist/app/session-shell/session-concern.d.ts +22 -0
- package/dist/app/session-shell/session-concern.js +29 -0
- package/dist/app/session-shell/session-lifecycle.d.ts +29 -0
- package/dist/app/session-shell/session-lifecycle.js +49 -0
- package/dist/app/session-shell/session-shell-root.d.ts +1 -1
- package/dist/app/session-shell/session-shell-root.js +182 -931
- package/dist/app/session-shell/session-shell.d.ts +2 -8
- package/dist/app/session-shell/session-shell.js +202 -901
- package/dist/app/session-shell/settings-bindings.d.ts +17 -0
- package/dist/app/session-shell/settings-bindings.js +91 -0
- package/dist/app/session-shell/shell-editor-factory.d.ts +27 -0
- package/dist/app/session-shell/shell-editor-factory.js +102 -0
- package/dist/app/session-shell/shell-host.d.ts +6 -0
- package/dist/app/session-shell/shell-host.js +8 -0
- package/dist/app/session-shell/shell-layout.d.ts +64 -0
- package/dist/app/session-shell/shell-layout.js +18 -0
- package/dist/app/session-shell/suggestion-surface.d.ts +25 -0
- package/dist/app/session-shell/suggestion-surface.js +63 -0
- package/dist/app/session-shell/transcript-document.d.ts +78 -0
- package/dist/app/session-shell/transcript-document.js +365 -0
- package/dist/app/session-shell/viewport-layout.d.ts +31 -0
- package/dist/app/session-shell/viewport-layout.js +160 -0
- package/dist/app/session-shell/workflow-output.d.ts +33 -0
- package/dist/app/session-shell/workflow-output.js +174 -0
- package/dist/app/session-shell/workflow-router.d.ts +25 -0
- package/dist/app/session-shell/workflow-router.js +39 -0
- package/dist/composition/owned-ui.d.ts +4 -25
- package/dist/composition/owned-ui.js +26 -270
- package/dist/composition/resident-tab-bridge.d.ts +16 -0
- package/dist/composition/resident-tab-bridge.js +159 -0
- package/dist/composition/session-backend.d.ts +19 -0
- package/dist/composition/session-backend.js +1 -0
- package/dist/composition/session-runtime-registry.d.ts +20 -0
- package/dist/composition/session-runtime-registry.js +85 -0
- package/dist/composition/startup-route.d.ts +32 -0
- package/dist/composition/startup-route.js +72 -0
- package/dist/foundation/release/progress-palette.generated.d.ts +2 -2
- package/dist/foundation/release/progress-palette.generated.js +2 -2
- package/dist/foundation/startup/startup-descriptor.js +2 -2
- package/dist/integrations/pi/components/resources/builtin-themes.d.ts +2 -2
- package/dist/integrations/pi/components/resources/builtin-themes.js +2 -2
- package/dist/integrations/pi/components/shell-extension-ui.js +79 -60
- package/dist/integrations/pi/components/upstream/adjacent/core/keybindings.d.ts +1 -1
- package/dist/integrations/pi/components/upstream/adjacent/core/keybindings.js +1 -1
- package/dist/integrations/pi/components/upstream/assets/earendil-image.json +2 -2
- package/dist/integrations/pi/components/upstream/components/countdown-timer.d.ts +1 -1
- package/dist/integrations/pi/components/upstream/components/earendil-announcement.js +1 -1
- package/dist/integrations/pi/components/upstream/components/extension-editor.d.ts +1 -1
- package/dist/integrations/pi/components/upstream/components/extension-editor.js +1 -1
- package/dist/integrations/pi/components/upstream/components/extension-input.js +1 -1
- package/dist/integrations/pi/components/upstream/components/extension-selector.js +1 -1
- package/dist/integrations/pi/components/upstream/components/mermaid.js +1 -1
- package/dist/integrations/pi/components/upstream/components/owned-editor.d.ts +1 -1
- package/dist/integrations/pi/components/upstream/components/owned-editor.js +1 -1
- package/dist/integrations/pi/components/upstream/components/pi-logo.js +1 -1
- package/dist/integrations/pi/components/upstream/components/scoped-models-selector.d.ts +1 -1
- package/dist/integrations/pi/components/upstream/components/session-footer.js +1 -1
- package/dist/integrations/pi/components/upstream/components/session-selector-search.js +1 -1
- package/dist/integrations/pi/components/upstream/components/session-selector.js +1 -1
- package/dist/integrations/pi/components/upstream/components/skill-invocation-message.d.ts +1 -1
- package/dist/integrations/pi/components/upstream/components/skill-invocation-message.js +1 -1
- package/dist/integrations/pi/components/upstream/components/status-indicator.d.ts +1 -1
- package/dist/integrations/pi/components/upstream/components/status-indicator.js +1 -1
- package/dist/integrations/pi/components/upstream/components/themed-text.d.ts +1 -1
- package/dist/integrations/pi/components/upstream/components/themed-text.js +1 -1
- package/dist/integrations/pi/components/upstream/components/thinking-selector.d.ts +1 -1
- package/dist/integrations/pi/components/upstream/components/thinking-selector.js +1 -1
- package/dist/integrations/pi/components/upstream/components/tool-execution.d.ts +2 -4
- package/dist/integrations/pi/components/upstream/components/tool-execution.js +77 -98
- package/dist/integrations/pi/components/upstream/components/tree-selector.d.ts +1 -1
- package/dist/integrations/pi/components/upstream/components/tree-selector.js +1 -1
- package/dist/integrations/pi/components/upstream/components/trust-selector.js +1 -1
- package/dist/integrations/pi/components/upstream/external-editor.js +1 -1
- package/dist/integrations/pi/components/upstream/history/editor-core.d.ts +1 -1
- package/dist/integrations/pi/components/upstream/history/editor-core.js +1 -1
- package/dist/integrations/pi/components/upstream/history/kill-ring.d.ts +1 -1
- package/dist/integrations/pi/components/upstream/history/kill-ring.js +1 -1
- package/dist/integrations/pi/components/upstream/history/printable-key.js +1 -1
- package/dist/integrations/pi/components/upstream/history/text-helpers.js +1 -1
- package/dist/integrations/pi/components/upstream/history/undo-stack.d.ts +1 -1
- package/dist/integrations/pi/components/upstream/history/undo-stack.js +1 -1
- package/dist/integrations/pi/components/upstream/history/word-navigation.js +1 -1
- package/dist/integrations/pi/components/upstream/model-search.d.ts +1 -1
- package/dist/integrations/pi/components/upstream/program-status-reporter.d.ts +1 -1
- package/dist/integrations/pi/components/upstream/theme/theme-controller.d.ts +1 -1
- package/dist/integrations/pi/components/upstream/theme/theme.js +1 -1
- package/dist/integrations/pi/engine/adapter.d.ts +4 -77
- package/dist/integrations/pi/engine/adapter.js +85 -393
- package/dist/integrations/pi/engine/command-dispatch.d.ts +13 -0
- package/dist/integrations/pi/engine/command-dispatch.js +57 -0
- package/dist/integrations/pi/engine/host.js +2 -2
- package/dist/integrations/pi/engine/ports.d.ts +56 -0
- package/dist/integrations/pi/engine/ports.js +89 -0
- package/dist/integrations/pi/engine/resources/changelog.json +4 -4
- package/dist/integrations/pi/engine/view-state.d.ts +42 -0
- package/dist/integrations/pi/engine/view-state.js +126 -0
- package/dist/integrations/pi/startup-public.js +164 -150
- package/dist/integrations/pi/startup-public.manifest.json +351 -310
- package/dist/integrations/pi/tui-runtime/adapter.js +4 -0
- package/dist/integrations/pi/tui-runtime/contracts.d.ts +5 -0
- package/dist/integrations/pi/tui-runtime/damage-aware-terminal.d.ts +1 -1
- package/dist/integrations/pi/tui-runtime/damage-aware-terminal.js +1 -1
- package/dist/native/darwin-arm64/manifest.json +1 -1
- package/dist/native/darwin-arm64/terminal-host.manifest.json +3 -3
- package/dist/native/darwin-arm64/terminal-host.node +0 -0
- package/dist/native/darwin-x64/manifest.json +1 -1
- package/dist/native/darwin-x64/terminal-host.manifest.json +3 -3
- package/dist/native/darwin-x64/terminal-host.node +0 -0
- package/dist/native/linux-x64/manifest.json +1 -1
- package/dist/native/linux-x64/terminal-host.manifest.json +3 -3
- package/dist/native/linux-x64/terminal-host.node +0 -0
- package/dist/native/win32-x64/manifest.json +2 -2
- package/dist/native/win32-x64/process-guardian.node +0 -0
- package/dist/native/win32-x64/terminal-host.manifest.json +3 -3
- package/dist/native/win32-x64/terminal-host.node +0 -0
- package/dist/runtime-payload-inventory.json +5181 -5369
- package/dist/ui/components/transcript-viewport.js +10 -19
- package/docs/architecture/boundaries.md +14 -0
- package/docs/architecture/resident-tabs.md +8 -8
- package/docs/architecture/response-copy-delivery.md +1 -1
- package/docs/architecture/toolchain.md +2 -2
- package/package.json +5 -5
|
@@ -4,6 +4,10 @@ import { backgroundSgrSpan, overlaySpan } from "./spans.js";
|
|
|
4
4
|
import { faint, truncateToWidth, displayWidth, stripAnsi } from "./text.js";
|
|
5
5
|
import { extendTextSelection, orderedTextSelection, pressTextSelection, releaseTextSelection, textSelectionLineExtendColumn, textSelectionPointAt, textSelectionText, usefulTextLineContent, } from "./text-selection.js";
|
|
6
6
|
const CONTROL_STYLE_RESET = "\u001b]8;;\u001b\\\u001b[0m";
|
|
7
|
+
// Protocol: upstream OSC 133 zones are layout annotations, not fullscreen cursor commands.
|
|
8
|
+
// Styling/padding can move them away from the row prefix Pi strips; 133;A then advances a real
|
|
9
|
+
// terminal parser to a fresh line. The custom viewport owns prompt anchors separately.
|
|
10
|
+
const VIEWPORT_PROMPT_ZONES = /\u001b\]133;[ABC](?:\u0007|\u001b\\)/gu;
|
|
7
11
|
// Invariant: scrollbar chrome closes source links and decoration without clearing
|
|
8
12
|
// the row surface painted beneath its dedicated, non-semantic gutter.
|
|
9
13
|
const GUTTER_DECORATION_RESET = "\u001b]8;;\u001b\\\u001b[22;23;24;25;27;28;29;39;54;55m";
|
|
@@ -362,7 +366,7 @@ export class TranscriptViewport {
|
|
|
362
366
|
contentLength: documentRows.length,
|
|
363
367
|
viewportHeight,
|
|
364
368
|
scroll: this.#scrollTop,
|
|
365
|
-
//
|
|
369
|
+
// Invariant: the rail keeps its top gap; the shell owns the spacing above the dock.
|
|
366
370
|
trackHeight: Math.max(0, viewportHeight - 1),
|
|
367
371
|
});
|
|
368
372
|
const presentation = scrollbarPresentation({
|
|
@@ -504,7 +508,7 @@ export class TranscriptViewport {
|
|
|
504
508
|
// Invariant: paint the rail after selection over the gutter's continued row
|
|
505
509
|
// background. Source content and selection still end at the preceding cell.
|
|
506
510
|
let railCell = "";
|
|
507
|
-
if (row < viewportHeight && presentation.visible && geometry !== null
|
|
511
|
+
if (row > 0 && row < viewportHeight && presentation.visible && geometry !== null) {
|
|
508
512
|
const trackRow = row - 1;
|
|
509
513
|
const thumb = isThumbRow(geometry, trackRow);
|
|
510
514
|
const glyph = thumb ? presentation.thumbGlyph : presentation.trackGlyph;
|
|
@@ -526,7 +530,7 @@ export class TranscriptViewport {
|
|
|
526
530
|
return overlayWidth === 0 ? withControl : overlaySpan(padRowPreservingBackground(withControl, width), overlayLimit - overlayWidth, overlayLimit, `${GUTTER_DECORATION_RESET}${overlayText}`, { inheritStartStyle: true });
|
|
527
531
|
});
|
|
528
532
|
rowRecomputed ||= !final.reused;
|
|
529
|
-
frameRows[row] = final.value;
|
|
533
|
+
frameRows[row] = final.value.replace(VIEWPORT_PROMPT_ZONES, "");
|
|
530
534
|
(rowRecomputed ? recomputedRows : reusedRows).push(row + 1);
|
|
531
535
|
const state = `${width}\u0000${row}\u0000${painted}\u0000${rangeKey}\u0000${range === null ? "" : selectionPainterId}\u0000${railCell}\u0000${overlayText}\u0000${rowControl?.text ?? ""}`;
|
|
532
536
|
visibleStates.push(state);
|
|
@@ -627,19 +631,10 @@ export class TranscriptViewport {
|
|
|
627
631
|
|| !sameRectangle(previous.descriptor.transcript, expectedTranscript))
|
|
628
632
|
return null;
|
|
629
633
|
const descriptor = {
|
|
634
|
+
...previous.descriptor,
|
|
630
635
|
frameId: ++this.#frameId,
|
|
631
|
-
width: boundedWidth,
|
|
632
|
-
height: boundedHeight,
|
|
633
|
-
transcript: expectedTranscript,
|
|
634
|
-
dock: expectedDock,
|
|
635
636
|
previousDocumentRange: previous.descriptor.nextDocumentRange,
|
|
636
|
-
nextDocumentRange: previous.descriptor.nextDocumentRange,
|
|
637
637
|
previousFollowingEnd: previous.followingEnd,
|
|
638
|
-
followingEnd: previous.followingEnd,
|
|
639
|
-
transientRowCount: previous.descriptor.transientRowCount,
|
|
640
|
-
transientAlignmentGapRows: previous.descriptor.transientAlignmentGapRows,
|
|
641
|
-
bottomAlignedTailRowCount: previous.descriptor.bottomAlignedTailRowCount,
|
|
642
|
-
liveTailRows: previous.descriptor.liveTailRows,
|
|
643
638
|
verticalShiftRows: 0,
|
|
644
639
|
safeVerticalShift: false,
|
|
645
640
|
selectionRevision: this.#selectionRevision,
|
|
@@ -650,12 +645,8 @@ export class TranscriptViewport {
|
|
|
650
645
|
this.#selectionRows = [...this.#selectionRows.slice(0, viewportHeight), ...dock].slice(0, boundedHeight);
|
|
651
646
|
this.#copyableDockRows = copyableDockRowsBySuffix(dockRows, copyableDockRows);
|
|
652
647
|
const frame = {
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
scrollTop: previous.scrollTop,
|
|
656
|
-
maxScroll: previous.maxScroll,
|
|
657
|
-
followingEnd: previous.followingEnd,
|
|
658
|
-
hits: previous.hits,
|
|
648
|
+
...previous,
|
|
649
|
+
rows: [...previous.rows.slice(0, viewportHeight), ...dock.map(row => row.replace(VIEWPORT_PROMPT_ZONES, ""))].slice(0, boundedHeight),
|
|
659
650
|
descriptor,
|
|
660
651
|
selectionDamage: {
|
|
661
652
|
revision: this.#selectionRevision,
|
|
@@ -44,6 +44,20 @@ The JavaScript product path has no PTY or terminal-emulator dependency. Reintrod
|
|
|
44
44
|
|
|
45
45
|
`scripts/governance/check-architecture.mjs` enforces the structural parts of these boundaries. Cross-cutting rationale belongs here; implementation history belongs in Git and archived OpenSpec changes.
|
|
46
46
|
|
|
47
|
+
## Session shell composition
|
|
48
|
+
|
|
49
|
+
The session presenter (`src/app/session-shell/session-shell.ts`) coordinates; it does not own per-concern state. Each concern implements `SessionConcern` (`session-concern.ts`): it resets its own state in `onSessionReplaced` and releases it in `dispose`, and the presenter lists its concerns once, in reset order, in `#createConcerns`. New submission, routing, dialog, login, or resident-tab behavior goes into the concern that owns it, or a new concern added to that list. The render root (`session-shell-root.ts`) likewise picks one `ShellLayout` at construction and delegates transcript caching to `TranscriptDocument`, dock chrome to `DockChrome`, workflow output to `WorkflowOutput`, extension surfaces to `ExtensionSurface`, and the dock's input surface to `InputSurfaceSwitch`. The engine adapter serves the shell through the ports built in `src/integrations/pi/engine/ports.ts`, and the composition root delegates runtime claims, the startup release note, and the resident-tab bridge to their own modules under `src/composition/`.
|
|
50
|
+
|
|
51
|
+
## Unit size ratchet
|
|
52
|
+
|
|
53
|
+
Module boundaries do not stop one class or function inside a module from absorbing every feature. The architecture gate therefore measures every production TypeScript class under `src/` (methods and fields) and every TypeScript or Rust function under `src/` and `native/<crate>/src/` (inclusive lines), excluding vendored sources and Rust `#[cfg(test)]` code. A unit with more than 20 methods, 15 fields, or 100 function lines must be recorded in `config/baselines/size-ratchet.json`, and its recorded counts can only shrink:
|
|
54
|
+
|
|
55
|
+
- A recorded count that grows fails the gate. Split the unit instead. If growth is truly unavoidable, raise the entry by hand in the same pull request and say why in its description, so the growth is reviewed rather than silent.
|
|
56
|
+
- An unrecorded unit over a threshold fails the gate; split it before it lands.
|
|
57
|
+
- A count that shrinks, or a unit that falls below every threshold, fails until `node scripts/governance/update-size-ratchet.mjs` lowers or removes the entry. That script never adds or raises an entry; `--check` reports without writing.
|
|
58
|
+
|
|
59
|
+
The measurement in `scripts/governance/size-ratchet-policy.mjs` masks strings, comments, and regular expressions and counts braces, so it needs no build; a file whose braces do not balance is reported rather than mismeasured. Keys are `<path>::<Class>`, `<path>::<Class>.<method>`, or `<path>::<Type>::<fn>`, so moving or renaming a unit means moving its entry.
|
|
60
|
+
|
|
47
61
|
## Multi-session limits of the pinned engine
|
|
48
62
|
|
|
49
63
|
The engine host removes A1's own obstacles to several Pi sessions in one process, but three remain in the pinned Pi SDK and must be planned around, not discovered:
|
|
@@ -64,7 +64,7 @@ The read-only review used A1 `develop` at `b42b3c9e`, PR #586 at `8fdb7361`, `E:
|
|
|
64
64
|
|
|
65
65
|
### Milestone 3 failure-isolation contract (2026-10-14)
|
|
66
66
|
|
|
67
|
-
- The native `core/server.rs
|
|
67
|
+
- The native `core/server.rs`, `core/holder.rs`, and `core/attach/` state machines are deterministic and I/O-free; the production holder uses the holder core for bounded input admission and ordered writer effects, the production server uses the server core for heartbeat supervision, and the attach client steps the attach core for every interaction mode (popup, rename, drag), shortcut, deferred input, and server answer while `roles/attach.rs` keeps the connection, outer terminal, encoders, and presentation. Blocking identity/termination work runs through the bounded worker shell with deadlines and stale-incarnation filtering.
|
|
68
68
|
- Every attach, server, and holder role has an independent 15-second watchdog. Watchdog records are bounded, timestamped, owner-only metadata under the profile runtime directory; fault-only role freezes are refused by non-test release builds.
|
|
69
69
|
- Holders read PTY output continuously, use one bounded input authority, reserve complete pastes before delivery, and emit a typed uncertain-delivery result after an admitted write failure. Each holder independently refreshes the server's latest complete retained surface even while hidden. Server-to-client control lanes are frame/byte bounded, render lanes retain one replaceable full current surface, and only the viewed tab is delivered to each attach client.
|
|
70
70
|
- Server replacement is serialized by `server-start.lock` in the profile runtime directory. Recovery verifies the recorded native owner before termination, waits boundedly for the registry-writer lease, increments the durable epoch, derives holder credentials, and re-admits only exact holder/child identities and incarnations. A durable three-start/sixty-second budget stops automatic replacement; explicit `--restart` clears it.
|
|
@@ -229,7 +229,7 @@ The channels carry bounded generation-1 frames: a u32 little-endian length follo
|
|
|
229
229
|
|
|
230
230
|
### 6. Rendering, input, and outer-terminal fidelity
|
|
231
231
|
|
|
232
|
-
- **Composition.** The attach client composes row 0 (the strip) and rows `1..N` (the viewed tab's surface). The tab PTY is sized `cols × (rows − 1)`. Ghostty remains the sole child-terminal parser. Its stream parser reports synchronized-output begin/end/reset boundaries to the holder, which keeps mutable parser state separate from an immutable committed surface and never publishes an open transaction. A non-renewable 250 ms deadline publishes one typed recovery commit for a malformed transaction. The outer composer owns the only synchronized envelope and falls back to a full repaint only when identity, geometry generation, dimensions, or the structured base changes.
|
|
232
|
+
- **Composition.** The attach client composes row 0 (the strip) and rows `1..N` (the viewed tab's surface). The tab PTY is sized `cols × (rows − 1)`. Ghostty remains the sole child-terminal parser. Its stream parser reports synchronized-output begin/end/reset boundaries to the holder, which keeps mutable parser state separate from an immutable committed surface and never publishes an open transaction. A non-renewable 250 ms deadline publishes one typed recovery commit for a malformed transaction. On Windows, ConPTY re-renders the child's cells on its own schedule and relays the DEC 2026 markers when it parses them, so a render pass can land between a frame's markers and the rest of its cells can arrive after the end marker; the holder therefore treats a relayed end marker as "frame parsed", keeps the state private until the following render pass has arrived and settled for 2 ms, and publishes anyway after a 40 ms bound. A begin marker that arrives while that pass is still pending does not publish the torn state. Unix PTYs relay bytes verbatim, so their markers still delimit frames exactly. The outer composer owns the only synchronized envelope and falls back to a full repaint only when identity, geometry generation, dimensions, or the structured base changes.
|
|
233
233
|
- **Outer modes.** The client negotiates the outer terminal's modes: raw mode, alternate screen, bracketed paste, focus events, SGR mouse, kitty keyboard protocol where available, and synchronized output.
|
|
234
234
|
- Child-requested modes are tracked in the holder's model. Input is re-encoded per child mode by libghostty-vt, which the proof already does.
|
|
235
235
|
- Mouse rows are offset by the strip. Row 0 belongs to the client.
|
|
@@ -395,12 +395,12 @@ Every queue, buffer, file, and collection the resident roles keep has a declared
|
|
|
395
395
|
| Structured complete surface | 512 × 256 geometry, 65,536 cells, 4,096 styles, 4,096 links, and 8 MiB decoded state | `protocol.rs` `StructuredSurface::validate` | `structured_surfaces_fail_closed_on_dimensions_indexes_and_control_injection` |
|
|
396
396
|
| Input per message and holder input queue | 1 MiB | `protocol.rs`, `core/holder.rs`, `roles/holder.rs` | `over_capacity_paste_delivers_no_prefix` |
|
|
397
397
|
| Holder PTY ingress and work round | 64 × 16 KiB lossless chunks; at most 256 KiB or 2 ms before yielding | `roles/holder.rs` | `verify-resident-parallel-progress.mjs` concurrent and stopped-stage cases |
|
|
398
|
-
| Per-client control lane | 1,024 frames and 4 MiB | `roles/server.rs` | `control_lane_is_bounded_by_frames_and_bytes` |
|
|
399
|
-
| Per-client render slot | one pending full surface; a newer one replaces it | `roles/server.rs` `Peer::offer_surface` | `stalled_client_gets_one_full_current_surface` |
|
|
400
|
-
| Concurrent endpoint connections | 128 | `roles/server.rs` `admit_connection` | `connections_beyond_the_cap_are_refused_and_released_slots_are_reused` |
|
|
401
|
-
| Attached viewing clients | 16 | `roles/server.rs` `client_slot_available` | `attached_clients_are_capped` |
|
|
398
|
+
| Per-client control lane | 1,024 frames and 4 MiB | `roles/server/mod.rs` | `control_lane_is_bounded_by_frames_and_bytes` |
|
|
399
|
+
| Per-client render slot | one pending full surface; a newer one replaces it | `roles/server/mod.rs` `Peer::offer_surface` | `stalled_client_gets_one_full_current_surface` |
|
|
400
|
+
| Concurrent endpoint connections | 128 | `roles/server/mod.rs` `admit_connection` | `connections_beyond_the_cap_are_refused_and_released_slots_are_reused` |
|
|
401
|
+
| Attached viewing clients | 16 | `roles/server/mod.rs` `client_slot_available` | `attached_clients_are_capped` |
|
|
402
402
|
| Concurrent holder starts | default 2, hard 8 | `core/server.rs` | `limits_starts_and_drops_stale_completion` |
|
|
403
|
-
| Stopped tab records | 16, oldest dropped first | `roles/server.rs` `prune_stopped_records` | `stopped_records_are_bounded_oldest_first_and_live_tabs_are_kept` |
|
|
403
|
+
| Stopped tab records | 16, oldest dropped first | `roles/server/mod.rs` `prune_stopped_records` | `stopped_records_are_bounded_oldest_first_and_live_tabs_are_kept` |
|
|
404
404
|
| Prior tab-set archives | bounded history | `roles/registry.rs` | `prior_tab_sets_are_bounded` |
|
|
405
405
|
| Abandoned blocking workers | 8 | `shell/workers.rs` | `fails_fast_after_eight_abandoned_workers` |
|
|
406
406
|
| Diagnostic logs | 5 MiB × 3 generations per role | `roles/diagnostics.rs` | `logs_rotate_at_their_cap_and_keep_a_bounded_number_of_generations` |
|
|
@@ -458,7 +458,7 @@ The v2 daemon was unreliable for structural reasons, and a forensic pass over it
|
|
|
458
458
|
| Synchronous `taskkill` loops blocked the daemon for 30–60 s | Blocking kills on the event loop | Kills run asynchronously and concurrently, with deadlines. The loop keeps answering heartbeats. |
|
|
459
459
|
| Blocked ConPTY writes stalled the loop, and keystrokes or pastes were silently dropped ("newest wins") | No flow control | A dedicated writer per holder with a bounded queue. Reserve capacity for a complete paste before delivery; reject an over-capacity paste visibly without delivering a prefix. After admission, preserve byte order and report delivery uncertainty if a child or process fails; never silently truncate or retry accepted bytes. |
|
|
460
460
|
| Terminal queries (DA/DSR/CPR) were answered by the busy shared emulator, so children stalled | One emulator loop for all agents | Each holder answers its own tab's queries from its own model. |
|
|
461
|
-
| Repaints arrived in fragments ("ghost frames"), patched with timing heuristics and two screen sources | Emulation reconciled with bridge surfaces by timers | One source of truth, the holder model. Frames are published at synchronized-output boundaries, with a bounded coalescing window. |
|
|
461
|
+
| Repaints arrived in fragments ("ghost frames"), patched with timing heuristics and two screen sources | Emulation reconciled with bridge surfaces by timers | One source of truth, the holder model. Frames are published at synchronized-output boundaries, with a bounded coalescing window; where ConPTY relays those boundaries ahead of the cells it re-renders, publication waits for the render pass instead of the marker. |
|
|
462
462
|
| A late exit event poisoned the replacement child | Events were not tied to an incarnation | Incarnation IDs on every event. Stale events are discarded. |
|
|
463
463
|
| Resizes were lost in transit | Edge-triggered resize | Size is desired state, reconciled until observed. |
|
|
464
464
|
| Restore spawned duplicate agents | No restore gate | A single start gate for crash restarts, at most one start in flight per tab, and conditional revisions. The duplicate-start invariant is checked in simulation. |
|
|
@@ -19,7 +19,7 @@ A generated probe on Windows Node 24.16.0 copied the same eight-character range
|
|
|
19
19
|
- Copy: 5-second admission deadline, one executing request and one newest pending request, at most 16 MiB UTF-8 text. Source snapshots retain only selected rows, capped at 65,536 rows and 32 Mi UTF-16 code units; they do not keep an obsolete whole-transcript graph.
|
|
20
20
|
- Paste: eight distinct admitted requests, a 5-second acquisition budget including the captured write wait, and a 15-second deadline through insertion. A canceled executor counts against capacity until its stop fence. Image conversion has one process-wide slot. Copy supersession is deliberately not used for paste edits.
|
|
21
21
|
- Text transfer: 16 MiB UTF-8 cap; IPC fragments are at most 16,384 code units and preserve surrogate pairs. The receiver acknowledges each fragment. Prepared large text is stored behind the existing compact chip rather than inserted as millions of editor characters. Existing source-image, pixel, encoded-output and attachment-count limits remain unchanged.
|
|
22
|
-
- Clipboard executors have a 250 ms stop grace. A helper that has already reported a complete prepared result and lingers past that grace is reaped, not canceled: it is still terminated, but its prepared text is delivered exactly rather than replaced with an empty payload. Only an explicit cancellation, a protocol violation, or an incomplete byte count discards prepared text. POSIX command fallbacks share the paste helper's isolated process group; strict command reads use a forceful kill signal. Unconfirmed executor termination retains its capacity instead of allowing unbounded replacements or late A1-controlled writes. No helper inherits the UI terminal or places clipboard payloads in argv, temporary files, or logs.
|
|
22
|
+
- Clipboard executors have a 250 ms stop grace. A helper that has already reported a complete prepared result and lingers past that grace is reaped, not canceled: it is still terminated, but its prepared text is delivered exactly rather than replaced with an empty payload. Only an explicit cancellation, a protocol violation, or an incomplete byte count discards prepared text. POSIX command fallbacks share the paste helper's isolated process group; strict command reads use a forceful kill signal. Native POSIX copy writers (`wl-copy`, `xclip`, `pbcopy`) start detached in their own process group, as in pinned Pi 1.4, so a writer that daemonizes to keep serving the clipboard is not stopped when Ctrl+Z suspends A1. Unconfirmed executor termination retains its capacity instead of allowing unbounded replacements or late A1-controlled writes. No helper inherits the UI terminal or places clipboard payloads in argv, temporary files, or logs.
|
|
23
23
|
- Local copy prefers native delivery outside the terminal. OSC 52 uses the existing writer only on a non-blocking supported output route and is capped at a complete 64 KiB control, or a lower advertised limit. Submission is not clipboard acknowledgment. Remote/multiplexed sessions never silently read or write a different host's clipboard. Native Ctrl+V acquisition is unavailable when only the remote terminal owns the desired clipboard; normal terminal-provided paste remains supported.
|
|
24
24
|
- URL-chip decoration: at most 65,536 UTF-8 bytes of added OSC 8 metadata per editor render pass across rows and repeated occurrences, including opening/closing pairs and cleanup closes. Targets that do not fit are omitted whole before control construction; a UTF-16 length precheck avoids scanning huge backing values. The budget resets each pass. Full chip data, atomic editing and exact copy/history/submission expansion remain intact; ordinary in-budget links retain their targets. Terminal automatic URL recognition is separate from explicit metadata.
|
|
25
25
|
- Path-list presentation: the isolated classifier budgets 4,096 UTF-16 units per paste for existing individual tags plus 20 suffix-reserve units per occurrence. Over-budget lists use one existing text-paste chip backed by all classified full paths concatenated in order, including repetitions, without extra separators or re-normalization. No individual members are adopted into the UI before compaction. Small lists retain their file/folder/image-file chips; failed/timed-out classification retains the existing original-text fallback. Existing draft/history chips and the synchronous compatibility classifier are unchanged.
|
|
@@ -34,9 +34,9 @@ It contains no executable built from A1 sources, separate session-lock addon, br
|
|
|
34
34
|
|
|
35
35
|
## Native addon layer
|
|
36
36
|
|
|
37
|
-
`npm run doctor` reports this contract against the current machine—Node range, npm major, git, the GitHub CLI, Rust/Cargo, and whether `node_modules` matches the lockfile—and names the
|
|
37
|
+
`npm run doctor` reports this contract against the current machine—Node range, npm major, git, the GitHub CLI, Rust/Cargo, Windows Microsoft C++ readiness where applicable, and whether `node_modules` matches the lockfile—and names the explicit setup action for anything missing. `npm run build` resolves the same native environment and runs the check before cleaning or compiling, so an unmet prerequisite fails by name rather than inside a module resolver, Cargo, or the linker. Unmet tool prerequisites block; a Node or npm version outside the declared contract is reported as an advisory without failing the build.
|
|
38
38
|
|
|
39
|
-
Source builds require Rust/Cargo 1.85 or newer; `rust-toolchain.toml` pins the exact version CI and publication install through `scripts/development/prepare-ci-rust.sh`, and rustup selects that version for Cargo commands inside the repository, installing it on first use. The Zig cache (`mlugg/setup-zig`, one entry per workflow and platform per run, bounded to 512 MiB) stays enabled: measured on 2026-10-16, a cold Zig build of `libghostty-vt` added about 40 to 60 seconds to a terminal-host test build (Linux 2m21s cold against 1m20s warm, Windows 2m05s against 1m26s), which the cache saves on every warm run.
|
|
39
|
+
Source builds require Rust/Cargo 1.85 or newer; `rust-toolchain.toml` pins the exact version CI and publication install through `scripts/development/prepare-ci-rust.sh`, and rustup selects that version for Cargo commands inside the repository, installing it on first use. On Windows, the resolver honors explicit `CARGO` and `RUSTC` executables, then the launching `PATH`, then `%USERPROFILE%\.cargo\bin`; the fallback changes only build-child state. Windows native linking also requires Visual Studio or Visual Studio Build Tools with the Desktop development with C++ workload, MSVC x64/x86 tools, and a Windows SDK. Visual Studio Code is not a compiler prerequisite. An already valid developer environment is retained; otherwise the resolver uses the installed stable Visual Studio locator and `vcvars64.bat`, verifies that `cl.exe` and Microsoft's `link.exe` come from the selected VC tools, and passes the captured environment only to child processes. This prevents Git Bash's GNU `link.exe` from shadowing MSVC without changing persistent `PATH`. A1 never installs these tools, elevates privileges, or accepts licenses automatically. The Zig cache (`mlugg/setup-zig`, one entry per workflow and platform per run, bounded to 512 MiB) stays enabled: measured on 2026-10-16, a cold Zig build of `libghostty-vt` added about 40 to 60 seconds to a terminal-host test build (Linux 2m21s cold against 1m20s warm, Windows 2m05s against 1m26s), which the cache saves on every warm run.
|
|
40
40
|
|
|
41
41
|
`npm run build` compiles `native/process-guardian` as the host platform's Node-API 9 addon, places `process-guardian.node` under `dist/native/<platform>-<architecture>/`, loads it to observe its version identity, and writes the v2 integrity manifest. It also builds the current platform's release-profile `terminal-host.node`, whose v2 manifest binds the addon, `dist/foundation/resident-tabs/host-entry.js`, and notices, so the ordinary `npm run build && ./scripts/dev` handoff exercises resident tabs without deployment. On Windows the normal build reuses a compatible ignored terminal-library cache or downloads the newest compatible library from the current branch or a successful CI run belonging to a pull request already merged into `develop`, then links it under the crate's manifest verification; it never silently invokes the quarantined Zig package fetch. An unavailable or mismatched prerequisite fails the build instead of leaving a nominally successful single-agent-only tree. The npm `prepare` lifecycle and validation preflight use the explicit core build because selected native lanes assemble and certify terminal hosts separately.
|
|
42
42
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@timurproko/a1",
|
|
3
|
-
"version": "0.2.7-dev.
|
|
3
|
+
"version": "0.2.7-dev.810",
|
|
4
4
|
"description": "Standalone terminal workspace for supervised native and managed agents",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"privateLaunchContract": "neutral-launch-v1",
|
|
@@ -23,8 +23,8 @@
|
|
|
23
23
|
},
|
|
24
24
|
"scripts": {
|
|
25
25
|
"clean": "node scripts/clean.mjs",
|
|
26
|
-
"build": "node scripts/development/
|
|
27
|
-
"build:core": "node scripts/development/
|
|
26
|
+
"build": "node scripts/development/run-build.mjs",
|
|
27
|
+
"build:core": "node scripts/development/run-build.mjs --core",
|
|
28
28
|
"build:managed": "npm run clean && tsc -p tsconfig.build.json && node scripts/release/generate-release-notes-resource.mjs && node scripts/pi/build-pi-settings-metadata.mjs && node scripts/pi/build-startup-public.mjs && node scripts/development/build-process-guardian.mjs",
|
|
29
29
|
"build:process-guardian": "node scripts/development/build-process-guardian.mjs",
|
|
30
30
|
"build:terminal-host": "node scripts/development/build-terminal-host.mjs",
|
|
@@ -72,8 +72,8 @@
|
|
|
72
72
|
"typecheck:bin": "tsgo -p tsconfig.bin.json"
|
|
73
73
|
},
|
|
74
74
|
"dependencies": {
|
|
75
|
-
"@earendil-works/pi-coding-agent": "1.
|
|
76
|
-
"@earendil-works/pi-tui": "1.
|
|
75
|
+
"@earendil-works/pi-coding-agent": "1.4.0",
|
|
76
|
+
"@earendil-works/pi-tui": "1.4.0",
|
|
77
77
|
"@silvia-odwyer/photon-node": "0.3.4",
|
|
78
78
|
"chalk": "5.6.2",
|
|
79
79
|
"cross-spawn": "7.0.6",
|