Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,13 @@

## Unreleased

## 0.2.2 - 2026-10-01

### Fixed

- Keep Pi's working, compaction and retry spinners in the editor border instead of above the input when queue-steer installs the editor ([#11](https://github.com/tmustier/pi-queue-steer/pull/11) by [@VinhLe1410](https://github.com/VinhLe1410)).
- Keep the embedded spinner visible below the queue while a queued row is edited inline.

## 0.2.1 - 2026-10-01

### Fixed
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ pi install git:github.com/tmustier/pi-queue-steer
Pin the current release:

```bash
pi install git:github.com/tmustier/[email protected].1
pi install git:github.com/tmustier/[email protected].2
```

Then start a new Pi session or run `/reload`.
Expand Down
16 changes: 14 additions & 2 deletions docs/validation.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,19 @@ npm run ci

The suite covers queue/edit invariants, command classification, images, one-at-a-time and all-mode delivery, synchronous partial handoff restoration, non-TUI pass-through, prompt and Skill expansion, manual compaction success/failure, automatic overflow compaction, retry ordering, settled-handler launch ordering, repeated reload restoration, and compaction/native-input ordering.

Release 0.2.1: 84 tests passed on both Pi 0.87.0 (the lockfile) and Pi 0.99.2 (the current installed release).
Release 0.2.2: 86 tests passed on both Pi 0.87.0 (the lockfile) and Pi 1.0.0 (the current installed release).

Release 0.2.1: 84 tests passed on both Pi 0.87.0 and Pi 0.99.2.

## Embedded working status

Validated on 1 October 2026 at `3cbd2b57ac4d78efbeb60c6b579c9a8efc7a95c9` for release 0.2.2.

A scratch Pi 1.0.0 TUI used `openai/gpt-6-astra` at low thinking with only this extension loaded. The prompt asked the model to run `sleep 20 && echo done` with bash. While the tool ran, the TUI queued a follow-up. Terminal captures showed:

- `── ⠸ Working ───` in the editor's top border below the queue, where 0.2.1 showed `⠸ Working` above the queue
- the same border line below the queue while the queued row was edited inline, with no stray border when editing a paused queue at idle
- the follow-up delivered once after the run

## Automatic-compaction steering regression

Expand Down Expand Up @@ -67,7 +79,7 @@ Run:

The output directory contains plain terminal captures, provider-call logs, lifecycle-event logs, and runtime-initialization logs. Run it immediately before review so `summary.txt` records the exact Pi version, commit and working-tree state under test. A release evidence run should report `working tree: clean`.

The full harness passed against Pi 0.87.0 and 0.99.2 for release 0.2.1. The historical 0.2.0 release-evidence run reported:
The full harness passed against Pi 0.87.0 and 1.0.0 for release 0.2.2, and against Pi 0.87.0 and 0.99.2 for release 0.2.1. The historical 0.2.0 release-evidence run reported:

```text
pi: 0.84.1
Expand Down
10 changes: 10 additions & 0 deletions editor-render.ts
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,16 @@ function stripOuterFrameAndPadding(line: string, paddingX: number): string {
* add side borders and padding. The queue already provides that frame, so an
* active row should inherit only the live editor content and cursor.
*/
/**
* Keep an editor's top border only when it carries an embedded status such as
* Pi's working spinner, so the status stays visible while a queued row is edited inline.
*/
export function extractEmbeddedStatusBorder(lines: readonly string[]): string[] {
const top = lines[0] ?? "";
const label = stripAnsi(top).replace(/↑ \d+ more/, "").replace(/─/g, "").trim();
return label ? [top] : [];
}

export function extractInlineEditorLines(lines: readonly string[], paddingX = 0): string[] {
if (lines.length === 0) return [""];
if (!isEditorFrame(lines[0] ?? "")) return [...lines];
Expand Down
11 changes: 8 additions & 3 deletions index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import {
type ThemeColor,
} from "@earendil-works/pi-coding-agent";
import { matchesKey, truncateToWidth, visibleWidth, type Component, type EditorComponent } from "@earendil-works/pi-tui";
import { extractInlineEditorLines } from "./editor-render.ts";
import { extractEmbeddedStatusBorder, extractInlineEditorLines } from "./editor-render.ts";
import { expandQueuedInput, queuesDuringCompaction } from "./queued-input.ts";
import {
DeliveryQueue,
Expand Down Expand Up @@ -582,7 +582,9 @@ export default function queueSteerExtension(pi: ExtensionAPI) {
if (features.has(QUEUE_STEER_FEATURE)) return;

const factory = ((tui, theme, keybindings) => {
const editor = previousFactory?.(tui, theme, keybindings) ?? new CustomEditor(tui, theme, keybindings);
const editor = previousFactory?.(tui, theme, keybindings) ?? new CustomEditor(tui, theme, keybindings, {
embedWorkingStatus: true,
});
installSubmitGuard(editor, ctx);
const handleInput = editor.handleInput.bind(editor);
const renderEditor = editor.render.bind(editor);
Expand All @@ -602,8 +604,11 @@ export default function queueSteerExtension(pi: ExtensionAPI) {
}
};

const embedsWorkingStatus = "embedWorkingStatus" in editor && editor.embedWorkingStatus === true;
editor.render = (width: number): string[] => {
if (editSession && !renderingInline) return [];
if (editSession && !renderingInline) {
return embedsWorkingStatus ? extractEmbeddedStatusBorder(renderEditor(width)) : [];
}
return renderEditor(width);
};

Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@tmustier/pi-queue-steer",
"version": "0.2.1",
"version": "0.2.2",
"description": "Visible steering and follow-up queues with inline editing for Pi.",
"type": "module",
"license": "MIT",
Expand Down
17 changes: 16 additions & 1 deletion test/editor-render.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import assert from "node:assert/strict";
import test from "node:test";
import { extractInlineEditorLines, stripAnsi } from "../editor-render.ts";
import { extractEmbeddedStatusBorder, extractInlineEditorLines, stripAnsi } from "../editor-render.ts";

test("removes the stock editor frame without disturbing its cursor", () => {
const cursorMarker = "\x1b_pi:c\x07";
Expand Down Expand Up @@ -65,3 +65,18 @@ test("does not mistake short horizontal user text for the bottom frame", () => {
test("leaves frameless custom editor output intact", () => {
assert.deepEqual(extractInlineEditorLines(["custom editor"]), ["custom editor"]);
});

test("keeps an embedded working status border while a row is edited inline", () => {
const lines = [
"\x1b[33m── \x1b[36m⠸ Working\x1b[33m ──────\x1b[39m",
"draft ",
"\x1b[33m────────────\x1b[39m",
];

assert.deepEqual(extractEmbeddedStatusBorder(lines), [lines[0]]);
});

test("drops plain and overflow-only editor borders while a row is edited inline", () => {
assert.deepEqual(extractEmbeddedStatusBorder(["────────────", "draft", "────────────"]), []);
assert.deepEqual(extractEmbeddedStatusBorder(["─── ↑ 3 more ───", "draft", "────────────"]), []);
});
Loading