@buildaharness/aielia 0.3.3 → 0.3.5
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 +63 -20
- package/dist/PlanGraphPane.d.ts +19 -0
- package/dist/_memory-core-generated.d.ts +1764 -0
- package/dist/agent-loop.d.ts +31 -8
- package/dist/ambiguity-guard-flag.d.ts +12 -0
- package/dist/ambiguity-guard.d.ts +20 -0
- package/dist/answer-claim.d.ts +13 -1
- package/dist/ask-clarification-service.d.ts +12 -1
- package/dist/ask-response-format.d.ts +6 -0
- package/dist/assistant-session.d.ts +16 -5
- package/dist/assistant-source.d.ts +7 -0
- package/dist/assistant-types.d.ts +25 -1
- package/dist/assistant.d.ts +166 -5
- package/dist/benchmark-injected-failure.d.ts +6 -0
- package/dist/bin-CjKpxDxl.js +4836 -0
- package/dist/bin-CjKpxDxl.js.map +1 -0
- package/dist/cli-session.d.ts +26 -1
- package/dist/cli.d.ts +20 -2
- package/dist/cli.js +1 -1
- package/dist/code-plan-templates.d.ts +21 -0
- package/dist/config.d.ts +51 -0
- package/dist/constraint-check.d.ts +35 -0
- package/dist/contradiction-checker.d.ts +7 -0
- package/dist/decomposed-answer.d.ts +13 -0
- package/dist/decomposition-classifier.d.ts +2 -0
- package/dist/doctor-checks.d.ts +3 -0
- package/dist/episodic-digest.d.ts +89 -0
- package/dist/fact-extraction.d.ts +39 -0
- package/dist/file-tools-mcp-server.mjs +138 -12
- package/dist/file-tools.d.ts +4 -0
- package/dist/first-run.d.ts +3 -2
- package/dist/goal-graph-flag.d.ts +44 -0
- package/dist/goal-graph-reconcile.d.ts +55 -0
- package/dist/goal-graph-service.d.ts +48 -0
- package/dist/goal-graph-store.d.ts +485 -0
- package/dist/goal-graph-suggest-flag.d.ts +34 -0
- package/dist/goal-identity-matcher.d.ts +21 -0
- package/dist/goal-thread-identity.d.ts +32 -0
- package/dist/goal-thread-scheduler.d.ts +78 -0
- package/dist/grounding-check.d.ts +33 -0
- package/dist/harness-bridge.d.ts +75 -2
- package/dist/harness-token-budget.d.ts +9 -0
- package/dist/index.d.ts +30 -1
- package/dist/index.js +166 -80
- package/dist/index.js.map +1 -1
- package/dist/layer-policy-flag.d.ts +13 -0
- package/dist/layer-policy-wiring.d.ts +77 -0
- package/dist/layer-settings.d.ts +49 -0
- package/dist/layer-telemetry.d.ts +2 -0
- package/dist/lexical/lexical-mode.d.ts +29 -0
- package/dist/live-steering-channel.d.ts +31 -0
- package/dist/memory-consolidation.d.ts +80 -0
- package/dist/memory-governance.d.ts +30 -0
- package/dist/memory-reviewer.d.ts +114 -0
- package/dist/memory-service.d.ts +348 -9
- package/dist/model-json.d.ts +17 -0
- package/dist/next-step-context.d.ts +51 -0
- package/dist/next-step-proposer.d.ts +53 -0
- package/dist/plan-approval-service.d.ts +1 -1
- package/dist/plan-drafting-service.d.ts +1 -1
- package/dist/plan-graph-flag.d.ts +20 -0
- package/dist/plan-question.d.ts +60 -0
- package/dist/plan-service.d.ts +6 -2
- package/dist/plan-step-prompt.d.ts +15 -0
- package/dist/plan-store.d.ts +7 -1
- package/dist/plan-viz/normalize.d.ts +14 -0
- package/dist/plan-viz/plan-detail-lines.d.ts +3 -0
- package/dist/plan-viz/plan-layout.d.ts +48 -0
- package/dist/plan-viz/plan-nav.d.ts +29 -0
- package/dist/plan-viz/plan-raster.d.ts +36 -0
- package/dist/plan-viz/plan-routes.d.ts +6 -0
- package/dist/plan-viz/plan-snapshot.d.ts +73 -0
- package/dist/plan-viz/plan-viewport.d.ts +29 -0
- package/dist/plan-viz/plan-width.d.ts +15 -0
- package/dist/plan-viz/testkit/display-width.d.ts +12 -0
- package/dist/plan-viz/testkit/generators.d.ts +61 -0
- package/dist/plan-viz/testkit/grid-oracles.d.ts +38 -0
- package/dist/plan-viz/testkit/nav-oracles.d.ts +79 -0
- package/dist/plan-viz/testkit/types.d.ts +8 -0
- package/dist/plan-viz/types.d.ts +34 -0
- package/dist/provider-setup-LFsaTkpf.js +16606 -0
- package/dist/provider-setup-LFsaTkpf.js.map +1 -0
- package/dist/provider-setup.d.ts +51 -0
- package/dist/recall-tool.d.ts +43 -0
- package/dist/recovery-note.d.ts +22 -0
- package/dist/response-service.d.ts +28 -2
- package/dist/review-checker.d.ts +10 -4
- package/dist/reviewer-revision.d.ts +23 -0
- package/dist/risk-classifier.d.ts +7 -0
- package/dist/scope-urgency-classifier.d.ts +29 -0
- package/dist/scripted-llm-client.d.ts +26 -1
- package/dist/semantic-compaction.d.ts +15 -0
- package/dist/semantic-hypotheses.d.ts +40 -0
- package/dist/source-reliability.d.ts +71 -0
- package/dist/supervisor-flag.d.ts +20 -0
- package/dist/task-completion-check.d.ts +24 -0
- package/dist/tool-control-plane.d.ts +33 -1
- package/dist/tool-effect-class.d.ts +9 -0
- package/dist/transcript-compaction.d.ts +9 -0
- package/dist/{tui-app-CFfOP2DC.js → tui-app-BLR-PRFp.js} +321 -7
- package/dist/tui-app-BLR-PRFp.js.map +1 -0
- package/dist/tui-app.d.ts +38 -0
- package/dist/turn-intent-classifier.d.ts +75 -16
- package/dist/turn-interpreter.d.ts +25 -3
- package/dist/version.d.ts +1 -1
- package/package.json +7 -7
- package/dist/bin-Btzhiyzi.js +0 -2108
- package/dist/bin-Btzhiyzi.js.map +0 -1
- package/dist/cli-session-DnSc6Hhx.js +0 -8343
- package/dist/cli-session-DnSc6Hhx.js.map +0 -1
- package/dist/tui-app-CFfOP2DC.js.map +0 -1
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { PlanRecord, PlanTaskRecord } from './plan-store.js';
|
|
2
|
+
/**
|
|
3
|
+
* How a message that only asks about the active plan (the classifier's `isPlanQuestion`) is handled:
|
|
4
|
+
* - `stuck` (default): answered from the plan's recorded state ONLY while the plan is stuck on a failed
|
|
5
|
+
* task — exactly where re-driving the plan is known to go wrong. A healthy plan behaves as it always
|
|
6
|
+
* has, so this default changes nothing for it.
|
|
7
|
+
* - `always`: any plan question is answered from the recorded state, healthy plan or not.
|
|
8
|
+
* - `off`: an active plan drives every non-trivial turn (the pre-routing behaviour).
|
|
9
|
+
* `AUDIT_PLAN_QUESTION_ROUTING`: `always`/`on`/`1`/`true` → always; `0`/`false`/`off`/`no`/`disabled` → off;
|
|
10
|
+
* empty or `stuck` → stuck. Read at exactly one site: assistant.ts, where the turn is routed.
|
|
11
|
+
*/
|
|
12
|
+
export type PlanQuestionRouting = 'off' | 'stuck' | 'always';
|
|
13
|
+
export declare function planQuestionRoutingMode(env?: Record<string, string | undefined>): PlanQuestionRouting;
|
|
14
|
+
/** A plan is stuck when a step failed and was not skipped: the harness cannot advance past it on its own. */
|
|
15
|
+
export declare function isPlanStuck(plan: PlanRecord): boolean;
|
|
16
|
+
export declare function shouldRoutePlanQuestion(input: {
|
|
17
|
+
mode: PlanQuestionRouting;
|
|
18
|
+
plan: PlanRecord | null;
|
|
19
|
+
isPlanQuestion: boolean | undefined;
|
|
20
|
+
}): boolean;
|
|
21
|
+
/**
|
|
22
|
+
* `AUDIT_STUCK_PLAN_RESUME` (default ON): a plan stuck on a failed step is resumed only by a message that says to carry it
|
|
23
|
+
* on (the classifier's `continuesPlan`). Any other message is answered on its own terms — the plan is not handed to the
|
|
24
|
+
* harness, so the failed step is not silently retried — and the reply ends by asking whether to retry it. `0`/`false`/
|
|
25
|
+
* `off`/`no`/`disabled` restores the old behaviour (any non-trivial message on a stuck plan retries the step).
|
|
26
|
+
*/
|
|
27
|
+
export declare function stuckPlanResumeEnabled(env?: Record<string, string | undefined>): boolean;
|
|
28
|
+
/**
|
|
29
|
+
* True when the turn should set the stuck plan aside: the plan is stuck, the message is not a question about it (that is
|
|
30
|
+
* routed separately) and the classifier said explicitly that it does not continue it. A missing `continuesPlan` is not
|
|
31
|
+
* "no" — it keeps today's behaviour.
|
|
32
|
+
*/
|
|
33
|
+
export declare function shouldSetAsideStuckPlan(input: {
|
|
34
|
+
enabled: boolean;
|
|
35
|
+
plan: PlanRecord | null;
|
|
36
|
+
isPlanQuestion: boolean | undefined;
|
|
37
|
+
continuesPlan: boolean | undefined;
|
|
38
|
+
}): boolean;
|
|
39
|
+
/** Prompt addendum for a turn that set a stuck plan aside: answer the message, then ask about the failed step. */
|
|
40
|
+
export declare function renderStuckPlanNudge(plan: PlanRecord): string;
|
|
41
|
+
/**
|
|
42
|
+
* The plan's tasks as the harness should see them for a turn that moves the plan forward. A step that
|
|
43
|
+
* failed is put back to pending so it gets another attempt (left as FAILED it would strand the run on
|
|
44
|
+
* every later turn), and its description carries why the last attempt was rejected so the retry can
|
|
45
|
+
* address that instead of repeating it. Only the harness's copy changes: the stored plan keeps its
|
|
46
|
+
* original description, and its status is rewritten from the run's outcome afterwards.
|
|
47
|
+
*/
|
|
48
|
+
export declare function planTasksForRun(tasks: PlanTaskRecord[]): PlanTaskRecord[];
|
|
49
|
+
/**
|
|
50
|
+
* What to add to the reply of a turn that ran an approved plan and stopped because a step was not
|
|
51
|
+
* accepted as done. Without it the reply is just the last step that DID complete, and the user only finds
|
|
52
|
+
* out the plan stalled by asking. Empty when nothing was rejected this turn.
|
|
53
|
+
*/
|
|
54
|
+
export declare function renderPlanStopNote(plan: PlanRecord, taskNotes: Record<string, string> | undefined): string;
|
|
55
|
+
/**
|
|
56
|
+
* The plan's real state, rendered for the prompt of a turn that only asks about it. Grounds the answer
|
|
57
|
+
* in what the task graph actually recorded (a task is "done" only if it completed; a failed one carries
|
|
58
|
+
* the reason it was not accepted) so the reply can't drift into describing the plan as it was drafted.
|
|
59
|
+
*/
|
|
60
|
+
export declare function renderPlanStateBlock(plan: PlanRecord): string;
|
package/dist/plan-service.d.ts
CHANGED
|
@@ -33,7 +33,7 @@ export declare class PlanService {
|
|
|
33
33
|
updatePlanFromRun(plan: PlanRecord, taskGraphTasks: {
|
|
34
34
|
id: string;
|
|
35
35
|
status: TaskStatus;
|
|
36
|
-
}[]): PlanRecord;
|
|
36
|
+
}[], taskNotes?: Record<string, string>): PlanRecord;
|
|
37
37
|
planCompletionPct(plan: PlanRecord): number;
|
|
38
38
|
computePlanPosition(plan: PlanRecord, taskGraphTasks: {
|
|
39
39
|
id: string;
|
|
@@ -44,7 +44,7 @@ export declare class PlanService {
|
|
|
44
44
|
saveAndSummarize(sessionId: string, plan: PlanRecord, taskGraphTasks: {
|
|
45
45
|
id: string;
|
|
46
46
|
status: TaskStatus;
|
|
47
|
-
}[]): Promise<{
|
|
47
|
+
}[], taskNotes?: Record<string, string>): Promise<{
|
|
48
48
|
plan: PlanRecord;
|
|
49
49
|
completionPct: number;
|
|
50
50
|
planStatus: {
|
|
@@ -55,6 +55,10 @@ export declare class PlanService {
|
|
|
55
55
|
id: string;
|
|
56
56
|
description: string;
|
|
57
57
|
status: string;
|
|
58
|
+
note?: string;
|
|
59
|
+
dependsOn?: string[];
|
|
60
|
+
cancelled?: boolean;
|
|
61
|
+
riskLevel?: 'LOW' | 'MEDIUM' | 'HIGH';
|
|
58
62
|
}[];
|
|
59
63
|
};
|
|
60
64
|
}>;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `AUDIT_PLAN_STEP_PROMPT` gate. Default **ON**: while an approved plan runs, the model is told which
|
|
3
|
+
* step it is carrying out. A falsy value (`0` / `false` / `off` / `no` / `disabled`) restores the
|
|
4
|
+
* previous behaviour, where every step was run by re-sending the user's message alone. Read at exactly
|
|
5
|
+
* one site: assistant.ts, where the proposer is wired.
|
|
6
|
+
*/
|
|
7
|
+
export declare function planStepPromptEnabled(env?: Record<string, string | undefined>): boolean;
|
|
8
|
+
/**
|
|
9
|
+
* The instruction that makes one step of a plan a distinct piece of work. Without it the harness ran
|
|
10
|
+
* every step through the same proposer with only the user's message ("run the plan"), so each step
|
|
11
|
+
* produced the same answer and none of them did its own step. `description` may already carry the
|
|
12
|
+
* reason a previous attempt was rejected (plan-question.ts's planTasksForRun), which is what lets a
|
|
13
|
+
* retry address it.
|
|
14
|
+
*/
|
|
15
|
+
export declare function buildStepInstruction(description: string): string;
|
package/dist/plan-store.d.ts
CHANGED
|
@@ -23,6 +23,12 @@ export interface PlanTaskRecord {
|
|
|
23
23
|
* claiming the user's own work actually got done.
|
|
24
24
|
*/
|
|
25
25
|
cancelled?: boolean;
|
|
26
|
+
/**
|
|
27
|
+
* Why the last attempt at this task did not count as done — set when the semantic task-completion
|
|
28
|
+
* check judged its output did not do the task (task-completion-check.ts), so a later turn can say
|
|
29
|
+
* why the plan is stuck. Cleared once the task completes. Absent otherwise.
|
|
30
|
+
*/
|
|
31
|
+
statusNote?: string;
|
|
26
32
|
}
|
|
27
33
|
/**
|
|
28
34
|
* Superset of the old 3-value `status`: 'drafting' and 'awaiting_approval' are new (plan mode's
|
|
@@ -202,7 +208,7 @@ export declare function editPlanTask(memory: MemoryAdapter, sessionId: string, p
|
|
|
202
208
|
export declare function updatePlanFromRun(plan: PlanRecord, taskGraphTasks: {
|
|
203
209
|
id: string;
|
|
204
210
|
status: TaskStatus;
|
|
205
|
-
}[]): PlanRecord;
|
|
211
|
+
}[], taskNotes?: Record<string, string>): PlanRecord;
|
|
206
212
|
/** Cancelled tasks are excluded from both sides of the ratio — they're neither remaining work nor
|
|
207
213
|
* something the user actually did, so counting them as "complete" would overstate real progress.
|
|
208
214
|
* A plan with no tasks at all is 0% (unchanged); a plan whose remaining tasks were all cancelled
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { VizNode } from './types.js';
|
|
2
|
+
export interface NormalizedNodes {
|
|
3
|
+
nodes: VizNode[];
|
|
4
|
+
/** What was repaired, one human-readable line each (duplicate ids, unknown/self dependencies, broken cycles). */
|
|
5
|
+
warnings: string[];
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Makes any node list safe for the layout and rasterizer: drops duplicate ids (first wins), unknown and
|
|
9
|
+
* self dependencies, duplicate dependencies, and breaks cycles by removing the edge that closes one
|
|
10
|
+
* (depth-first in input order, so the result is deterministic). Never throws and never mutates its input.
|
|
11
|
+
* Behaviour is specified by `normalizePlan` in testkit/generators.ts and differential-tested against it.
|
|
12
|
+
* The depth-first walk is iterative so a very deep chain cannot overflow the stack.
|
|
13
|
+
*/
|
|
14
|
+
export declare function normalizePlanNodes(input: readonly VizNode[]): NormalizedNodes;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { VizNode } from './types.js';
|
|
2
|
+
/** Above this many nodes the picture is not useful in a terminal; callers fall back to the checklist. */
|
|
3
|
+
export declare const MAX_PLAN_NODES = 150;
|
|
4
|
+
/** Dense plans (hundreds of dependencies) turn into a wall of lines; same checklist fallback as the node cap. */
|
|
5
|
+
export declare const MAX_PLAN_EDGES = 600;
|
|
6
|
+
export declare const BOX_HEIGHT = 3;
|
|
7
|
+
/** A box (real) or a one-column waypoint of an edge that skips ranks (virtual). */
|
|
8
|
+
export interface LayoutItem {
|
|
9
|
+
uid: number;
|
|
10
|
+
rank: number;
|
|
11
|
+
x: number;
|
|
12
|
+
w: number;
|
|
13
|
+
virtual: boolean;
|
|
14
|
+
/** Real items only. */
|
|
15
|
+
node?: VizNode;
|
|
16
|
+
/** Visible label text of a real item (sanitized and shortened). */
|
|
17
|
+
label?: string;
|
|
18
|
+
/** Virtual items: the chain they belong to, so adjacent-rank waypoints of one edge may share a column. */
|
|
19
|
+
chain?: number;
|
|
20
|
+
}
|
|
21
|
+
export interface EdgeChain {
|
|
22
|
+
from: string;
|
|
23
|
+
to: string;
|
|
24
|
+
/** Source box, waypoints in rank order, target box. */
|
|
25
|
+
items: LayoutItem[];
|
|
26
|
+
}
|
|
27
|
+
export interface PlanLayout {
|
|
28
|
+
ok: true;
|
|
29
|
+
nodes: VizNode[];
|
|
30
|
+
ranks: LayoutItem[][];
|
|
31
|
+
chains: EdgeChain[];
|
|
32
|
+
byId: Map<string, LayoutItem>;
|
|
33
|
+
width: number;
|
|
34
|
+
warnings: string[];
|
|
35
|
+
}
|
|
36
|
+
export type LayoutFailure = {
|
|
37
|
+
ok: false;
|
|
38
|
+
reason: 'empty' | 'too_large' | 'cannot_draw';
|
|
39
|
+
message: string;
|
|
40
|
+
};
|
|
41
|
+
export declare const LABEL_FLOOR = 8;
|
|
42
|
+
/**
|
|
43
|
+
* Layered layout in character units. dagre decides the ranks and the left-to-right order (dummy nodes
|
|
44
|
+
* included); positions are then legalized per rank so boxes never touch and waypoints keep clear of boxes.
|
|
45
|
+
* Deterministic: nodes and edges are inserted in task order and nothing in the input depends on status, so
|
|
46
|
+
* a status change never moves a box.
|
|
47
|
+
*/
|
|
48
|
+
export declare function layoutPlan(input: readonly VizNode[], labelMax: number): PlanLayout | LayoutFailure;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { Box, VizNode } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Keyboard navigation over the plan graph (section 5.4). Same behaviour as `referenceNavigator` in
|
|
4
|
+
* testkit/nav-oracles.ts (copied: production code does not import the kit); a differential test keeps them equal.
|
|
5
|
+
* Pure: no I/O. Read-only: it only moves a selection.
|
|
6
|
+
*/
|
|
7
|
+
export type NavKey = 'up' | 'down' | 'left' | 'right' | 'tab' | 'shiftTab';
|
|
8
|
+
export interface NavModel {
|
|
9
|
+
ids: string[];
|
|
10
|
+
taskOrder: string[];
|
|
11
|
+
/** Box centre x and top y; rank is decided by y (equal y = same rank). */
|
|
12
|
+
x: Record<string, number>;
|
|
13
|
+
y: Record<string, number>;
|
|
14
|
+
deps: Record<string, string[]>;
|
|
15
|
+
dependents: Record<string, string[]>;
|
|
16
|
+
}
|
|
17
|
+
export interface NavState {
|
|
18
|
+
cur: string;
|
|
19
|
+
lastKey?: NavKey;
|
|
20
|
+
/** For a repeated vertical key: the node the cycling started from. */
|
|
21
|
+
lastFrom?: string;
|
|
22
|
+
k: number;
|
|
23
|
+
}
|
|
24
|
+
export interface Navigator {
|
|
25
|
+
start(model: NavModel, id: string): NavState;
|
|
26
|
+
press(model: NavModel, state: NavState, key: NavKey): NavState;
|
|
27
|
+
}
|
|
28
|
+
export declare function navModelFrom(nodes: readonly VizNode[], boxes: readonly Box[]): NavModel;
|
|
29
|
+
export declare const planNavigator: Navigator;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { LayoutFailure } from './plan-layout.js';
|
|
2
|
+
import { RenderResult, VizNode, VizStatus } from './types.js';
|
|
3
|
+
export interface PlanRenderOptions {
|
|
4
|
+
/** Terminal width in cells; labels shrink (down to a floor) until the picture fits. Omit for the natural size. */
|
|
5
|
+
maxCols?: number;
|
|
6
|
+
ascii?: boolean;
|
|
7
|
+
color?: boolean;
|
|
8
|
+
selectedId?: string;
|
|
9
|
+
}
|
|
10
|
+
/** What a successful render returns beyond what the grid oracles need. */
|
|
11
|
+
export interface PlanRender extends RenderResult {
|
|
12
|
+
ok: true;
|
|
13
|
+
width: number;
|
|
14
|
+
height: number;
|
|
15
|
+
/** False when even the shortest labels do not fit `maxCols`; the caller pans a viewport over the full grid. */
|
|
16
|
+
fits: boolean;
|
|
17
|
+
/** The label text each box shows (after sanitizing and shortening). */
|
|
18
|
+
labels: Record<string, string>;
|
|
19
|
+
/** Cells (row, column) every edge is drawn through, keyed `${from}>${to}`. */
|
|
20
|
+
routes: Record<string, Array<[number, number]>>;
|
|
21
|
+
/** One entry per terminal cell (a double-width character is followed by WIDE_TAIL) and its SGR parameters ('' = none). */
|
|
22
|
+
cells: string[][];
|
|
23
|
+
styles: string[][];
|
|
24
|
+
warnings: string[];
|
|
25
|
+
}
|
|
26
|
+
export type PlanRenderFailure = LayoutFailure;
|
|
27
|
+
export declare const GLYPHS: Record<VizStatus, string>;
|
|
28
|
+
export declare const ASCII_GLYPHS: Record<VizStatus, string>;
|
|
29
|
+
/** Joins cells into text lines, emitting SGR sequences only where the style changes. Trailing blanks are dropped. */
|
|
30
|
+
export declare function toLines(cells: readonly string[][], styles: readonly string[][], rows?: [number, number], cols?: [number, number]): string[];
|
|
31
|
+
/**
|
|
32
|
+
* Lays out and draws a plan. Labels shrink (down to a floor) until the picture fits `maxCols`; when it still
|
|
33
|
+
* does not, the full-size grid is returned with `fits: false` so the caller can pan over it. Never throws:
|
|
34
|
+
* a plan that cannot be drawn comes back as `{ ok: false, reason, message }` and the caller shows the checklist.
|
|
35
|
+
*/
|
|
36
|
+
export declare function renderPlan(nodes: readonly VizNode[], opts?: PlanRenderOptions): PlanRender | PlanRenderFailure;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { PlanRender } from './plan-raster.js';
|
|
2
|
+
import { Edge } from './types.js';
|
|
3
|
+
/** The edges that touch a node: its incoming (dependencies) and outgoing (dependents) ones. */
|
|
4
|
+
export declare function incidentEdges(edges: readonly Edge[], id: string): Edge[];
|
|
5
|
+
/** Every cell the incident edges of `id` are drawn through, as `"row,col"` keys (exact: the rasterizer reports its own routes). */
|
|
6
|
+
export declare function highlightCells(render: Pick<PlanRender, 'edges' | 'routes'>, id: string): Set<string>;
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { TaskStatus } from '@buildaharness/harness';
|
|
2
|
+
import { PlanRecord } from '../plan-store.js';
|
|
3
|
+
import { GoalGraphRecord } from '../goal-graph-store.js';
|
|
4
|
+
import { VizNode } from './types.js';
|
|
5
|
+
/** One node of the snapshot the web viewer consumes (cuddlytoddly's node shape; absent metadata means "nothing to show"). */
|
|
6
|
+
export interface SnapshotNode {
|
|
7
|
+
id: string;
|
|
8
|
+
node_type: 'goal' | 'task';
|
|
9
|
+
status: string;
|
|
10
|
+
origin: 'system';
|
|
11
|
+
dependencies: string[];
|
|
12
|
+
children: string[];
|
|
13
|
+
result: string | null;
|
|
14
|
+
metadata: {
|
|
15
|
+
description: string;
|
|
16
|
+
expanded?: boolean;
|
|
17
|
+
required_input: string[];
|
|
18
|
+
output: string[];
|
|
19
|
+
execution_steps: string[];
|
|
20
|
+
reflection_notes: string[];
|
|
21
|
+
verification_failure?: string;
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
export interface PlanSnapshot {
|
|
25
|
+
type: 'snapshot';
|
|
26
|
+
nodes: Record<string, SnapshotNode>;
|
|
27
|
+
status: {
|
|
28
|
+
total: number;
|
|
29
|
+
by_status: Record<string, number>;
|
|
30
|
+
running_nodes: string[];
|
|
31
|
+
node_activities: Record<string, string>;
|
|
32
|
+
};
|
|
33
|
+
structure_version: number;
|
|
34
|
+
paused: boolean;
|
|
35
|
+
activity: string | null;
|
|
36
|
+
activity_started_ms: number | null;
|
|
37
|
+
status_events: never[];
|
|
38
|
+
tokens: {
|
|
39
|
+
prompt: number;
|
|
40
|
+
completion: number;
|
|
41
|
+
total: number;
|
|
42
|
+
calls: number;
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
export interface PlanSnapshotResult {
|
|
46
|
+
/** What the web viewer consumes. */
|
|
47
|
+
snapshot: PlanSnapshot;
|
|
48
|
+
/** The normalized nodes the CLI renderer consumes (goal nodes included, ids namespaced exactly as in the snapshot). */
|
|
49
|
+
nodes: VizNode[];
|
|
50
|
+
/** Repairs `normalizePlanNodes` made to malformed input (empty for a well-formed plan). */
|
|
51
|
+
warnings: string[];
|
|
52
|
+
}
|
|
53
|
+
export interface PlanSnapshotOptions {
|
|
54
|
+
/** The node the harness is currently executing — becomes `activity: "Executing: <currentNode>"`. Defaults to the first running task. */
|
|
55
|
+
currentNode?: string;
|
|
56
|
+
tokens?: {
|
|
57
|
+
prompt: number;
|
|
58
|
+
completion: number;
|
|
59
|
+
total: number;
|
|
60
|
+
calls: number;
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Turns a plan (or every goal thread) into the node snapshot both surfaces draw. Pure and total: malformed
|
|
65
|
+
* input is repaired by `normalizePlanNodes`, never thrown on. `live` overlays per-task statuses from a
|
|
66
|
+
* running turn; un-namespaced ids apply to the active thread (or the only plan), namespaced ids anywhere.
|
|
67
|
+
* Statuses: PENDING with every dependency done is `ready`; BLOCKED -> awaiting_input; HUMAN_REQUIRED ->
|
|
68
|
+
* awaiting_user; a cancelled task is `done` in the snapshot (with a ⊘ description) and `cancelled` for the CLI.
|
|
69
|
+
*/
|
|
70
|
+
export declare function planToSnapshot(source: PlanRecord | GoalGraphRecord, live?: readonly {
|
|
71
|
+
id: string;
|
|
72
|
+
status: TaskStatus;
|
|
73
|
+
}[], opts?: PlanSnapshotOptions): PlanSnapshotResult;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { Box } from './types.js';
|
|
2
|
+
export interface Viewport {
|
|
3
|
+
left: number;
|
|
4
|
+
top: number;
|
|
5
|
+
width: number;
|
|
6
|
+
height: number;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Keeps the selected box fully visible when it fits, never leaves the diagram and never exceeds the terminal.
|
|
10
|
+
* Scrolls the minimum amount from the previous viewport so the picture does not jump while navigating.
|
|
11
|
+
* Same behaviour as `followSelection` in testkit/nav-oracles.ts (copied: production code does not import the kit).
|
|
12
|
+
*/
|
|
13
|
+
export declare function followSelection(prev: Viewport, box: Box, grid: {
|
|
14
|
+
width: number;
|
|
15
|
+
height: number;
|
|
16
|
+
}, term: {
|
|
17
|
+
cols: number;
|
|
18
|
+
rows: number;
|
|
19
|
+
}): Viewport;
|
|
20
|
+
/** Which edges of the diagram lie beyond the viewport, for scroll indicators. */
|
|
21
|
+
export declare function scrollIndicators(v: Viewport, grid: {
|
|
22
|
+
width: number;
|
|
23
|
+
height: number;
|
|
24
|
+
}): {
|
|
25
|
+
up: boolean;
|
|
26
|
+
down: boolean;
|
|
27
|
+
left: boolean;
|
|
28
|
+
right: boolean;
|
|
29
|
+
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Terminal cell widths for the plan renderer. Same tables as testkit/display-width.ts (copied, not imported: production code must not depend on the test kit);
|
|
3
|
+
* the oracles cross-check it against that independent copy. Covers the ranges that matter for plan labels, not all of Unicode.
|
|
4
|
+
*/
|
|
5
|
+
export declare function cellWidth(ch: string): 0 | 1 | 2;
|
|
6
|
+
export declare function displayWidth(s: string): number;
|
|
7
|
+
/** Marks the second cell of a double-width character in a cell grid. */
|
|
8
|
+
export declare const WIDE_TAIL = "\0";
|
|
9
|
+
/** Expands a line into one entry per terminal cell (a wide character becomes [char, WIDE_TAIL]). */
|
|
10
|
+
export declare function toCells(line: string): string[];
|
|
11
|
+
export declare function toGrid(lines: readonly string[]): string[][];
|
|
12
|
+
/** One printable line: control, escape and bidi characters are removed, whitespace runs collapse, ends are trimmed. */
|
|
13
|
+
export declare function sanitizeLabel(raw: string): string;
|
|
14
|
+
/** Cuts `s` to at most `max` cells, ending with an ellipsis when something was removed. Never splits a wide character. */
|
|
15
|
+
export declare function fitLabel(s: string, max: number): string;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* An intentionally simple, independent terminal cell-width function for the oracles. The production
|
|
3
|
+
* renderer may use a library; checking it against this separate implementation catches width bugs in
|
|
4
|
+
* either (CJK, emoji, combining marks). Covers the ranges that matter for plan labels, not all of Unicode.
|
|
5
|
+
*/
|
|
6
|
+
export declare function cellWidth(ch: string): 0 | 1 | 2;
|
|
7
|
+
export declare function displayWidth(s: string): number;
|
|
8
|
+
/** Marks the second cell of a double-width character in a cell grid. */
|
|
9
|
+
export declare const WIDE_TAIL = "\0";
|
|
10
|
+
/** Expands a line into one entry per terminal cell (a wide character becomes [char, WIDE_TAIL]). */
|
|
11
|
+
export declare function toCells(line: string): string[];
|
|
12
|
+
export declare function toGrid(lines: readonly string[]): string[][];
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { Box, Edge, VizNode, VizStatus } from './types.js';
|
|
2
|
+
/** Small deterministic PRNG (mulberry32): the same seed always yields the same plans, so failures reproduce. */
|
|
3
|
+
export declare function rng(seed: number): () => number;
|
|
4
|
+
export declare function edgesOf(nodes: readonly VizNode[]): Edge[];
|
|
5
|
+
export declare function dependentsOf(nodes: readonly VizNode[]): Record<string, string[]>;
|
|
6
|
+
export declare function isAcyclic(nodes: readonly VizNode[]): boolean;
|
|
7
|
+
/** Weakly connected: ignoring edge direction, every node can reach every other. */
|
|
8
|
+
export declare function isConnected(nodes: readonly VizNode[]): boolean;
|
|
9
|
+
/** Longest-path rank from the roots (roots are rank 0). Assumes an acyclic, normalized plan. */
|
|
10
|
+
export declare function ranksOf(nodes: readonly VizNode[]): Record<string, number>;
|
|
11
|
+
/** Adds a goal node that depends on every sink — exactly what the production adapter does, so the result is connected. */
|
|
12
|
+
export declare function withGoal(nodes: readonly VizNode[], goalId?: string, label?: string): VizNode[];
|
|
13
|
+
export declare function withStatus(nodes: readonly VizNode[], id: string, status: VizStatus): VizNode[];
|
|
14
|
+
export interface Normalized {
|
|
15
|
+
nodes: VizNode[];
|
|
16
|
+
warnings: string[];
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Executable specification of input sanitising: drops duplicate ids (first wins), unknown and self
|
|
20
|
+
* dependencies, and breaks cycles by removing the edge that closes one (deterministically, in input order).
|
|
21
|
+
* The production adapter/layout must satisfy `checkNormalized` on every input, malformed ones included.
|
|
22
|
+
*/
|
|
23
|
+
export declare function normalizePlan(input: readonly VizNode[]): Normalized;
|
|
24
|
+
export declare function checkNormalized(nodes: readonly VizNode[]): string[];
|
|
25
|
+
/**
|
|
26
|
+
* A trivial deterministic layout (longest-path ranks, input order within a rank). It is *not* the
|
|
27
|
+
* production layout; it exists so navigation and viewport oracles can be tested before that layout
|
|
28
|
+
* exists, and as a cross-check afterwards. Box height is 3, label width is the display width.
|
|
29
|
+
*/
|
|
30
|
+
export declare function toyLayout(plan: readonly VizNode[], gapX?: number, gapY?: number): {
|
|
31
|
+
boxes: Box[];
|
|
32
|
+
edges: Edge[];
|
|
33
|
+
width: number;
|
|
34
|
+
height: number;
|
|
35
|
+
};
|
|
36
|
+
/** The 9-task plan used throughout the verification work, every interesting status included, goal depending on the terminals. */
|
|
37
|
+
export declare const NINE_TASK_PLAN: VizNode[];
|
|
38
|
+
/** Hand-shaped plans, each chosen to stress one thing. Every one is normalized; `connected` says whether it is weakly connected. */
|
|
39
|
+
export declare const NAMED_PLANS: Record<string, {
|
|
40
|
+
nodes: VizNode[];
|
|
41
|
+
connected: boolean;
|
|
42
|
+
}>;
|
|
43
|
+
/**
|
|
44
|
+
* The seven real plan templates shipped with aielia, converted to nodes with a goal node added
|
|
45
|
+
* (what a user of the product actually gets). Statuses are assigned by progress so each one exercises
|
|
46
|
+
* done / running / pending.
|
|
47
|
+
*/
|
|
48
|
+
export declare function templatePlans(): Record<string, VizNode[]>;
|
|
49
|
+
export interface RandomPlanOptions {
|
|
50
|
+
minNodes?: number;
|
|
51
|
+
maxNodes?: number;
|
|
52
|
+
/** Probability that a node depends on any given earlier node (default depends on size). */
|
|
53
|
+
density?: number;
|
|
54
|
+
/** Add a goal depending on every sink (connected, like the adapter's output). Default true. */
|
|
55
|
+
goal?: boolean;
|
|
56
|
+
/** Mix in CJK and very long labels. Default false. */
|
|
57
|
+
unicodeLabels?: boolean;
|
|
58
|
+
}
|
|
59
|
+
export declare function randomPlan(seed: number, opts?: RandomPlanOptions): VizNode[];
|
|
60
|
+
/** Malformed inputs the production code must survive (it receives LLM-drafted and hand-edited plans). */
|
|
61
|
+
export declare const MALFORMED_PLANS: Record<string, VizNode[]>;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { Box, Edge, RenderResult, VizNode } from './types.js';
|
|
2
|
+
export interface OracleOptions {
|
|
3
|
+
/** The diagram uses the ASCII glyph set (`| - + v`). `+` is ambiguous, so edge checks become connectivity-only. */
|
|
4
|
+
ascii?: boolean;
|
|
5
|
+
/** Require reached = expected exactly (default true; forced off for ASCII). */
|
|
6
|
+
exact?: boolean;
|
|
7
|
+
/** Treat `┼` as a junction (turns allowed). Default false: a crossing is straight-through only. */
|
|
8
|
+
crossingIsJunction?: boolean;
|
|
9
|
+
}
|
|
10
|
+
/** Exactness: from every node, following drawn lines reaches precisely the nodes that depend on it. */
|
|
11
|
+
export declare function checkEdges(lines: readonly string[], boxes: readonly Box[], edges: readonly Edge[], opts?: OracleOptions): string[];
|
|
12
|
+
/** Line glyphs outside every box that no edge traversal passes through: leftovers such as the prototype's stray segments. */
|
|
13
|
+
export declare function checkNoStrays(lines: readonly string[], boxes: readonly Box[], opts?: OracleOptions): string[];
|
|
14
|
+
/** Every arrowhead must sit directly above the top border of some box. */
|
|
15
|
+
export declare function checkArrowsPointAtBoxes(lines: readonly string[], boxes: readonly Box[], opts?: OracleOptions): string[];
|
|
16
|
+
/** No two boxes overlap, and boxes in the same rows keep at least `minGap` empty columns between them. */
|
|
17
|
+
export declare function checkNoOverlap(boxes: readonly Box[], minGap?: number): string[];
|
|
18
|
+
/** Edge direction: a dependent is drawn strictly below the node it depends on. */
|
|
19
|
+
export declare function checkRanksDownward(boxes: readonly Box[], edges: readonly Edge[]): string[];
|
|
20
|
+
/** Borders are intact and nothing but label text sits inside a box. */
|
|
21
|
+
export declare function checkBoxesDrawn(lines: readonly string[], boxes: readonly Box[], opts?: OracleOptions): string[];
|
|
22
|
+
/** Each node's label text (already truncated by the renderer, if it truncates) appears inside its own box. */
|
|
23
|
+
export declare function checkLabelsVisible(lines: readonly string[], boxes: readonly Box[], expected: Readonly<Record<string, string>>): string[];
|
|
24
|
+
/** No output line is wider than the terminal, measured in cells (CJK and emoji count as two). */
|
|
25
|
+
export declare function checkWidth(lines: readonly string[], maxCols: number): string[];
|
|
26
|
+
/** Output must be plain printable text: no stray control characters or newlines inside a line. */
|
|
27
|
+
export declare function checkPrintable(lines: readonly string[]): string[];
|
|
28
|
+
export interface RenderCheckInput {
|
|
29
|
+
render: RenderResult;
|
|
30
|
+
nodes: readonly VizNode[];
|
|
31
|
+
/** Terminal width the render was asked for; width is only checked when given. */
|
|
32
|
+
maxCols?: number;
|
|
33
|
+
/** Expected visible label text per node id (after any truncation); omit to skip. */
|
|
34
|
+
labels?: Readonly<Record<string, string>>;
|
|
35
|
+
opts?: OracleOptions;
|
|
36
|
+
}
|
|
37
|
+
/** Runs every grid oracle and returns all violations (empty = the diagram is correct). */
|
|
38
|
+
export declare function checkRender({ render, maxCols, labels, opts }: RenderCheckInput): string[];
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { Box, Edge, VizNode } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* The navigation specification and its oracles. `referenceNavigator` is the *executable specification*
|
|
4
|
+
* of the pane's keys (section 5.4 of the plan); the production navigator must behave identically on the
|
|
5
|
+
* property suite below. It was derived from the V10 simulation, where the obvious rule ("go to the
|
|
6
|
+
* nearest connected node") stranded nodes in about 1.1–1.5% of plans and the final rule reached every
|
|
7
|
+
* node in 3,000 of 3,000.
|
|
8
|
+
*
|
|
9
|
+
* Rules:
|
|
10
|
+
* - ↑ / ↓ follow edges to the nearest (by horizontal position) dependency / dependent. Pressing the SAME
|
|
11
|
+
* key again cycles through the other candidates of the node the sequence started from.
|
|
12
|
+
* - ← / → move to the neighbour in the same rank (by horizontal position), wrapping around.
|
|
13
|
+
* - Tab / Shift+Tab step through all nodes in task order, wrapping — a guaranteed way to reach any node.
|
|
14
|
+
* - A key with nothing to move to leaves the selection unchanged.
|
|
15
|
+
*/
|
|
16
|
+
export type NavKey = 'up' | 'down' | 'left' | 'right' | 'tab' | 'shiftTab';
|
|
17
|
+
export interface NavModel {
|
|
18
|
+
ids: string[];
|
|
19
|
+
/** Task order, used by Tab (usually the plan's own order). */
|
|
20
|
+
taskOrder: string[];
|
|
21
|
+
/** Box centre x and top y; rank is decided by y (equal y = same rank). */
|
|
22
|
+
x: Record<string, number>;
|
|
23
|
+
y: Record<string, number>;
|
|
24
|
+
deps: Record<string, string[]>;
|
|
25
|
+
dependents: Record<string, string[]>;
|
|
26
|
+
}
|
|
27
|
+
export interface NavState {
|
|
28
|
+
cur: string;
|
|
29
|
+
lastKey?: NavKey;
|
|
30
|
+
/** For a repeated vertical key: the node the cycling started from. */
|
|
31
|
+
lastFrom?: string;
|
|
32
|
+
/** How many times the same vertical key has been repeated. */
|
|
33
|
+
k: number;
|
|
34
|
+
}
|
|
35
|
+
export interface Navigator {
|
|
36
|
+
start(model: NavModel, id: string): NavState;
|
|
37
|
+
press(model: NavModel, state: NavState, key: NavKey): NavState;
|
|
38
|
+
}
|
|
39
|
+
export declare function navModelFrom(nodes: readonly VizNode[], boxes: readonly Box[]): NavModel;
|
|
40
|
+
export declare const referenceNavigator: Navigator;
|
|
41
|
+
/** Every node reachable from `startId` using only the four arrow keys (explores real key state, with repeats). */
|
|
42
|
+
export declare function reachableByArrows(nav: Navigator, m: NavModel, startId: string): Set<string>;
|
|
43
|
+
/** Arrow-only reachability: every node of a connected plan is reachable from the start node. */
|
|
44
|
+
export declare function checkReachability(nav: Navigator, m: NavModel, startId?: string): string[];
|
|
45
|
+
/** Tab visits every node once in task order and returns to the start; Shift+Tab is its exact inverse. */
|
|
46
|
+
export declare function checkTabCycle(nav: Navigator, m: NavModel): string[];
|
|
47
|
+
/** A vertical key with no candidate leaves the selection (and state) untouched. */
|
|
48
|
+
export declare function checkBoundaries(nav: Navigator, m: NavModel): string[];
|
|
49
|
+
/** ← and → stay in the rank, wrap, and are inverses of each other. */
|
|
50
|
+
export declare function checkHorizontal(nav: Navigator, m: NavModel): string[];
|
|
51
|
+
/** Repeating ↓ (↑) visits each dependent (dependency) exactly once, then wraps. */
|
|
52
|
+
export declare function checkRepeatCycles(nav: Navigator, m: NavModel): string[];
|
|
53
|
+
/** The highlighted edges for a selection are exactly the edges touching that node. */
|
|
54
|
+
export declare function checkHighlightIncident(m: NavModel, edges: readonly Edge[], highlight: (id: string) => readonly Edge[]): string[];
|
|
55
|
+
export interface Viewport {
|
|
56
|
+
left: number;
|
|
57
|
+
top: number;
|
|
58
|
+
width: number;
|
|
59
|
+
height: number;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Executable specification for panning: keep the selected box fully visible when it fits, never leave
|
|
63
|
+
* the diagram, and never exceed the terminal. Scrolls the minimum amount from the previous viewport so the
|
|
64
|
+
* picture does not jump while navigating.
|
|
65
|
+
*/
|
|
66
|
+
export declare function followSelection(prev: Viewport, box: Box, grid: {
|
|
67
|
+
width: number;
|
|
68
|
+
height: number;
|
|
69
|
+
}, term: {
|
|
70
|
+
cols: number;
|
|
71
|
+
rows: number;
|
|
72
|
+
}): Viewport;
|
|
73
|
+
export declare function checkViewport(v: Viewport, box: Box, grid: {
|
|
74
|
+
width: number;
|
|
75
|
+
height: number;
|
|
76
|
+
}, term: {
|
|
77
|
+
cols: number;
|
|
78
|
+
rows: number;
|
|
79
|
+
}): string[];
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared types for the plan-visualization test kit. The kit contains fixtures, seeded generators and
|
|
3
|
+
* *oracles* (independent correctness checkers) that the layout, rasterizer, navigation and pane tests all
|
|
4
|
+
* use, so every layer is held to the same definition of "correct". Nothing here is production code and
|
|
5
|
+
* nothing here is exported from the package index.
|
|
6
|
+
*/
|
|
7
|
+
export { VIZ_STATUSES } from '../types.js';
|
|
8
|
+
export type { VizStatus, VizNode, Box, Edge, RenderResult } from '../types.js';
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Production types for the plan visualization: the status vocabulary the renderers receive, the node
|
|
3
|
+
* shape the layout consumes, and what a rasterizer returns. The test kit re-exports these so there is
|
|
4
|
+
* one definition.
|
|
5
|
+
*/
|
|
6
|
+
/** The status vocabulary the renderer receives (the adapter maps aielia TaskStatus onto it). */
|
|
7
|
+
export type VizStatus = 'pending' | 'ready' | 'running' | 'done' | 'failed' | 'awaiting_user' | 'awaiting_input' | 'cancelled';
|
|
8
|
+
export declare const VIZ_STATUSES: readonly VizStatus[];
|
|
9
|
+
export interface VizNode {
|
|
10
|
+
id: string;
|
|
11
|
+
label: string;
|
|
12
|
+
status: VizStatus;
|
|
13
|
+
/** Ids this node depends on (they are drawn above it). */
|
|
14
|
+
deps: string[];
|
|
15
|
+
}
|
|
16
|
+
/** A node rectangle on the character grid, in cells (a double-width character occupies two cells). */
|
|
17
|
+
export interface Box {
|
|
18
|
+
id: string;
|
|
19
|
+
x: number;
|
|
20
|
+
y: number;
|
|
21
|
+
w: number;
|
|
22
|
+
h: number;
|
|
23
|
+
}
|
|
24
|
+
/** `from` is the dependency (drawn above), `to` the dependent (drawn below). */
|
|
25
|
+
export interface Edge {
|
|
26
|
+
from: string;
|
|
27
|
+
to: string;
|
|
28
|
+
}
|
|
29
|
+
/** What a rasterizer must return for the oracles to be able to check it. */
|
|
30
|
+
export interface RenderResult {
|
|
31
|
+
lines: string[];
|
|
32
|
+
boxes: Box[];
|
|
33
|
+
edges: Edge[];
|
|
34
|
+
}
|