@aragon-agent/cli 0.6.34 → 0.6.36
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/CHANGELOG.md +21 -0
- package/README.md +173 -7
- package/dist/agent/agent-mode.d.ts +20 -4
- package/dist/agent/agent-mode.js +20 -4
- package/dist/agent/controller.d.ts +67 -3
- package/dist/agent/controller.js +106 -5
- package/dist/agent/headless.js +31 -0
- package/dist/agent/kit-apply.d.ts +56 -0
- package/dist/agent/kit-apply.js +209 -0
- package/dist/agent/model-profile-settings.d.ts +28 -0
- package/dist/agent/model-profile-settings.js +142 -29
- package/dist/agent/reducer.d.ts +13 -2
- package/dist/agent/reducer.js +1 -0
- package/dist/cli.js +12 -0
- package/dist/commands/agents-command.d.ts +15 -0
- package/dist/commands/agents-command.js +27 -0
- package/dist/commands/builtins.js +135 -4
- package/dist/commands/kit-command.d.ts +20 -0
- package/dist/commands/kit-command.js +131 -0
- package/dist/commands/perf.d.ts +11 -0
- package/dist/commands/perf.js +2 -1
- package/dist/commands/registry.d.ts +14 -0
- package/dist/config/app-paths.d.ts +15 -0
- package/dist/config/app-paths.js +33 -2
- package/dist/config/env.d.ts +4 -1
- package/dist/config/env.js +28 -2
- package/dist/config/kit-resolution.d.ts +93 -0
- package/dist/config/kit-resolution.js +226 -0
- package/dist/config/load.d.ts +10 -0
- package/dist/config/load.js +8 -1
- package/dist/config/model-kits.d.ts +224 -0
- package/dist/config/model-kits.js +302 -0
- package/dist/config/model-profile-store.d.ts +25 -0
- package/dist/config/model-profiles.d.ts +41 -3
- package/dist/config/model-profiles.js +46 -5
- package/dist/config/schema.d.ts +84 -0
- package/dist/config/schema.js +39 -0
- package/dist/config/store.js +12 -1
- package/dist/config/ui-state.d.ts +18 -0
- package/dist/config/ui-state.js +9 -0
- package/dist/exec/events.d.ts +25 -0
- package/dist/exec/events.js +4 -0
- package/dist/exec/index.js +16 -1
- package/dist/exec/runner.js +10 -0
- package/dist/input/keymap.js +18 -4
- package/dist/proc/limits.d.ts +16 -0
- package/dist/proc/limits.js +16 -0
- package/dist/proc/supervisor.d.ts +20 -1
- package/dist/proc/supervisor.js +42 -14
- package/dist/prompts/command.d.ts +34 -0
- package/dist/prompts/command.js +237 -0
- package/dist/prompts/copy.d.ts +89 -0
- package/dist/prompts/copy.js +131 -0
- package/dist/prompts/fill.d.ts +51 -0
- package/dist/prompts/fill.js +46 -0
- package/dist/prompts/limits.d.ts +53 -0
- package/dist/prompts/limits.js +53 -0
- package/dist/prompts/normalize.d.ts +53 -0
- package/dist/prompts/normalize.js +190 -0
- package/dist/prompts/resolve.d.ts +31 -0
- package/dist/prompts/resolve.js +60 -0
- package/dist/prompts/search.d.ts +58 -0
- package/dist/prompts/search.js +146 -0
- package/dist/prompts/store.d.ts +86 -0
- package/dist/prompts/store.js +453 -0
- package/dist/prompts/types.d.ts +204 -0
- package/dist/prompts/types.js +13 -0
- package/dist/session/checkpoint.d.ts +8 -1
- package/dist/session/checkpoint.js +6 -0
- package/dist/session/persist.d.ts +19 -1
- package/dist/session/persist.js +13 -1
- package/dist/session/startup-session.d.ts +7 -2
- package/dist/session/startup-session.js +5 -2
- package/dist/session/store.js +3 -0
- package/dist/session/validate-session.js +64 -1
- package/dist/team/limits.d.ts +25 -0
- package/dist/team/limits.js +26 -0
- package/dist/team/runtime.js +27 -2
- package/dist/team/settled.d.ts +57 -0
- package/dist/team/settled.js +87 -0
- package/dist/team/subagent.js +48 -2
- package/dist/team/timeline.d.ts +74 -0
- package/dist/team/timeline.js +101 -0
- package/dist/team/types.d.ts +24 -1
- package/dist/todo/acceptance.d.ts +120 -0
- package/dist/todo/acceptance.js +399 -0
- package/dist/todo/follow-through.d.ts +48 -23
- package/dist/todo/follow-through.js +110 -44
- package/dist/todo/limits.d.ts +62 -1
- package/dist/todo/limits.js +62 -1
- package/dist/todo/panel-rows.d.ts +29 -39
- package/dist/todo/panel-rows.js +37 -83
- package/dist/todo/plan-sections.d.ts +60 -0
- package/dist/todo/plan-sections.js +108 -0
- package/dist/todo/prompt.d.ts +17 -12
- package/dist/todo/prompt.js +59 -40
- package/dist/todo/row-window.d.ts +51 -0
- package/dist/todo/row-window.js +107 -0
- package/dist/todo/store.d.ts +139 -31
- package/dist/todo/store.js +271 -73
- package/dist/todo/todo-tool.d.ts +33 -8
- package/dist/todo/todo-tool.js +186 -30
- package/dist/todo/types.d.ts +58 -0
- package/dist/ui/App.js +414 -54
- package/dist/ui/Composer.d.ts +6 -2
- package/dist/ui/Composer.js +2 -2
- package/dist/ui/Header.d.ts +17 -1
- package/dist/ui/Header.js +8 -2
- package/dist/ui/PromptInput.d.ts +21 -1
- package/dist/ui/PromptInput.js +22 -2
- package/dist/ui/ScrollbackShell.d.ts +22 -7
- package/dist/ui/ScrollbackShell.js +8 -1
- package/dist/ui/StatusBar.d.ts +18 -0
- package/dist/ui/StatusBar.js +11 -3
- package/dist/ui/TeamPanel.d.ts +35 -41
- package/dist/ui/TeamPanel.js +53 -163
- package/dist/ui/TodoPanel.d.ts +17 -14
- package/dist/ui/TodoPanel.js +146 -38
- package/dist/ui/Transcript.js +23 -3
- package/dist/ui/composer-input.d.ts +10 -0
- package/dist/ui/composer-input.js +57 -24
- package/dist/ui/entries/TeamCard.d.ts +18 -2
- package/dist/ui/entries/TeamCard.js +47 -13
- package/dist/ui/entries/TodoCard.d.ts +26 -11
- package/dist/ui/entries/TodoCard.js +56 -15
- package/dist/ui/glyphs.d.ts +19 -0
- package/dist/ui/glyphs.js +4 -0
- package/dist/ui/layout/agents-board.d.ts +102 -0
- package/dist/ui/layout/agents-board.js +389 -0
- package/dist/ui/layout/cells.d.ts +61 -0
- package/dist/ui/layout/cells.js +156 -0
- package/dist/ui/layout/header-hints.d.ts +23 -3
- package/dist/ui/layout/header-hints.js +73 -7
- package/dist/ui/layout/kit-chip.d.ts +50 -0
- package/dist/ui/layout/kit-chip.js +81 -0
- package/dist/ui/layout/status-detail-layout.js +9 -0
- package/dist/ui/layout/status-layout.d.ts +13 -0
- package/dist/ui/layout/team-row.d.ts +139 -0
- package/dist/ui/layout/team-row.js +246 -0
- package/dist/ui/layout/todo-layout.d.ts +38 -0
- package/dist/ui/layout/todo-layout.js +75 -0
- package/dist/ui/layout/virtual-window.js +32 -3
- package/dist/ui/overlays/AgentsBoardOverlay.d.ts +57 -0
- package/dist/ui/overlays/AgentsBoardOverlay.js +183 -0
- package/dist/ui/overlays/HelpOverlay.js +24 -2
- package/dist/ui/overlays/KitEditor.d.ts +23 -0
- package/dist/ui/overlays/KitEditor.js +101 -0
- package/dist/ui/overlays/KitManager.d.ts +23 -0
- package/dist/ui/overlays/KitManager.js +104 -0
- package/dist/ui/overlays/KitPicker.d.ts +49 -0
- package/dist/ui/overlays/KitPicker.js +58 -0
- package/dist/ui/overlays/ModelProfilePicker.js +16 -6
- package/dist/ui/overlays/PromptEditorPage.d.ts +48 -0
- package/dist/ui/overlays/PromptEditorPage.js +227 -0
- package/dist/ui/overlays/PromptLibraryOverlay.d.ts +37 -0
- package/dist/ui/overlays/PromptLibraryOverlay.js +191 -0
- package/dist/ui/overlays/PromptPicker.d.ts +36 -0
- package/dist/ui/overlays/PromptPicker.js +129 -0
- package/dist/ui/overlays/PromptTextArea.d.ts +86 -0
- package/dist/ui/overlays/PromptTextArea.js +141 -0
- package/dist/ui/overlays/SettingsScreen.js +139 -16
- package/dist/ui/overlays/kit-picker-state.d.ts +87 -0
- package/dist/ui/overlays/kit-picker-state.js +136 -0
- package/dist/ui/overlays/kit-settings-state.d.ts +129 -0
- package/dist/ui/overlays/kit-settings-state.js +267 -0
- package/dist/ui/overlays/model-profile-state.d.ts +26 -3
- package/dist/ui/overlays/model-profile-state.js +59 -6
- package/dist/ui/overlays/prompt-library-state.d.ts +162 -0
- package/dist/ui/overlays/prompt-library-state.js +335 -0
- package/dist/ui/overlays/prompt-picker-state.d.ts +71 -0
- package/dist/ui/overlays/prompt-picker-state.js +98 -0
- package/dist/ui/scrollback/LiveTail.d.ts +2 -2
- package/dist/ui/scrollback/LiveTail.js +7 -2
- package/dist/ui/scrollback/band.js +14 -1
- package/dist/ui/scrollback/live-preview.js +10 -3
- package/dist/ui/scrollback/tail-window.d.ts +12 -0
- package/dist/ui/scrollback/tail-window.js +17 -2
- package/dist/ui/scrollback/use-scrollback-view.js +7 -0
- package/dist/ui/team-status.d.ts +166 -0
- package/dist/ui/team-status.js +252 -0
- package/dist/ui/transcript-text.js +13 -4
- package/dist/ui/use-startup-notices.d.ts +35 -1
- package/dist/ui/use-startup-notices.js +29 -2
- package/dist/ui/use-wheel-routing.js +10 -2
- package/package.json +2 -2
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The rail's two-section row allocation (todo-acceptance-criteria §6.9.2).
|
|
3
|
+
*
|
|
4
|
+
* ASCII ONLY: `src/todo/**` is inside the glyph scanner's scope.
|
|
5
|
+
*
|
|
6
|
+
* ONE ROW IDENTITY, DEFINED BEFORE IT IS IMPLEMENTED, and it is the only
|
|
7
|
+
* bookkeeping this feature does:
|
|
8
|
+
*
|
|
9
|
+
* showGauge 1 row when the gauge rule fires (width >= 20, rows >= 8)
|
|
10
|
+
* + 1 the TODO header row
|
|
11
|
+
* + (compact ? 0 : 1) ONE blank row: the full rail has it, the compact rail does not
|
|
12
|
+
* + todoItemRows
|
|
13
|
+
* + Number(todoFooter)
|
|
14
|
+
* + (acc ? acc.headerRows + acc.itemRows : 0)
|
|
15
|
+
* <= rows
|
|
16
|
+
*
|
|
17
|
+
* `overhead = 3` appears only in the full rung with a `visible` second section:
|
|
18
|
+
* 1 TODO header + 1 blank row + 1 ACCEPT header. THAT BLANK ROW IS THE SAME ROW
|
|
19
|
+
* TWICE OVER - it is the breathing space under the TODO header AND the separator
|
|
20
|
+
* between the two sections - so counting it twice overflows the box by one row,
|
|
21
|
+
* and Ink's `overflow="hidden"` clips the overflow silently. The symptom a user
|
|
22
|
+
* reports is "the panel only shows 2 criteria", which is why this comment is at
|
|
23
|
+
* the top of the file rather than next to the arithmetic.
|
|
24
|
+
*
|
|
25
|
+
* PURE: no I/O, no timers, no imports from `ui/**`. The rail renders what this
|
|
26
|
+
* returns; `/perf` reports the `acceptance.reason` it returns; the status-bar chip
|
|
27
|
+
* asks it whether the rail is already reporting the count. One number, one owner.
|
|
28
|
+
*/
|
|
29
|
+
import type { PlanPhase } from './types.js';
|
|
30
|
+
export interface PlanSectionsInput {
|
|
31
|
+
/** The rail's whole row budget (`TodoPanel`'s `rows` prop). */
|
|
32
|
+
rows: number;
|
|
33
|
+
/** The rail's whole column budget, chrome included. */
|
|
34
|
+
width: number;
|
|
35
|
+
phase: PlanPhase;
|
|
36
|
+
todoCount: number;
|
|
37
|
+
/** 0 means "no acceptance section at all". */
|
|
38
|
+
acceptanceCount: number;
|
|
39
|
+
/** Decided by `TodoPanel` under the existing gauge rule (width >= 20, rows >= 8). */
|
|
40
|
+
showGauge: boolean;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* `visible` - header row plus item rows.
|
|
44
|
+
* `summary` - one row only (`AC 2/5`), no header, no items.
|
|
45
|
+
* `absent` - nothing at all; the count has to reach the status-bar chip (I-7).
|
|
46
|
+
*/
|
|
47
|
+
export type AcceptanceSectionReason = 'visible' | 'summary' | 'absent';
|
|
48
|
+
export interface PlanSections {
|
|
49
|
+
todoItemRows: number;
|
|
50
|
+
/** Whether the `-N +M` footer is drawn (the existing `compactFooter` semantics). */
|
|
51
|
+
todoFooter: boolean;
|
|
52
|
+
acceptance: {
|
|
53
|
+
reason: AcceptanceSectionReason;
|
|
54
|
+
/** 1 = header row drawn; 0 = summary row only. */
|
|
55
|
+
headerRows: number;
|
|
56
|
+
/** > 0 to draw item rows. */
|
|
57
|
+
itemRows: number;
|
|
58
|
+
} | null;
|
|
59
|
+
}
|
|
60
|
+
export declare function buildPlanSections(input: PlanSectionsInput): PlanSections;
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The rail's two-section row allocation (todo-acceptance-criteria §6.9.2).
|
|
3
|
+
*
|
|
4
|
+
* ASCII ONLY: `src/todo/**` is inside the glyph scanner's scope.
|
|
5
|
+
*
|
|
6
|
+
* ONE ROW IDENTITY, DEFINED BEFORE IT IS IMPLEMENTED, and it is the only
|
|
7
|
+
* bookkeeping this feature does:
|
|
8
|
+
*
|
|
9
|
+
* showGauge 1 row when the gauge rule fires (width >= 20, rows >= 8)
|
|
10
|
+
* + 1 the TODO header row
|
|
11
|
+
* + (compact ? 0 : 1) ONE blank row: the full rail has it, the compact rail does not
|
|
12
|
+
* + todoItemRows
|
|
13
|
+
* + Number(todoFooter)
|
|
14
|
+
* + (acc ? acc.headerRows + acc.itemRows : 0)
|
|
15
|
+
* <= rows
|
|
16
|
+
*
|
|
17
|
+
* `overhead = 3` appears only in the full rung with a `visible` second section:
|
|
18
|
+
* 1 TODO header + 1 blank row + 1 ACCEPT header. THAT BLANK ROW IS THE SAME ROW
|
|
19
|
+
* TWICE OVER - it is the breathing space under the TODO header AND the separator
|
|
20
|
+
* between the two sections - so counting it twice overflows the box by one row,
|
|
21
|
+
* and Ink's `overflow="hidden"` clips the overflow silently. The symptom a user
|
|
22
|
+
* reports is "the panel only shows 2 criteria", which is why this comment is at
|
|
23
|
+
* the top of the file rather than next to the arithmetic.
|
|
24
|
+
*
|
|
25
|
+
* PURE: no I/O, no timers, no imports from `ui/**`. The rail renders what this
|
|
26
|
+
* returns; `/perf` reports the `acceptance.reason` it returns; the status-bar chip
|
|
27
|
+
* asks it whether the rail is already reporting the count. One number, one owner.
|
|
28
|
+
*/
|
|
29
|
+
import { TODO_LIMITS } from './limits.js';
|
|
30
|
+
/**
|
|
31
|
+
* Clamp, and NEVER silently reverse: `clampRows` requires `lo <= hi` at the call
|
|
32
|
+
* site, which every branch below establishes before it calls (§6.9.2, P2-5).
|
|
33
|
+
* `clampRows(x, 1, 0)` would return 0 - a panel that draws no acceptance rows and
|
|
34
|
+
* says nothing about why.
|
|
35
|
+
*/
|
|
36
|
+
function clampRows(value, lo, hi) {
|
|
37
|
+
return Math.min(Math.max(value, lo), hi);
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* The share of the item budget a `work`/`done` rail gives the criteria: 0.3, so the
|
|
41
|
+
* two sections trade rows rather than one starving the other (§6.9.2 step 6). The
|
|
42
|
+
* `verify` phase does not use it - there the criteria take everything above one row.
|
|
43
|
+
*/
|
|
44
|
+
const ACCEPTANCE_SHARE = 0.3;
|
|
45
|
+
export function buildPlanSections(input) {
|
|
46
|
+
const rows = Math.max(0, Math.floor(input.rows));
|
|
47
|
+
const acceptanceCount = Math.max(0, Math.floor(input.acceptanceCount));
|
|
48
|
+
const todoCount = Math.max(0, Math.floor(input.todoCount));
|
|
49
|
+
// 1. The existing definition of "compact", unchanged.
|
|
50
|
+
const compact = rows < TODO_LIMITS.panelFullRows;
|
|
51
|
+
// 2. What is left after the gauge, unchanged.
|
|
52
|
+
const available = rows - Number(input.showGauge);
|
|
53
|
+
// 3. The existing footer rule, unchanged.
|
|
54
|
+
const todoFooter = compact && todoCount > rows - 1;
|
|
55
|
+
// 4. No criteria: BYTE-IDENTICAL to the pre-feature arithmetic (I-5).
|
|
56
|
+
if (acceptanceCount === 0) {
|
|
57
|
+
return {
|
|
58
|
+
todoItemRows: compact
|
|
59
|
+
? rows - 1 - Number(todoFooter)
|
|
60
|
+
: rows - 2 - Number(input.showGauge),
|
|
61
|
+
todoFooter,
|
|
62
|
+
acceptance: null,
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
// 5. Compact rung: rows in {3,4,5}, the gauge never fires, available === rows.
|
|
66
|
+
if (compact) {
|
|
67
|
+
const base = rows - 1 - Number(todoFooter);
|
|
68
|
+
// Lend one row to the summary line, but never the TODO window's last row.
|
|
69
|
+
// `absent` is reachable ONLY at rows === 3 with a footer (base === 1), which
|
|
70
|
+
// is the one "panel is up, section is not" combination (AC-34).
|
|
71
|
+
if (base - 1 >= 1) {
|
|
72
|
+
return {
|
|
73
|
+
todoItemRows: base - 1,
|
|
74
|
+
todoFooter,
|
|
75
|
+
acceptance: { reason: 'summary', headerRows: 0, itemRows: 1 },
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
return {
|
|
79
|
+
todoItemRows: base,
|
|
80
|
+
todoFooter,
|
|
81
|
+
acceptance: { reason: 'absent', headerRows: 0, itemRows: 0 },
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
// 6. Full rung: rows >= 6. Three rows of chrome for the second section.
|
|
85
|
+
const budget = available - 3;
|
|
86
|
+
if (input.phase === 'verify') {
|
|
87
|
+
// Every step is done, so the step list carries no information - one row says
|
|
88
|
+
// so and the rest goes to the criteria the eye is actually on (D-7).
|
|
89
|
+
return {
|
|
90
|
+
todoItemRows: 1,
|
|
91
|
+
todoFooter: false,
|
|
92
|
+
acceptance: {
|
|
93
|
+
reason: 'visible',
|
|
94
|
+
headerRows: 1,
|
|
95
|
+
itemRows: clampRows(budget - 1, 1, acceptanceCount),
|
|
96
|
+
},
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
// `work` AND `done` share this branch on purpose: a plan that just passed every
|
|
100
|
+
// criterion must keep showing the table it passed - that is the screen the user
|
|
101
|
+
// wants to read - rather than fold like `verify` does.
|
|
102
|
+
const accItemRows = clampRows(Math.round(budget * ACCEPTANCE_SHARE), 1, Math.min(acceptanceCount, budget - 1));
|
|
103
|
+
return {
|
|
104
|
+
todoItemRows: budget - accItemRows,
|
|
105
|
+
todoFooter: false,
|
|
106
|
+
acceptance: { reason: 'visible', headerRows: 1, itemRows: accItemRows },
|
|
107
|
+
};
|
|
108
|
+
}
|
package/dist/todo/prompt.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* The `<todo_planning>` system-prompt block (todo-plan-execution §3.7
|
|
2
|
+
* The `<todo_planning>` system-prompt block (todo-plan-execution §3.7;
|
|
3
|
+
* todo-acceptance-criteria §6.5).
|
|
3
4
|
*
|
|
4
5
|
* ASCII ONLY: `src/todo/**` is inside the glyph scanner's scope, and this string
|
|
5
6
|
* also reaches a model that may be running in a `cmd.exe` terminal.
|
|
@@ -7,8 +8,9 @@
|
|
|
7
8
|
* SPLICED CONDITIONALLY by `buildSystemPrompt`, which is what preserves C-10:
|
|
8
9
|
* with `todo.enabled: false` the prompt is BYTE-IDENTICAL to the pre-todo output
|
|
9
10
|
* for a fixed tool array. An unconditional guidance line anywhere here would
|
|
10
|
-
* quietly break `--no-todo`, `--no-team`, `--no-skills` and the plan-mode
|
|
11
|
-
*
|
|
11
|
+
* quietly break `--no-todo`, `--no-team`, `--no-skills` and the plan-mode snapshot
|
|
12
|
+
* all at once. The acceptance paragraph obeys the same rule one level down: with
|
|
13
|
+
* `acceptance: false` the block is byte-identical to v1.
|
|
12
14
|
*
|
|
13
15
|
* THE BLOCK'S THRESHOLD (3+ steps) IS STRICTER THAN THE STRUCTURAL GUARD
|
|
14
16
|
* (`minFreshItems`, 2). A backstop looser than the guidance never argues with a
|
|
@@ -16,24 +18,27 @@
|
|
|
16
18
|
* separate deliverables is fine, and the prompt simply does not encourage it.
|
|
17
19
|
*
|
|
18
20
|
* `TODO_BLOCK_VERSION` exists so a change to this wording is greppable from a
|
|
19
|
-
* behaviour report - INCLUDING a change to either `{{VISIBILITY}}` variant,
|
|
20
|
-
*
|
|
21
|
+
* behaviour report - INCLUDING a change to either `{{VISIBILITY}}` variant, which
|
|
22
|
+
* is part of the block.
|
|
21
23
|
*/
|
|
22
24
|
import { TODO_BLOCK_VERSION } from './limits.js';
|
|
23
25
|
export { TODO_BLOCK_VERSION };
|
|
24
26
|
export interface TodoBlockParams {
|
|
25
27
|
panelVisible: boolean;
|
|
28
|
+
/**
|
|
29
|
+
* `todo.acceptance`, read LIVE. False reproduces the v1 block byte for byte
|
|
30
|
+
* (the version constant itself is not inside the block, so it cannot spoil the
|
|
31
|
+
* comparison).
|
|
32
|
+
*/
|
|
33
|
+
acceptance: boolean;
|
|
26
34
|
}
|
|
27
35
|
/**
|
|
28
|
-
* BOUNDED AT
|
|
36
|
+
* BOUNDED AT 2400 CHARACTERS, and the number is asserted in `todo-tool.test.ts`.
|
|
29
37
|
*
|
|
30
38
|
* The block is paid for on EVERY turn of every todo-enabled session, so anything
|
|
31
39
|
* that does not change a planning decision does not belong in it (the discipline
|
|
32
|
-
* `buildTeamBlock` records at 1200 for a shorter block).
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
* planning decision, which is the test that actually applies. The bound exists
|
|
36
|
-
* so that adding a paragraph stays a decision someone makes on purpose. See
|
|
37
|
-
* spec §15 IF-3.
|
|
40
|
+
* `buildTeamBlock` records at 1200 for a shorter block). v1 landed at 1433; v2
|
|
41
|
+
* lands at 2300 (2264 for the hidden variant), and the bound exists so that adding a
|
|
42
|
+
* paragraph stays a decision someone makes on purpose rather than a drift.
|
|
38
43
|
*/
|
|
39
44
|
export declare function buildTodoBlock(params: TodoBlockParams): string;
|
package/dist/todo/prompt.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* The `<todo_planning>` system-prompt block (todo-plan-execution §3.7
|
|
2
|
+
* The `<todo_planning>` system-prompt block (todo-plan-execution §3.7;
|
|
3
|
+
* todo-acceptance-criteria §6.5).
|
|
3
4
|
*
|
|
4
5
|
* ASCII ONLY: `src/todo/**` is inside the glyph scanner's scope, and this string
|
|
5
6
|
* also reaches a model that may be running in a `cmd.exe` terminal.
|
|
@@ -7,8 +8,9 @@
|
|
|
7
8
|
* SPLICED CONDITIONALLY by `buildSystemPrompt`, which is what preserves C-10:
|
|
8
9
|
* with `todo.enabled: false` the prompt is BYTE-IDENTICAL to the pre-todo output
|
|
9
10
|
* for a fixed tool array. An unconditional guidance line anywhere here would
|
|
10
|
-
* quietly break `--no-todo`, `--no-team`, `--no-skills` and the plan-mode
|
|
11
|
-
*
|
|
11
|
+
* quietly break `--no-todo`, `--no-team`, `--no-skills` and the plan-mode snapshot
|
|
12
|
+
* all at once. The acceptance paragraph obeys the same rule one level down: with
|
|
13
|
+
* `acceptance: false` the block is byte-identical to v1.
|
|
12
14
|
*
|
|
13
15
|
* THE BLOCK'S THRESHOLD (3+ steps) IS STRICTER THAN THE STRUCTURAL GUARD
|
|
14
16
|
* (`minFreshItems`, 2). A backstop looser than the guidance never argues with a
|
|
@@ -16,61 +18,78 @@
|
|
|
16
18
|
* separate deliverables is fine, and the prompt simply does not encourage it.
|
|
17
19
|
*
|
|
18
20
|
* `TODO_BLOCK_VERSION` exists so a change to this wording is greppable from a
|
|
19
|
-
* behaviour report - INCLUDING a change to either `{{VISIBILITY}}` variant,
|
|
20
|
-
*
|
|
21
|
+
* behaviour report - INCLUDING a change to either `{{VISIBILITY}}` variant, which
|
|
22
|
+
* is part of the block.
|
|
21
23
|
*/
|
|
22
24
|
import { TODO_BLOCK_VERSION } from './limits.js';
|
|
23
25
|
export { TODO_BLOCK_VERSION };
|
|
24
26
|
/**
|
|
25
27
|
* The ONLY sentence in the block that mentions a display at all. Everything else
|
|
26
|
-
* talks about "the list", which is what makes "the two variants differ in
|
|
27
|
-
*
|
|
28
|
+
* talks about "the list", which is what makes "the two variants differ in exactly
|
|
29
|
+
* one sentence" checkable rather than approximate - and it is why the acceptance
|
|
30
|
+
* paragraph's visibility sentence is appended HERE rather than written inline:
|
|
31
|
+
* with the capability on, the variants differ in exactly TWO sentences, one per
|
|
32
|
+
* section, in the same position and the same number of lines.
|
|
28
33
|
*/
|
|
29
34
|
const VISIBLE = 'The user sees this list in a panel beside the conversation, so it is the only place ' +
|
|
30
35
|
'they can watch a long task progress.';
|
|
31
36
|
const NOT_VISIBLE = 'The user cannot see this list in this session, but keeping it is still how you stay ' +
|
|
32
37
|
'on one step at a time and report what is left.';
|
|
38
|
+
/** The acceptance section's one visibility sentence, per variant (§6.5). */
|
|
39
|
+
const ACCEPT_VISIBLE = 'The criteria are shown in the same panel, under the steps, so they are also what the ' +
|
|
40
|
+
'user watches during the final check.';
|
|
41
|
+
const ACCEPT_NOT_VISIBLE = 'The criteria are still how you keep yourself honest during the final check.';
|
|
33
42
|
/**
|
|
34
|
-
*
|
|
43
|
+
* The acceptance paragraph. Five lines of guidance, and each one is there because
|
|
44
|
+
* it changes a planning decision:
|
|
45
|
+
*
|
|
46
|
+
* - the first says criteria exist at all and belong in the SAME call;
|
|
47
|
+
* - the second names the phase transition and the one-at-a-time rule;
|
|
48
|
+
* - the third forbids the "call it done anyway" ending;
|
|
49
|
+
* - the fourth is the only defence against the commonest degeneration, a
|
|
50
|
+
* criterion that is just the step name again (R-5).
|
|
51
|
+
*
|
|
52
|
+
* MEASURED, NOT ESTIMATED (P1-5): this paragraph plus the visibility sentences
|
|
53
|
+
* and two newlines adds 867 characters to a 1433-character block, so the v2 block
|
|
54
|
+
* is asserted at 2300 and bounded at 2400 in `todo-tool.test.ts`. Trimming it to
|
|
55
|
+
* fit 2200 would cost the criterion-versus-step contrast below (143 characters),
|
|
56
|
+
* which is the only mitigation R-5 has - see Q-8.
|
|
57
|
+
*/
|
|
58
|
+
const ACCEPTANCE_LINES = [
|
|
59
|
+
'Every plan also carries ACCEPTANCE CRITERIA: one line each saying how you will know',
|
|
60
|
+
'that part of the work is really done. The user checks your claim against them.',
|
|
61
|
+
'- Plan them in the SAME todo_write call (the acceptance array), each with the check',
|
|
62
|
+
' you will run for it.',
|
|
63
|
+
'- Once every step is completed the plan is in VERIFY: check the criteria ONE at a',
|
|
64
|
+
' time, run the check you named, and record the verdict with its evidence. A verdict',
|
|
65
|
+
' without evidence is not a verdict.',
|
|
66
|
+
'- A failed check is not a detail: fix the work, reopen that criterion (reopen: true),',
|
|
67
|
+
' check it again - never call the work done while one has failed.',
|
|
68
|
+
'- A criterion is not a step: "Add the rail" is a step, "the rail shows 3 items on an',
|
|
69
|
+
' 80x24 terminal" is a criterion.',
|
|
70
|
+
];
|
|
71
|
+
/**
|
|
72
|
+
* BOUNDED AT 2400 CHARACTERS, and the number is asserted in `todo-tool.test.ts`.
|
|
35
73
|
*
|
|
36
74
|
* The block is paid for on EVERY turn of every todo-enabled session, so anything
|
|
37
75
|
* that does not change a planning decision does not belong in it (the discipline
|
|
38
|
-
* `buildTeamBlock` records at 1200 for a shorter block).
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
* planning decision, which is the test that actually applies. The bound exists
|
|
42
|
-
* so that adding a paragraph stays a decision someone makes on purpose. See
|
|
43
|
-
* spec §15 IF-3.
|
|
76
|
+
* `buildTeamBlock` records at 1200 for a shorter block). v1 landed at 1433; v2
|
|
77
|
+
* lands at 2300 (2264 for the hidden variant), and the bound exists so that adding a
|
|
78
|
+
* paragraph stays a decision someone makes on purpose rather than a drift.
|
|
44
79
|
*/
|
|
45
80
|
export function buildTodoBlock(params) {
|
|
46
|
-
|
|
81
|
+
const lines = [
|
|
47
82
|
'<todo_planning>',
|
|
48
83
|
'For work that takes three or more distinct steps, keep a visible plan with the',
|
|
49
84
|
'todo_write tool.',
|
|
50
85
|
params.panelVisible ? VISIBLE : NOT_VISIBLE,
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
'- restating a step you are already in the middle of.',
|
|
61
|
-
'',
|
|
62
|
-
'How to use it:',
|
|
63
|
-
'- Send the COMPLETE list every time. The tool replaces the whole list; it has no',
|
|
64
|
-
' add or update operation.',
|
|
65
|
-
'- Exactly one item is in_progress at a time. Mark an item completed the moment',
|
|
66
|
-
' it is done and mark the next one in_progress in the SAME call.',
|
|
67
|
-
'- Do not batch. Finishing three steps and reporting them together hides where you',
|
|
68
|
-
' are RIGHT NOW, which is the whole point of keeping the list.',
|
|
69
|
-
'- Give each item a content ("Add the rail to AppShell") and an activeForm',
|
|
70
|
-
' ("Adding the rail to AppShell"). The list shows activeForm for the step in',
|
|
71
|
-
' progress and content for the rest.',
|
|
72
|
-
'- Only mark an item completed when it is really finished. If you hit a blocker,',
|
|
73
|
-
' leave it in_progress, add an item describing what is blocking, and say so.',
|
|
74
|
-
'</todo_planning>',
|
|
75
|
-
].join('\n');
|
|
86
|
+
];
|
|
87
|
+
if (params.acceptance) {
|
|
88
|
+
lines.push(params.panelVisible ? ACCEPT_VISIBLE : ACCEPT_NOT_VISIBLE);
|
|
89
|
+
}
|
|
90
|
+
lines.push('', 'Use it when:', '- the request has three or more steps that must happen in order;', '- the user gave you several things to do in one message;', '- you are part-way through a long task and the user asks what is left.', '', 'Do NOT use it for:', '- anything you can finish in one or two steps - just do it and say what you did;', '- a question, an explanation, or a search with no work attached;', '- restating a step you are already in the middle of.', '', 'How to use it:', '- Send the COMPLETE list every time. The tool replaces the whole list; it has no', ' add or update operation.', '- Exactly one item is in_progress at a time. Mark an item completed the moment', ' it is done and mark the next one in_progress in the SAME call.', '- Do not batch. Finishing three steps and reporting them together hides where you', ' are RIGHT NOW, which is the whole point of keeping the list.', '- Give each item a content ("Add the rail to AppShell") and an activeForm', ' ("Adding the rail to AppShell"). The list shows activeForm for the step in', ' progress and content for the rest.', '- Only mark an item completed when it is really finished. If you hit a blocker,', ' leave it in_progress, add an item describing what is blocking, and say so.');
|
|
91
|
+
if (params.acceptance)
|
|
92
|
+
lines.push(...ACCEPTANCE_LINES);
|
|
93
|
+
lines.push('</todo_planning>');
|
|
94
|
+
return lines.join('\n');
|
|
76
95
|
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `selectRowsAround` — the generic anchored window (todo-acceptance-criteria §6.9.4).
|
|
3
|
+
|
|
4
|
+
ASCII ONLY: `src/todo/**` is inside the glyph scanner's scope.
|
|
5
|
+
|
|
6
|
+
PURE WINDOWING, NO OFFSET STATE ANYWHERE (non-goal 2 / R-10). Ink has no absolute
|
|
7
|
+
positioning and this codebase already owns one hand-rolled viewport
|
|
8
|
+
(`ScrollViewport`) whose invariants took a whole spec to pin down; a second
|
|
9
|
+
scrollable region with its own offset, its own intent nonce and its own wheel band
|
|
10
|
+
would be the largest source of new bugs in that feature by a wide margin. The rail
|
|
11
|
+
therefore never scrolls - it windows around the row being worked on and reports
|
|
12
|
+
what is off each end.
|
|
13
|
+
|
|
14
|
+
THE DIRECT DESCENDANT OF `selectPanelRows`'s F-2 LESSON: the team panel originally
|
|
15
|
+
took the first five children by ARRAY INDEX, which showed the five that finished
|
|
16
|
+
FIRST and hid everything still working. Here the equivalent mistake is
|
|
17
|
+
`slice(0, maxRows)`, which on a 20-row plan shows rows 1-8 - all completed - and
|
|
18
|
+
hides the one the user is actually watching.
|
|
19
|
+
|
|
20
|
+
GENERIC OVER THE ROW TYPE (todo-acceptance-criteria §6.9.4): the todo window and
|
|
21
|
+
the acceptance window are the same algorithm over two different item shapes, so
|
|
22
|
+
the anchored-window fixpoint lives here once and three thin wrappers expose it.
|
|
23
|
+
The wrappers' outputs are field-for-field identical to the original todo-only
|
|
24
|
+
implementation (AC-13).
|
|
25
|
+
*/
|
|
26
|
+
export interface RowWindow<T> {
|
|
27
|
+
visible: {
|
|
28
|
+
item: T;
|
|
29
|
+
index: number;
|
|
30
|
+
}[];
|
|
31
|
+
hiddenAbove: number;
|
|
32
|
+
hiddenBelow: number;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* The anchored contiguous window, WITHOUT reserving overflow-marker rows.
|
|
36
|
+
*
|
|
37
|
+
* `maxRows` is a row count; invalid or non-positive values return an empty window
|
|
38
|
+
* with every row counted below it, which is what makes a caller whose arithmetic
|
|
39
|
+
* produced 0 render nothing rather than render everything.
|
|
40
|
+
*/
|
|
41
|
+
export declare function selectCompactRowsAround<T>(items: readonly T[], maxRows: number, anchor: (items: readonly T[]) => number): RowWindow<T>;
|
|
42
|
+
/**
|
|
43
|
+
* The anchored window WITH the two overflow markers accounted for.
|
|
44
|
+
*
|
|
45
|
+
* THE ANCHOR IS ALWAYS VISIBLE, and that beats the row bound when the two
|
|
46
|
+
* conflict. They can only conflict below `maxRows` 3 with overflow on BOTH sides
|
|
47
|
+
* - one row plus two markers is three rows - where this returns the anchor and
|
|
48
|
+
* lets the caller's `overflow="hidden"` clip a marker. Hiding the one row the user
|
|
49
|
+
* is watching in order to keep a `+N above` would be the wrong trade.
|
|
50
|
+
*/
|
|
51
|
+
export declare function selectRowsAround<T>(items: readonly T[], maxRows: number, anchor: (items: readonly T[]) => number): RowWindow<T>;
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `selectRowsAround` — the generic anchored window (todo-acceptance-criteria §6.9.4).
|
|
3
|
+
|
|
4
|
+
ASCII ONLY: `src/todo/**` is inside the glyph scanner's scope.
|
|
5
|
+
|
|
6
|
+
PURE WINDOWING, NO OFFSET STATE ANYWHERE (non-goal 2 / R-10). Ink has no absolute
|
|
7
|
+
positioning and this codebase already owns one hand-rolled viewport
|
|
8
|
+
(`ScrollViewport`) whose invariants took a whole spec to pin down; a second
|
|
9
|
+
scrollable region with its own offset, its own intent nonce and its own wheel band
|
|
10
|
+
would be the largest source of new bugs in that feature by a wide margin. The rail
|
|
11
|
+
therefore never scrolls - it windows around the row being worked on and reports
|
|
12
|
+
what is off each end.
|
|
13
|
+
|
|
14
|
+
THE DIRECT DESCENDANT OF `selectPanelRows`'s F-2 LESSON: the team panel originally
|
|
15
|
+
took the first five children by ARRAY INDEX, which showed the five that finished
|
|
16
|
+
FIRST and hid everything still working. Here the equivalent mistake is
|
|
17
|
+
`slice(0, maxRows)`, which on a 20-row plan shows rows 1-8 - all completed - and
|
|
18
|
+
hides the one the user is actually watching.
|
|
19
|
+
|
|
20
|
+
GENERIC OVER THE ROW TYPE (todo-acceptance-criteria §6.9.4): the todo window and
|
|
21
|
+
the acceptance window are the same algorithm over two different item shapes, so
|
|
22
|
+
the anchored-window fixpoint lives here once and three thin wrappers expose it.
|
|
23
|
+
The wrappers' outputs are field-for-field identical to the original todo-only
|
|
24
|
+
implementation (AC-13).
|
|
25
|
+
*/
|
|
26
|
+
/**
|
|
27
|
+
* How much of the window sits ABOVE the anchor.
|
|
28
|
+
*
|
|
29
|
+
* A QUARTER, and the asymmetry is the point: completed context above the anchor
|
|
30
|
+
* is sacrificed before upcoming work below it, because the user's question is
|
|
31
|
+
* "what is next", not "what is behind me".
|
|
32
|
+
*/
|
|
33
|
+
const ABOVE_SHARE = 0.25;
|
|
34
|
+
function windowFor(count, anchor, slots) {
|
|
35
|
+
if (slots >= count)
|
|
36
|
+
return { start: 0, end: count };
|
|
37
|
+
const above = Math.min(anchor, Math.max(0, Math.floor((slots - 1) * ABOVE_SHARE)));
|
|
38
|
+
let start = anchor - above;
|
|
39
|
+
let end = start + slots;
|
|
40
|
+
if (end > count) {
|
|
41
|
+
end = count;
|
|
42
|
+
start = Math.max(0, end - slots);
|
|
43
|
+
}
|
|
44
|
+
return { start, end };
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* The anchored contiguous window, WITHOUT reserving overflow-marker rows.
|
|
48
|
+
*
|
|
49
|
+
* `maxRows` is a row count; invalid or non-positive values return an empty window
|
|
50
|
+
* with every row counted below it, which is what makes a caller whose arithmetic
|
|
51
|
+
* produced 0 render nothing rather than render everything.
|
|
52
|
+
*/
|
|
53
|
+
export function selectCompactRowsAround(items, maxRows, anchor) {
|
|
54
|
+
const slots = Number.isFinite(maxRows) ? Math.max(0, Math.floor(maxRows)) : 0;
|
|
55
|
+
if (slots === 0 || items.length === 0) {
|
|
56
|
+
return { visible: [], hiddenAbove: 0, hiddenBelow: items.length };
|
|
57
|
+
}
|
|
58
|
+
const { start, end } = windowFor(items.length, anchor(items), slots);
|
|
59
|
+
return {
|
|
60
|
+
visible: items.slice(start, end).map((item, offset) => ({ item, index: start + offset })),
|
|
61
|
+
hiddenAbove: start,
|
|
62
|
+
hiddenBelow: items.length - end,
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* The anchored window WITH the two overflow markers accounted for.
|
|
67
|
+
*
|
|
68
|
+
* THE ANCHOR IS ALWAYS VISIBLE, and that beats the row bound when the two
|
|
69
|
+
* conflict. They can only conflict below `maxRows` 3 with overflow on BOTH sides
|
|
70
|
+
* - one row plus two markers is three rows - where this returns the anchor and
|
|
71
|
+
* lets the caller's `overflow="hidden"` clip a marker. Hiding the one row the user
|
|
72
|
+
* is watching in order to keep a `+N above` would be the wrong trade.
|
|
73
|
+
*/
|
|
74
|
+
export function selectRowsAround(items, maxRows, anchor) {
|
|
75
|
+
const count = items.length;
|
|
76
|
+
const anchorIndex = anchor(items);
|
|
77
|
+
if (count === 0)
|
|
78
|
+
return { visible: [], hiddenAbove: 0, hiddenBelow: 0 };
|
|
79
|
+
if (maxRows <= 0) {
|
|
80
|
+
return {
|
|
81
|
+
visible: [],
|
|
82
|
+
hiddenAbove: anchorIndex,
|
|
83
|
+
hiddenBelow: count - 1 - anchorIndex,
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
// The marker rows and the window depend on each other: a `+N above` row costs a
|
|
87
|
+
// slot, which can shrink the window, which can create a `+N below`. Two passes
|
|
88
|
+
// reach the fixpoint for every input this can be handed; the loop bound is a
|
|
89
|
+
// backstop, not a live case.
|
|
90
|
+
let reserved = 0;
|
|
91
|
+
let start = 0;
|
|
92
|
+
let end = count;
|
|
93
|
+
for (let pass = 0; pass < 3; pass += 1) {
|
|
94
|
+
const slots = Math.max(1, maxRows - reserved);
|
|
95
|
+
const win = windowFor(count, anchorIndex, slots);
|
|
96
|
+
start = win.start;
|
|
97
|
+
end = win.end;
|
|
98
|
+
const need = (start > 0 ? 1 : 0) + (end < count ? 1 : 0);
|
|
99
|
+
if (need === reserved)
|
|
100
|
+
break;
|
|
101
|
+
reserved = need;
|
|
102
|
+
}
|
|
103
|
+
const visible = [];
|
|
104
|
+
for (let i = start; i < end; i += 1)
|
|
105
|
+
visible.push({ item: items[i], index: i });
|
|
106
|
+
return { visible, hiddenAbove: start, hiddenBelow: count - end };
|
|
107
|
+
}
|