@timurproko/a1 0.2.5 → 0.2.6-dev.727
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/bin/cli.js +13 -2
- package/bin/ui.js +13 -0
- package/dist/app/session-shell/prompt-suggestion-controller.d.ts +5 -4
- package/dist/app/session-shell/prompt-suggestion-controller.js +148 -58
- package/dist/app/session-shell/session-shell-root.d.ts +5 -1
- package/dist/app/session-shell/session-shell-root.js +13 -6
- package/dist/app/session-shell/session-shell.js +132 -51
- package/dist/app/session-shell/session-viewport-controller.js +33 -21
- package/dist/cli/dispatch.js +5 -3
- package/dist/cli/session-context.d.ts +5 -1
- package/dist/cli/session-context.js +25 -8
- package/dist/composition/owned-ui.d.ts +3 -0
- package/dist/composition/owned-ui.js +66 -6
- package/dist/composition/settings-route-host.js +4 -3
- package/dist/contracts/owned-ui/index.d.ts +4 -2
- package/dist/contracts/owned-ui/index.js +1 -1
- package/dist/contracts/owned-ui/model.d.ts +4 -0
- package/dist/contracts/owned-ui/suggestion-diagnostics.d.ts +5 -1
- package/dist/contracts/owned-ui/suggestion-diagnostics.js +3 -1
- package/dist/contracts/owned-ui/validation.js +7 -0
- package/dist/features/launch/index.d.ts +1 -1
- package/dist/features/launch/session-context.d.ts +17 -2
- package/dist/features/launch/session-context.js +9 -5
- package/dist/features/owned-ui/reference-routes.d.ts +1 -1
- package/dist/features/owned-ui/reference-routes.js +1 -1
- package/dist/features/owned-ui/settings-app.js +21 -39
- package/dist/features/prompt-suggestions/diagnostics.js +4 -1
- package/dist/foundation/lifecycle/index.d.ts +2 -2
- package/dist/foundation/lifecycle/index.js +1 -1
- package/dist/foundation/lifecycle/session-repository-context.d.ts +19 -2
- package/dist/foundation/lifecycle/session-repository-context.js +434 -66
- package/dist/foundation/process-containment/index.d.ts +1 -0
- package/dist/foundation/process-containment/index.js +1 -0
- package/dist/foundation/process-containment/native-process-inspector.d.ts +3 -0
- package/dist/foundation/process-containment/native-process-inspector.js +21 -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/components.js +2 -2
- package/dist/integrations/pi/components/index.d.ts +2 -2
- package/dist/integrations/pi/components/index.js +1 -1
- package/dist/integrations/pi/components/lazy-selectors.d.ts +42 -0
- package/dist/integrations/pi/components/lazy-selectors.js +32 -0
- package/dist/integrations/pi/components/modal-frame.js +3 -4
- package/dist/integrations/pi/components/models-dialog.js +5 -5
- package/dist/integrations/pi/components/prompt-input-port.d.ts +1 -0
- 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/share-operation-dialog.js +3 -3
- package/dist/integrations/pi/components/shell-editor-autocomplete.js +8 -7
- package/dist/integrations/pi/components/shell-extension-ui.d.ts +2 -0
- package/dist/integrations/pi/components/shell-extension-ui.js +20 -10
- package/dist/integrations/pi/components/shell-hotkey-sections.js +2 -2
- package/dist/integrations/pi/components/shell-presenters-info.js +10 -10
- package/dist/integrations/pi/components/shell-presenters-transcript.js +10 -10
- package/dist/integrations/pi/components/shell-selectors-dialogs.js +5 -6
- package/dist/integrations/pi/components/shell-shared-facade.js +1 -1
- package/dist/integrations/pi/components/skills-dialog.js +3 -3
- package/dist/integrations/pi/components/submitted-prompt-adapter.js +2 -3
- package/dist/integrations/pi/components/theme.d.ts +9 -0
- package/dist/integrations/pi/components/theme.js +30 -0
- package/dist/integrations/pi/components/tool-result-adapter.js +6 -1
- 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 +6 -6
- package/dist/integrations/pi/components/upstream/components/extension-input.js +4 -4
- package/dist/integrations/pi/components/upstream/components/extension-selector.js +4 -4
- package/dist/integrations/pi/components/upstream/components/mermaid.js +1 -1
- package/dist/integrations/pi/components/upstream/components/owned-editor.d.ts +5 -5
- package/dist/integrations/pi/components/upstream/components/owned-editor.js +8 -5
- 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/scoped-models-selector.js +3 -3
- 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 +14 -20
- package/dist/integrations/pi/components/upstream/components/skill-invocation-message.d.ts +3 -2
- package/dist/integrations/pi/components/upstream/components/skill-invocation-message.js +6 -3
- 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 +2 -2
- package/dist/integrations/pi/components/upstream/components/tool-execution.d.ts +4 -0
- package/dist/integrations/pi/components/upstream/components/tool-execution.js +11 -1
- package/dist/integrations/pi/components/upstream/components/tree-selector.d.ts +2 -2
- package/dist/integrations/pi/components/upstream/components/tree-selector.js +27 -18
- 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 +4 -4
- package/dist/integrations/pi/components/upstream/history/editor-core.js +11 -7
- 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 +31 -0
- package/dist/integrations/pi/components/upstream/program-status-reporter.js +89 -0
- package/dist/integrations/pi/components/upstream/theme/system-theme.d.ts +1 -1
- package/dist/integrations/pi/components/upstream/theme/system-theme.js +1 -1
- package/dist/integrations/pi/components/upstream/theme/theme-controller.d.ts +1 -1
- package/dist/integrations/pi/components/upstream/theme/theme.d.ts +18 -1
- package/dist/integrations/pi/components/upstream/theme/theme.js +207 -10
- package/dist/integrations/pi/engine/pi-settings-metadata.json +1 -1
- package/dist/integrations/pi/engine/resources/changelog.json +4 -4
- package/dist/integrations/pi/engine/session-events.js +10 -2
- package/dist/integrations/pi/engine/transcript-projection.js +2 -1
- package/dist/integrations/pi/startup-public.js +306 -290
- package/dist/integrations/pi/startup-public.manifest.json +289 -265
- package/dist/integrations/pi/tui-runtime/adapter.d.ts +8 -1
- package/dist/integrations/pi/tui-runtime/adapter.js +31 -1
- package/dist/integrations/pi/tui-runtime/contracts.d.ts +3 -1
- 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/linux-x64/manifest.json +1 -1
- package/dist/native/win32-x64/manifest.json +2 -2
- package/dist/native/win32-x64/process-guardian.exe +0 -0
- package/dist/product-identity.d.ts +2 -2
- package/dist/product-identity.js +2 -2
- package/dist/product-identity.json +3 -1
- package/dist/runtime-payload-inventory.json +3092 -2878
- package/dist/ui/components/prompt-input.d.ts +2 -0
- package/dist/ui/components/prompt-input.js +5 -1
- package/dist/ui/components/text-selection.d.ts +1 -1
- package/dist/ui/components/text-selection.js +3 -1
- package/dist/ui/components/theme.d.ts +2 -0
- package/dist/ui/components/transcript-viewport.d.ts +6 -4
- package/dist/ui/components/transcript-viewport.js +94 -16
- package/dist/ui/components/value-menu.d.ts +2 -0
- package/dist/ui/components/value-menu.js +13 -8
- package/dist/ui/settings/declarations.d.ts +26 -14
- package/dist/ui/settings/declarations.js +24 -11
- package/dist/ui/settings/migrations.js +16 -0
- package/docs/architecture/project-structure.md +4 -3
- package/docs/architecture/prompt-suggestions.md +14 -10
- package/docs/local-worktree-cleanup.md +23 -9
- package/docs/manual-owned-ui-checkpoint.md +1 -1
- package/docs/openspec-archive-automation.md +20 -19
- package/package.json +3 -3
|
@@ -10,6 +10,8 @@ export interface PromptInputBody {
|
|
|
10
10
|
readonly topRule?: string | undefined;
|
|
11
11
|
readonly bottomRule?: string | undefined;
|
|
12
12
|
readonly after?: readonly string[];
|
|
13
|
+
/** Outer indentation for after-body rows; defaults to the prompt prefix width. */
|
|
14
|
+
readonly afterIndent?: number;
|
|
13
15
|
}
|
|
14
16
|
export interface PromptInputMetrics {
|
|
15
17
|
readonly measure: (text: string) => number;
|
|
@@ -31,6 +31,10 @@ export class PromptInput {
|
|
|
31
31
|
return [];
|
|
32
32
|
const { prefixWidth, innerWidth } = this.geometry(width, padding, promptGlyph);
|
|
33
33
|
const body = renderBody(innerWidth);
|
|
34
|
+
const requestedAfterIndent = body.afterIndent ?? prefixWidth;
|
|
35
|
+
const afterIndent = Number.isFinite(requestedAfterIndent)
|
|
36
|
+
? Math.min(width, Math.max(0, Math.floor(requestedAfterIndent)))
|
|
37
|
+
: prefixWidth;
|
|
34
38
|
const fit = (row) => {
|
|
35
39
|
const clipped = this.metrics.truncate(row, width);
|
|
36
40
|
return clipped + " ".repeat(Math.max(0, width - this.metrics.measure(clipped)));
|
|
@@ -45,7 +49,7 @@ export class PromptInput {
|
|
|
45
49
|
...(ruled ? [rule(body.topRule)] : []),
|
|
46
50
|
...rows,
|
|
47
51
|
...(ruled ? [rule(body.bottomRule)] : []),
|
|
48
|
-
...(body.after ?? []).map(row => fit(`${" ".repeat(
|
|
52
|
+
...(body.after ?? []).map(row => fit(`${" ".repeat(afterIndent)}${row}`)),
|
|
49
53
|
];
|
|
50
54
|
}
|
|
51
55
|
}
|
|
@@ -56,7 +56,7 @@ export declare function releaseTextSelection(selection: TextSelection | undefine
|
|
|
56
56
|
export declare function textSelectionLineExtendColumn(selection: TextSelection, line: number, contentWidth: number): number;
|
|
57
57
|
/** Resolves a reported one-based pointer cell to the complete grapheme it intersects. */
|
|
58
58
|
export declare function textSelectionPointAt(line: number, column: number, lineText: string): TextSelectionPoint;
|
|
59
|
-
export declare function textSelectionText(selection: OrderedTextSelection, rows: readonly string[], lineContent?: (line: number) => TextSelectionLineContent | undefined): string;
|
|
59
|
+
export declare function textSelectionText(selection: OrderedTextSelection, rows: readonly string[], lineContent?: (line: number) => TextSelectionLineContent | undefined, includeLine?: (line: number) => boolean): string;
|
|
60
60
|
/** Returns the plain cells covered by [from,to), expanding at grapheme edges. */
|
|
61
61
|
export declare function plainTextBetweenColumns(line: string, from: number, to: number): string;
|
|
62
62
|
export declare function usefulTextLineContent(line: string, from?: number): TextSelectionLineContent;
|
|
@@ -111,9 +111,11 @@ export function textSelectionPointAt(line, column, lineText) {
|
|
|
111
111
|
}
|
|
112
112
|
return { line, column, from: target, to: target + 1 };
|
|
113
113
|
}
|
|
114
|
-
export function textSelectionText(selection, rows, lineContent) {
|
|
114
|
+
export function textSelectionText(selection, rows, lineContent, includeLine = () => true) {
|
|
115
115
|
const parts = [];
|
|
116
116
|
for (let line = selection.start.line; line <= selection.end.line && line < rows.length; line += 1) {
|
|
117
|
+
if (!includeLine(line))
|
|
118
|
+
continue;
|
|
117
119
|
const plain = stripAnsi(rows[line] ?? "");
|
|
118
120
|
const content = lineContent?.(line);
|
|
119
121
|
if (content?.selectable === false) {
|
|
@@ -8,6 +8,8 @@ export interface UiTheme {
|
|
|
8
8
|
* into a dark terminal, which is how the engine leaves its lists too.
|
|
9
9
|
*/
|
|
10
10
|
plain(text: string): string;
|
|
11
|
+
/** Optional palette preview used by controls that choose the active accent. */
|
|
12
|
+
accentPreview?(color: string, text: string): string | null;
|
|
11
13
|
/** Selection background for an active list item or floating-surface row. */
|
|
12
14
|
highlight(text: string): string;
|
|
13
15
|
/** A control that is present but cannot act: quieter than quiet text. */
|
|
@@ -25,7 +25,7 @@ export interface TranscriptViewportFrameInput {
|
|
|
25
25
|
readonly documentRows: readonly string[];
|
|
26
26
|
/** Optional paint-only transform; semantic selection and copying keep documentRows exact. */
|
|
27
27
|
readonly paintDocumentRow?: (row: string) => string;
|
|
28
|
-
/** Leading document rows
|
|
28
|
+
/** Leading persistent document rows; later transient rows remain selectable visible-frame content. */
|
|
29
29
|
readonly selectableDocumentRowCount?: number;
|
|
30
30
|
/**
|
|
31
31
|
* First document row owned by the block that is currently streaming, if any. Rows from
|
|
@@ -84,7 +84,7 @@ export interface TranscriptViewportHitRegions {
|
|
|
84
84
|
readonly columnStart: number;
|
|
85
85
|
readonly columnEnd: number;
|
|
86
86
|
} | null;
|
|
87
|
-
/** Transient non-
|
|
87
|
+
/** Transient non-persistent document-tail rows currently visible in the viewport. */
|
|
88
88
|
readonly transientTail: readonly number[];
|
|
89
89
|
}
|
|
90
90
|
export interface TranscriptViewportFrameDescriptor {
|
|
@@ -109,7 +109,7 @@ export interface TranscriptViewportFrameDescriptor {
|
|
|
109
109
|
};
|
|
110
110
|
readonly previousFollowingEnd: boolean | null;
|
|
111
111
|
readonly followingEnd: boolean;
|
|
112
|
-
/** Complete non-
|
|
112
|
+
/** Complete non-persistent suffix, including pending steering, alignment, and status rows. */
|
|
113
113
|
readonly transientRowCount: number;
|
|
114
114
|
/** Flexible rows inserted before the bottom-aligned live status while content fits. */
|
|
115
115
|
readonly transientAlignmentGapRows: number;
|
|
@@ -164,7 +164,9 @@ export declare class TranscriptViewport {
|
|
|
164
164
|
get hasSelection(): boolean;
|
|
165
165
|
/** True when the active gesture began on transcript rows rather than the dock. */
|
|
166
166
|
get selectionFromContent(): boolean;
|
|
167
|
-
pressSelection(column: number, frameRow: number, now?: number
|
|
167
|
+
pressSelection(column: number, frameRow: number, now?: number, options?: {
|
|
168
|
+
readonly continueMultiClick?: boolean;
|
|
169
|
+
}): boolean;
|
|
168
170
|
extendSelection(column: number, frameRow: number, now?: number, autoScroll?: boolean): boolean;
|
|
169
171
|
releaseSelection(): boolean;
|
|
170
172
|
clearSelection(): boolean;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { MAX_COPY_SOURCE_UNITS } from "./selection-copy.js";
|
|
1
|
+
import { MAX_COPY_SOURCE_UNITS, selectionCopyLineContent } from "./selection-copy.js";
|
|
2
2
|
import { isThumbRow, scrollbarGeometry, scrollbarPresentation, } from "./scrollbar.js";
|
|
3
3
|
import { backgroundSgrSpan, overlaySpan } from "./spans.js";
|
|
4
4
|
import { faint, truncateToWidth, displayWidth, stripAnsi } from "./text.js";
|
|
@@ -8,8 +8,13 @@ const CONTROL_STYLE_RESET = "\u001b]8;;\u001b\\\u001b[0m";
|
|
|
8
8
|
// the row surface painted beneath its dedicated, non-semantic gutter.
|
|
9
9
|
const GUTTER_DECORATION_RESET = "\u001b]8;;\u001b\\\u001b[22;23;24;25;27;28;29;39;54;55m";
|
|
10
10
|
const IDENTITY_ROW = (row) => row;
|
|
11
|
-
function documentSelectionAnchor(row, source) {
|
|
12
|
-
return { kind: "document", row, source, identity: stripAnsi(source).trimEnd() };
|
|
11
|
+
function documentSelectionAnchor(row, source, liveFromBottom) {
|
|
12
|
+
return { kind: "document", row, source, identity: stripAnsi(source).trimEnd(), liveFromBottom };
|
|
13
|
+
}
|
|
14
|
+
function viewportSelectionAnchor(row, source, selectableDocumentRowCount, documentRowCount) {
|
|
15
|
+
return row < selectableDocumentRowCount
|
|
16
|
+
? documentSelectionAnchor(row, source)
|
|
17
|
+
: { kind: "transient", fromBottom: documentRowCount - row - 1 };
|
|
13
18
|
}
|
|
14
19
|
const DEFAULT_CONFIG = {
|
|
15
20
|
scrollbarAppearance: "auto",
|
|
@@ -53,6 +58,7 @@ export class TranscriptViewport {
|
|
|
53
58
|
#previousVisibleStates = [];
|
|
54
59
|
#documentRows = [];
|
|
55
60
|
#selectableDocumentRowCount = 0;
|
|
61
|
+
#liveTailStartRow;
|
|
56
62
|
#promptAnchors = [];
|
|
57
63
|
#contentWidth = 0;
|
|
58
64
|
#selectionWidth = 0;
|
|
@@ -91,7 +97,7 @@ export class TranscriptViewport {
|
|
|
91
97
|
get hasSelection() { return orderedTextSelection(this.#selection) !== undefined; }
|
|
92
98
|
/** True when the active gesture began on transcript rows rather than the dock. */
|
|
93
99
|
get selectionFromContent() { return this.#selectionAnchors !== undefined && this.#selectionAnchors.anchor.kind !== "dock"; }
|
|
94
|
-
pressSelection(column, frameRow, now = Date.now()) {
|
|
100
|
+
pressSelection(column, frameRow, now = Date.now(), options = {}) {
|
|
95
101
|
const frameHeight = this.#frame?.rows.length ?? 0;
|
|
96
102
|
const selectionWidth = frameRow <= (this.#frame?.hits.viewportHeight ?? 0)
|
|
97
103
|
? this.#contentWidth
|
|
@@ -105,7 +111,7 @@ export class TranscriptViewport {
|
|
|
105
111
|
contentWidth: selectionWidth,
|
|
106
112
|
lineText: this.#selectionRows[line] ?? "",
|
|
107
113
|
lineContent: usefulTextLineContent(this.#selectionRows[line] ?? ""),
|
|
108
|
-
...(this.#selectionClick
|
|
114
|
+
...(options.continueMultiClick !== false && this.#selectionClick !== undefined ? { previousClick: this.#selectionClick } : {}),
|
|
109
115
|
now,
|
|
110
116
|
});
|
|
111
117
|
this.#selection = pressed.selection;
|
|
@@ -176,7 +182,29 @@ export class TranscriptViewport {
|
|
|
176
182
|
const selection = this.#visibleSelection();
|
|
177
183
|
if (selection === undefined)
|
|
178
184
|
return null;
|
|
179
|
-
|
|
185
|
+
// Invariant: the blue range spans the complete frame, but automatic and Ctrl+C frame copy
|
|
186
|
+
// admit only persistent transcript rows. Transient status, suggestions, input, and footer
|
|
187
|
+
// chrome remain visually selectable without becoming clipboard payload.
|
|
188
|
+
const copiedLines = Array.from({ length: Math.max(0, selection.end.line - selection.start.line + 1) }, (_value, index) => selection.start.line + index).filter(line => {
|
|
189
|
+
const anchor = this.#selectionRowAnchors[line];
|
|
190
|
+
return anchor?.kind === "document" && anchor.row < this.#selectableDocumentRowCount;
|
|
191
|
+
});
|
|
192
|
+
if (copiedLines.length === 0)
|
|
193
|
+
return null;
|
|
194
|
+
// Rationale: a prompt selected by itself uses semantic prompt text. Once surrounding transcript text
|
|
195
|
+
// participates, preserve the prompt's visible prefix, alignment, and timestamp in the bulk range.
|
|
196
|
+
const prompt = this.#promptAnchors.find(candidate => copiedLines.every(line => {
|
|
197
|
+
const anchor = this.#selectionRowAnchors[line];
|
|
198
|
+
return anchor?.kind === "document" && anchor.row >= candidate.firstRow && anchor.row <= candidate.lastRow;
|
|
199
|
+
}));
|
|
200
|
+
const included = new Set(copiedLines);
|
|
201
|
+
const text = textSelectionText(selection, this.#selectionRows, line => {
|
|
202
|
+
const row = this.#selectionRows[line] ?? "";
|
|
203
|
+
const anchor = this.#selectionRowAnchors[line];
|
|
204
|
+
return prompt !== undefined && anchor?.kind === "document"
|
|
205
|
+
? selectionCopyLineContent(row, anchor.row === prompt.firstRow ? "first" : "continuation")
|
|
206
|
+
: usefulTextLineContent(row);
|
|
207
|
+
}, line => included.has(line));
|
|
180
208
|
return text.length === 0 ? null : text;
|
|
181
209
|
}
|
|
182
210
|
/** Captures visible selected text, not off-screen history. */
|
|
@@ -188,6 +216,8 @@ export class TranscriptViewport {
|
|
|
188
216
|
if (text === null)
|
|
189
217
|
return null;
|
|
190
218
|
text = text.trim();
|
|
219
|
+
if (text.length === 0)
|
|
220
|
+
return null;
|
|
191
221
|
const normalized = {
|
|
192
222
|
start: { line: 0, column: 0 },
|
|
193
223
|
end: { line: 0, column: Number.MAX_SAFE_INTEGER },
|
|
@@ -280,6 +310,7 @@ export class TranscriptViewport {
|
|
|
280
310
|
this.#previousVisibleStates = [];
|
|
281
311
|
this.#documentRows = [];
|
|
282
312
|
this.#selectableDocumentRowCount = 0;
|
|
313
|
+
this.#liveTailStartRow = undefined;
|
|
283
314
|
this.#promptAnchors = [];
|
|
284
315
|
this.#contentWidth = 0;
|
|
285
316
|
this.#selectionWidth = 0;
|
|
@@ -340,6 +371,9 @@ export class TranscriptViewport {
|
|
|
340
371
|
const contentWidth = presentation.reservesSpace ? Math.max(1, width - 1) : width;
|
|
341
372
|
this.#documentRows = documentRows;
|
|
342
373
|
this.#selectableDocumentRowCount = clamp(input.selectableDocumentRowCount ?? input.documentRows.length, 0, input.documentRows.length);
|
|
374
|
+
this.#liveTailStartRow = input.liveTailStartRow === undefined || !Number.isSafeInteger(input.liveTailStartRow)
|
|
375
|
+
? undefined
|
|
376
|
+
: clamp(input.liveTailStartRow, 0, this.#selectableDocumentRowCount);
|
|
343
377
|
this.#promptAnchors = input.promptAnchors;
|
|
344
378
|
this.#contentWidth = contentWidth;
|
|
345
379
|
// Invariant: dock rows remain selectable at full width; scrollable source rows
|
|
@@ -389,7 +423,7 @@ export class TranscriptViewport {
|
|
|
389
423
|
const visibleAnchors = Array.from({ length: viewportHeight }, (_value, row) => {
|
|
390
424
|
const documentRow = this.#scrollTop + row;
|
|
391
425
|
return documentRow < documentRows.length
|
|
392
|
-
?
|
|
426
|
+
? viewportSelectionAnchor(documentRow, documentRows[documentRow] ?? "", this.#selectableDocumentRowCount, documentRows.length)
|
|
393
427
|
: { kind: "screen", row, source: this.#selectionRows[row] ?? "" };
|
|
394
428
|
});
|
|
395
429
|
// Invariant: a pinned prompt is chrome over its hidden source row, which clips like off-screen rows.
|
|
@@ -486,7 +520,7 @@ export class TranscriptViewport {
|
|
|
486
520
|
// Invariant: floating control styling is applied only after the row and
|
|
487
521
|
// gutter surfaces are resolved, so its inline background cannot leak.
|
|
488
522
|
const withControl = rowControl === null ? withRail : overlaySpan(withRail, rowControl.left, rowControl.right, rowControl.text);
|
|
489
|
-
return overlayWidth === 0 ? withControl : overlaySpan(padRowPreservingBackground(withControl, width), overlayLimit - overlayWidth, overlayLimit, `${
|
|
523
|
+
return overlayWidth === 0 ? withControl : overlaySpan(padRowPreservingBackground(withControl, width), overlayLimit - overlayWidth, overlayLimit, `${GUTTER_DECORATION_RESET}${overlayText}`, { inheritStartStyle: true });
|
|
490
524
|
});
|
|
491
525
|
rowRecomputed ||= !final.reused;
|
|
492
526
|
frameRows[row] = final.value;
|
|
@@ -643,17 +677,30 @@ export class TranscriptViewport {
|
|
|
643
677
|
return undefined;
|
|
644
678
|
if (line < this.#viewportHeight) {
|
|
645
679
|
const existing = this.#selectionRowAnchors[line];
|
|
646
|
-
if (this.#frame?.scrollTop === this.#scrollTop)
|
|
647
|
-
return existing
|
|
680
|
+
if (this.#frame?.scrollTop === this.#scrollTop) {
|
|
681
|
+
return existing?.kind === "document"
|
|
682
|
+
? this.#interactionDocumentAnchor(existing.row, existing.source)
|
|
683
|
+
: existing;
|
|
684
|
+
}
|
|
648
685
|
// Concurrency: selection edge auto-scroll updates scrollTop before the next frame is
|
|
649
686
|
// composed. Resolve ordinary viewport rows from that latest position instead of stale paint.
|
|
650
687
|
const documentRow = this.#scrollTop + line;
|
|
651
688
|
if (documentRow >= 0 && documentRow < this.#documentRows.length) {
|
|
652
|
-
return
|
|
689
|
+
return documentRow < this.#selectableDocumentRowCount
|
|
690
|
+
? this.#interactionDocumentAnchor(documentRow, this.#documentRows[documentRow] ?? "")
|
|
691
|
+
: viewportSelectionAnchor(documentRow, this.#documentRows[documentRow] ?? "", this.#selectableDocumentRowCount, this.#documentRows.length);
|
|
653
692
|
}
|
|
654
693
|
}
|
|
655
694
|
return this.#selectionRowAnchors[line];
|
|
656
695
|
}
|
|
696
|
+
#interactionDocumentAnchor(row, source) {
|
|
697
|
+
const liveFromBottom = this.#liveTailStartRow !== undefined
|
|
698
|
+
&& row >= this.#liveTailStartRow
|
|
699
|
+
&& row < this.#selectableDocumentRowCount
|
|
700
|
+
? this.#selectableDocumentRowCount - row - 1
|
|
701
|
+
: undefined;
|
|
702
|
+
return documentSelectionAnchor(row, source, liveFromBottom);
|
|
703
|
+
}
|
|
657
704
|
#projectSelection(documentRows, dockRows, height) {
|
|
658
705
|
const selection = this.#selection;
|
|
659
706
|
const anchors = this.#selectionAnchors;
|
|
@@ -672,9 +719,16 @@ export class TranscriptViewport {
|
|
|
672
719
|
? undefined
|
|
673
720
|
: { line: anchor.row, anchor };
|
|
674
721
|
}
|
|
722
|
+
if (anchor.kind === "transient") {
|
|
723
|
+
const documentRow = documentRows.length - anchor.fromBottom - 1;
|
|
724
|
+
if (documentRow < this.#selectableDocumentRowCount || documentRow >= documentRows.length)
|
|
725
|
+
return undefined;
|
|
726
|
+
const visible = this.#selectionRowAnchors.findIndex(candidate => candidate?.kind === "transient" && candidate.fromBottom === anchor.fromBottom);
|
|
727
|
+
return visible < 0 ? undefined : { line: visible, anchor };
|
|
728
|
+
}
|
|
675
729
|
if (anchor.row >= 0 && anchor.row < documentRows.length
|
|
676
730
|
&& stripAnsi(documentRows[anchor.row] ?? "").trimEnd() === anchor.identity) {
|
|
677
|
-
const current = documentSelectionAnchor(anchor.row, documentRows[anchor.row] ?? "");
|
|
731
|
+
const current = documentSelectionAnchor(anchor.row, documentRows[anchor.row] ?? "", anchor.liveFromBottom);
|
|
678
732
|
const visible = this.#selectionRowAnchors.findIndex(candidate => candidate?.kind === "document"
|
|
679
733
|
&& candidate.row === current.row && candidate.identity === current.identity);
|
|
680
734
|
return { line: visible >= 0 ? visible : current.row - this.#scrollTop, anchor: current };
|
|
@@ -684,9 +738,29 @@ export class TranscriptViewport {
|
|
|
684
738
|
const visibleMatches = this.#selectionRowAnchors
|
|
685
739
|
.map((candidate, line) => ({ candidate, line }))
|
|
686
740
|
.filter((entry) => entry.candidate?.kind === "document" && entry.candidate.identity === anchor.identity);
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
741
|
+
if (visibleMatches.length === 1) {
|
|
742
|
+
const match = visibleMatches[0];
|
|
743
|
+
return {
|
|
744
|
+
line: match.line,
|
|
745
|
+
anchor: documentSelectionAnchor(match.candidate.row, match.candidate.source, anchor.liveFromBottom),
|
|
746
|
+
};
|
|
747
|
+
}
|
|
748
|
+
// Concurrency: a streaming chunk may replace or reflow the pointer's current live-tail
|
|
749
|
+
// row before the next motion report. During the held gesture only, retain its distance
|
|
750
|
+
// from the persistent tail; release restores identity-only projection.
|
|
751
|
+
if (selection.selecting && anchor.liveFromBottom !== undefined && this.#liveTailStartRow !== undefined) {
|
|
752
|
+
const documentRow = this.#selectableDocumentRowCount - anchor.liveFromBottom - 1;
|
|
753
|
+
if (documentRow >= this.#liveTailStartRow && documentRow < this.#selectableDocumentRowCount) {
|
|
754
|
+
const visible = this.#selectionRowAnchors.findIndex(candidate => candidate?.kind === "document" && candidate.row === documentRow);
|
|
755
|
+
if (visible >= 0) {
|
|
756
|
+
return {
|
|
757
|
+
line: visible,
|
|
758
|
+
anchor: documentSelectionAnchor(documentRow, documentRows[documentRow] ?? "", anchor.liveFromBottom),
|
|
759
|
+
};
|
|
760
|
+
}
|
|
761
|
+
}
|
|
762
|
+
}
|
|
763
|
+
return undefined;
|
|
690
764
|
};
|
|
691
765
|
const projectedAnchor = project(anchors.anchor);
|
|
692
766
|
const projectedHead = project(anchors.head);
|
|
@@ -704,7 +778,11 @@ export class TranscriptViewport {
|
|
|
704
778
|
};
|
|
705
779
|
}
|
|
706
780
|
#visibleSelection() {
|
|
707
|
-
const
|
|
781
|
+
const anchors = this.#selectionAnchors;
|
|
782
|
+
const crossesDock = anchors?.anchor.kind === "dock" || anchors?.head.kind === "dock";
|
|
783
|
+
// Invariant: mixed viewport/dock ranges project across the same complete frame regardless
|
|
784
|
+
// of origin. Document-only ranges remain clipped to the scrollable viewport when off-screen.
|
|
785
|
+
const rows = crossesDock ? this.#selectionRows.length : this.#viewportHeight;
|
|
708
786
|
return visibleTextSelection(orderedTextSelection(this.#selection), rows, this.#firstSelectableRow);
|
|
709
787
|
}
|
|
710
788
|
#updateCopyableSelection() {
|
|
@@ -7,6 +7,8 @@ import type { UiTheme } from "./theme.js";
|
|
|
7
7
|
export interface ValueMenuState {
|
|
8
8
|
/** Values offered, as they should read. */
|
|
9
9
|
readonly choices: readonly string[];
|
|
10
|
+
/** Optional already-painted square previews, aligned before each choice label. */
|
|
11
|
+
readonly previews?: readonly string[];
|
|
10
12
|
/** The value in effect, marked rather than highlighted. */
|
|
11
13
|
readonly current: string | null;
|
|
12
14
|
/** The entry picked by a key or the pointer, or -1 while none is. */
|
|
@@ -8,10 +8,12 @@ export function valueMenuFrame(state, anchor, layout) {
|
|
|
8
8
|
const top = below + state.choices.length <= bodyBottom
|
|
9
9
|
? below
|
|
10
10
|
: Math.max(bodyTop, anchor.screenRow - state.choices.length);
|
|
11
|
-
const
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
11
|
+
const previewWidth = Math.max(0, ...(state.previews ?? []).map(displayWidth));
|
|
12
|
+
const previewColumns = previewWidth === 0 ? 0 : previewWidth + 1;
|
|
13
|
+
const width = Math.max(...state.choices.map(choice => displayWidth(choice) + previewColumns + 4), 6);
|
|
14
|
+
// Invariant: rows reserve two cells for the effective-value mark and, when present,
|
|
15
|
+
// a preview plus one gap. Choice text remains aligned with the source value column.
|
|
16
|
+
const column = Math.min(Math.max(0, anchor.valueColumn - 2 - previewColumns), Math.max(0, layout.surfaceWidth - width - layout.reservedRight));
|
|
15
17
|
return { top, column, width, rows: state.choices.length };
|
|
16
18
|
}
|
|
17
19
|
/** Draws the menu over the rows behind it, leaving them otherwise untouched. */
|
|
@@ -24,11 +26,14 @@ export function renderValueMenu(lines, state, frame, theme) {
|
|
|
24
26
|
const active = index === state.index;
|
|
25
27
|
const paint = active ? theme.highlight : theme.panel;
|
|
26
28
|
const current = choice === state.current;
|
|
27
|
-
const
|
|
28
|
-
|
|
29
|
-
|
|
29
|
+
const previews = state.previews ?? [];
|
|
30
|
+
const previewWidth = Math.max(0, ...previews.map(displayWidth));
|
|
31
|
+
const preview = previewWidth === 0 ? "" : `${padToWidth(previews[index] ?? "", previewWidth)} `;
|
|
32
|
+
// Invariant: the current-value check stays on ordinary text while the optional
|
|
33
|
+
// square carries the palette color; the row treatment supplies only its surface.
|
|
34
|
+
const tail = padToWidth(`${current ? " " : " "}${preview}${choice} `, frame.width - (current ? 1 : 0));
|
|
30
35
|
const painted = current
|
|
31
|
-
? `${paint(theme.fg("
|
|
36
|
+
? `${paint(theme.fg("text", "✓"))}${paint(tail)}`
|
|
32
37
|
: paint(tail);
|
|
33
38
|
output[target] = overlaySpan(output[target] ?? "", frame.column, frame.column + frame.width, painted);
|
|
34
39
|
});
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export declare const OWNED_UI_SETTINGS_VERSION =
|
|
1
|
+
export declare const OWNED_UI_SETTINGS_VERSION = 12;
|
|
2
2
|
export type OwnedUiSettingValue = string | number | boolean;
|
|
3
3
|
export type OwnedUiSettingApplication = "live" | "restart";
|
|
4
4
|
export interface OwnedUiSettingDeclaration {
|
|
@@ -20,18 +20,6 @@ export interface OwnedUiSettingDeclaration {
|
|
|
20
20
|
* values are read from it, and `OwnedSettingValueOf` derives each getter's type from it.
|
|
21
21
|
*/
|
|
22
22
|
export declare const OWNED_SETTING_DECLARATIONS: Readonly<{
|
|
23
|
-
readonly quitAnimation: Readonly<{
|
|
24
|
-
id: "quitAnimation";
|
|
25
|
-
label: "Quit animation";
|
|
26
|
-
section: Readonly<{
|
|
27
|
-
id: "generic";
|
|
28
|
-
title: "Generic";
|
|
29
|
-
}>;
|
|
30
|
-
description: "Play the fall effect over the last screen when the session quits. Off returns to the terminal immediately.";
|
|
31
|
-
application: "live";
|
|
32
|
-
defaultValue: true;
|
|
33
|
-
allowedValues: readonly [true, false];
|
|
34
|
-
}>;
|
|
35
23
|
readonly updateCheck: Readonly<{
|
|
36
24
|
id: "updateCheck";
|
|
37
25
|
label: "Update check";
|
|
@@ -44,6 +32,30 @@ export declare const OWNED_SETTING_DECLARATIONS: Readonly<{
|
|
|
44
32
|
defaultValue: true;
|
|
45
33
|
allowedValues: readonly [true, false];
|
|
46
34
|
}>;
|
|
35
|
+
readonly accentColor: Readonly<{
|
|
36
|
+
id: "accentColor";
|
|
37
|
+
label: "Accent color";
|
|
38
|
+
section: Readonly<{
|
|
39
|
+
id: "appearance";
|
|
40
|
+
title: "Appearance";
|
|
41
|
+
}>;
|
|
42
|
+
description: "Color used by highlighted interface controls, list markers, and tonal interface surfaces.";
|
|
43
|
+
application: "live";
|
|
44
|
+
defaultValue: "purple";
|
|
45
|
+
allowedValues: readonly ["purple", "blue", "cyan", "green", "orange", "pink"];
|
|
46
|
+
}>;
|
|
47
|
+
readonly quitAnimation: Readonly<{
|
|
48
|
+
id: "quitAnimation";
|
|
49
|
+
label: "Quit animation";
|
|
50
|
+
section: Readonly<{
|
|
51
|
+
id: "appearance";
|
|
52
|
+
title: "Appearance";
|
|
53
|
+
}>;
|
|
54
|
+
description: "Play the fall effect over the last screen when the session quits. Off returns to the terminal immediately.";
|
|
55
|
+
application: "live";
|
|
56
|
+
defaultValue: true;
|
|
57
|
+
allowedValues: readonly [true, false];
|
|
58
|
+
}>;
|
|
47
59
|
readonly scrollbarAppearance: Readonly<{
|
|
48
60
|
id: "scrollbarAppearance";
|
|
49
61
|
label: "Scrollbar mode";
|
|
@@ -111,7 +123,7 @@ export declare const OWNED_SETTING_DECLARATIONS: Readonly<{
|
|
|
111
123
|
id: "agent";
|
|
112
124
|
title: "Agent";
|
|
113
125
|
}>;
|
|
114
|
-
description: "Predict likely next prompts with one
|
|
126
|
+
description: "Predict likely next prompts with one background request, plus one bounded recovery request when needed, using the selected model.";
|
|
115
127
|
application: "live";
|
|
116
128
|
defaultValue: true;
|
|
117
129
|
allowedValues: readonly [true, false];
|
|
@@ -1,8 +1,12 @@
|
|
|
1
|
-
export const OWNED_UI_SETTINGS_VERSION =
|
|
1
|
+
export const OWNED_UI_SETTINGS_VERSION = 12;
|
|
2
|
+
const UI_ACCENT_COLOR_CHOICES = Object.freeze([
|
|
3
|
+
"purple", "blue", "cyan", "green", "orange", "pink",
|
|
4
|
+
]);
|
|
2
5
|
const MAX_ID_LENGTH = 64;
|
|
3
6
|
const ID_PATTERN = /^[a-z][a-z0-9]*(?:[A-Z][a-z0-9]*)*$/;
|
|
4
7
|
/** Declared first so the settings screen opens on it; sections follow first-declaration order. */
|
|
5
8
|
const GENERIC_SECTION = Object.freeze({ id: "generic", title: "Generic" });
|
|
9
|
+
const APPEARANCE_SECTION = Object.freeze({ id: "appearance", title: "Appearance" });
|
|
6
10
|
const SCROLL_SECTION = Object.freeze({ id: "scroll", title: "Scroll" });
|
|
7
11
|
const AGENT_SECTION = Object.freeze({ id: "agent", title: "Agent" });
|
|
8
12
|
/**
|
|
@@ -10,15 +14,6 @@ const AGENT_SECTION = Object.freeze({ id: "agent", title: "Agent" });
|
|
|
10
14
|
* values are read from it, and `OwnedSettingValueOf` derives each getter's type from it.
|
|
11
15
|
*/
|
|
12
16
|
export const OWNED_SETTING_DECLARATIONS = Object.freeze({
|
|
13
|
-
quitAnimation: Object.freeze({
|
|
14
|
-
id: "quitAnimation",
|
|
15
|
-
label: "Quit animation",
|
|
16
|
-
section: GENERIC_SECTION,
|
|
17
|
-
description: "Play the fall effect over the last screen when the session quits. Off returns to the terminal immediately.",
|
|
18
|
-
application: "live",
|
|
19
|
-
defaultValue: true,
|
|
20
|
-
allowedValues: Object.freeze([true, false]),
|
|
21
|
-
}),
|
|
22
17
|
updateCheck: Object.freeze({
|
|
23
18
|
id: "updateCheck",
|
|
24
19
|
label: "Update check",
|
|
@@ -28,6 +23,24 @@ export const OWNED_SETTING_DECLARATIONS = Object.freeze({
|
|
|
28
23
|
defaultValue: true,
|
|
29
24
|
allowedValues: Object.freeze([true, false]),
|
|
30
25
|
}),
|
|
26
|
+
accentColor: Object.freeze({
|
|
27
|
+
id: "accentColor",
|
|
28
|
+
label: "Accent color",
|
|
29
|
+
section: APPEARANCE_SECTION,
|
|
30
|
+
description: "Color used by highlighted interface controls, list markers, and tonal interface surfaces.",
|
|
31
|
+
application: "live",
|
|
32
|
+
defaultValue: "purple",
|
|
33
|
+
allowedValues: UI_ACCENT_COLOR_CHOICES,
|
|
34
|
+
}),
|
|
35
|
+
quitAnimation: Object.freeze({
|
|
36
|
+
id: "quitAnimation",
|
|
37
|
+
label: "Quit animation",
|
|
38
|
+
section: APPEARANCE_SECTION,
|
|
39
|
+
description: "Play the fall effect over the last screen when the session quits. Off returns to the terminal immediately.",
|
|
40
|
+
application: "live",
|
|
41
|
+
defaultValue: true,
|
|
42
|
+
allowedValues: Object.freeze([true, false]),
|
|
43
|
+
}),
|
|
31
44
|
scrollbarAppearance: Object.freeze({
|
|
32
45
|
id: "scrollbarAppearance",
|
|
33
46
|
label: "Scrollbar mode",
|
|
@@ -77,7 +90,7 @@ export const OWNED_SETTING_DECLARATIONS = Object.freeze({
|
|
|
77
90
|
id: "promptSuggestions",
|
|
78
91
|
label: "Prompt suggestions",
|
|
79
92
|
section: AGENT_SECTION,
|
|
80
|
-
description: "Predict likely next prompts with one
|
|
93
|
+
description: "Predict likely next prompts with one background request, plus one bounded recovery request when needed, using the selected model.",
|
|
81
94
|
application: "live",
|
|
82
95
|
defaultValue: true,
|
|
83
96
|
allowedValues: Object.freeze([true, false]),
|
|
@@ -81,6 +81,22 @@ export const OWNED_UI_SETTINGS_MIGRATIONS = Object.freeze([
|
|
|
81
81
|
return { ...values };
|
|
82
82
|
},
|
|
83
83
|
}),
|
|
84
|
+
Object.freeze({
|
|
85
|
+
to: 11,
|
|
86
|
+
description: "Introduce semantic accent selection with the active-theme default.",
|
|
87
|
+
migrate(values) {
|
|
88
|
+
return { ...values };
|
|
89
|
+
},
|
|
90
|
+
}),
|
|
91
|
+
Object.freeze({
|
|
92
|
+
to: 12,
|
|
93
|
+
description: "Rename the inherited default accent choice to explicit purple.",
|
|
94
|
+
migrate(values) {
|
|
95
|
+
return values.accentColor === "default"
|
|
96
|
+
? { ...values, accentColor: "purple" }
|
|
97
|
+
: { ...values };
|
|
98
|
+
},
|
|
99
|
+
}),
|
|
84
100
|
]);
|
|
85
101
|
export function assertOwnedUiSettingsMigrations(migrations, currentVersion = OWNED_UI_SETTINGS_VERSION) {
|
|
86
102
|
const firstProduced = currentVersion - migrations.length + 1;
|
|
@@ -92,18 +92,19 @@ Build output mirrors the production namespaces directly under ignored `dist/`, w
|
|
|
92
92
|
|
|
93
93
|
Every task worktree must be created at `{working-dir}/.worktrees/<task-id>`, where `{working-dir}` is the agent session's initial working directory. The `.worktrees` directory is inside that working directory, not beside it. For working directory `D:/Git/a1`, `D:/Git/a1/.worktrees/<task-id>` is correct and `D:/Git/a1-<task-id>` is forbidden.
|
|
94
94
|
|
|
95
|
-
From the initial working directory,
|
|
95
|
+
From the initial working directory, run `a1 session worktrees` to inspect cooperative live ownership before selecting an existing checkout. A `busy` or `unverifiable` worktree is unavailable. An `available` checkout may be reused only when its exact branch, OpenSpec change, and pull request match the requested stream and atomic `a1 session link-worktree <absolute-worktree>` succeeds; names, similar files, recency, cleanliness, and ancestry are not ownership evidence. Otherwise create a fresh task branch/worktree, link it from the owning A1 session, and continue to address it explicitly:
|
|
96
96
|
|
|
97
97
|
```sh
|
|
98
|
+
a1 session worktrees
|
|
98
99
|
git fetch origin develop
|
|
99
100
|
git worktree add -b <type>/<short-description> .worktrees/<task-id> origin/develop
|
|
100
101
|
a1 session link-worktree <absolute-worktree>
|
|
101
102
|
git -C .worktrees/<task-id> status
|
|
102
103
|
```
|
|
103
104
|
|
|
104
|
-
A successful link response confirming the exact canonical worktree is required before planning, implementation, test, or delivery-documentation edits. If linking fails or confirms another path, stop task edits and report the blocker
|
|
105
|
+
Inventory is read-only and advisory because another runtime may win a later race. A successful link response confirming the exact canonical worktree is required before planning, implementation, test, or delivery-documentation edits. If inventory or linking fails, reports a live/unverifiable owner, loses a race, or confirms another path, stop task edits and report the blocker; use a separate fresh worktree rather than overriding, unlinking, or recovering that owner. A session resuming an existing delivery or switching streams atomically claims and links the exact worktree before editing it.
|
|
105
106
|
|
|
106
|
-
The
|
|
107
|
+
The link acquires a cooperative live-session editing claim and switches bare A1's footer repository context and pull-request discovery. It does not change process or tool cwd, create a Git worktree lock, or register, release, or authorize cleanup. Clean unlink/disposal releases live editing authority; a crashed owner becomes reusable only after exact process death is verified. Repository commands therefore keep an explicit worktree path. The primary worktree stays on `develop` for integration and must not be used for task edits. Do not edit, adopt, move, or remove another session's worktree.
|
|
107
108
|
|
|
108
109
|
An agent that directly chooses a transient file path for a PR/comment body, command payload, captured output, temporary patch/diff, or ad hoc log must place it beneath the linked worktree's exact `.artifacts/` root, never the primary checkout, another worktree, OS temp, home/desktop, or a sibling path. Such scratch remains ignored, unstaged, uncommitted, disposable, non-authoritative, and secret-free. This repository path rule does not relocate storage internally selected by tools, product runtime code, or hermetic tests.
|
|
109
110
|
|