agentfootprint-lens 0.44.0 → 0.46.0
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 +133 -0
- package/dist/{Lens-B039-UGw.d.cts → Lens-6elRg27j.d.cts} +22 -5
- package/dist/{Lens-ey1EgN9i.d.ts → Lens-Bdz-JzVm.d.ts} +22 -5
- package/dist/{chunk-OQRL3II6.js → chunk-2UOQEE4U.js} +114 -4
- package/dist/chunk-2UOQEE4U.js.map +1 -0
- package/dist/{chunk-LRGT7UQL.js → chunk-A4EIPCLY.js} +52 -31
- package/dist/chunk-A4EIPCLY.js.map +1 -0
- package/dist/{chunk-QNMA25X5.js → chunk-AUGRQKRL.js} +18 -6
- package/dist/chunk-AUGRQKRL.js.map +1 -0
- package/dist/{chunk-CGR5VFJU.js → chunk-SJEKKUTI.js} +113 -3
- package/dist/chunk-SJEKKUTI.js.map +1 -0
- package/dist/{chunk-5YSPWSLW.js → chunk-WN2RJKEH.js} +2 -2
- package/dist/core.cjs +125 -11
- package/dist/core.cjs.map +1 -1
- package/dist/core.d.cts +3 -3
- package/dist/core.d.ts +3 -3
- package/dist/core.js +6 -2
- package/dist/index.cjs +302 -46
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +48 -8
- package/dist/index.d.ts +48 -8
- package/dist/index.js +9 -5
- package/dist/index.js.map +1 -1
- package/dist/{scrubAxisFor-Cz214OHj.d.ts → lensStops-DAc3GB8G.d.ts} +157 -1
- package/dist/{scrubAxisFor-CNceBlz-.d.cts → lensStops-hQ10t3Lt.d.cts} +157 -1
- package/dist/{selectSkillFrameContext-CT_EKu4u.d.cts → selectSkillFrameContext-DJkvrggG.d.cts} +1 -1
- package/dist/{selectSkillFrameContext-D0xQV_px.d.ts → selectSkillFrameContext-IPsw4Pbj.d.ts} +1 -1
- package/dist/skillgraph.cjs +129 -7
- package/dist/skillgraph.cjs.map +1 -1
- package/dist/skillgraph.d.cts +2 -2
- package/dist/skillgraph.d.ts +2 -2
- package/dist/skillgraph.js +2 -2
- package/dist/why.cjs +186 -40
- package/dist/why.cjs.map +1 -1
- package/dist/why.d.cts +5 -4
- package/dist/why.d.ts +5 -4
- package/dist/why.js +7 -3
- package/dist/why.js.map +1 -1
- package/package.json +3 -3
- package/dist/chunk-CGR5VFJU.js.map +0 -1
- package/dist/chunk-LRGT7UQL.js.map +0 -1
- package/dist/chunk-OQRL3II6.js.map +0 -1
- package/dist/chunk-QNMA25X5.js.map +0 -1
- /package/dist/{chunk-5YSPWSLW.js.map → chunk-WN2RJKEH.js.map} +0 -0
package/README.md
CHANGED
|
@@ -808,6 +808,133 @@ const href = to.ok ? `/runs/${runId}?step=${to.step}` : undefined;
|
|
|
808
808
|
|
|
809
809
|
---
|
|
810
810
|
|
|
811
|
+
## Time travel through one port
|
|
812
|
+
|
|
813
|
+
**Nothing to do — this is how the cursor already moves.** Read it if you are
|
|
814
|
+
building a second surface over the same run, or wondering why the ruler behaves
|
|
815
|
+
identically in the Why Lens, the Flow Lens and your own view.
|
|
816
|
+
|
|
817
|
+
### Why
|
|
818
|
+
|
|
819
|
+
Every consumer of a footprintjs run was writing the same six lines: clamp at
|
|
820
|
+
zero, clamp at the end, resolve an address to a stop, decide what a miss does.
|
|
821
|
+
The lens had them in `<TimeTravel>`, the flow view had its own copy, and a
|
|
822
|
+
dashboard had a third — and they disagreed at exactly the places nobody tests: a
|
|
823
|
+
▶ at the last stop, a jump to a stage that is not on this ruler, a step stored
|
|
824
|
+
from a longer run.
|
|
825
|
+
|
|
826
|
+
footprintjs 9.17 owns that arithmetic now. `timeTravel(snapshot, { strategy })`
|
|
827
|
+
is the **reader's cursor over a finished trace**: `first` / `last` / `prev` /
|
|
828
|
+
`next` / `jumpTo`, one position, and one law — **a refused move never moves the
|
|
829
|
+
cursor**, it returns the reason and the nearest stop it could name. Since
|
|
830
|
+
0.46.0 the lens's movement goes through it.
|
|
831
|
+
|
|
832
|
+
**Which stops exist did not change.** The lens still computes its own axis —
|
|
833
|
+
milestones banded by iteration for the Why reading, one stop per executed stage
|
|
834
|
+
for the Flow reading, drill-scoped either way — with the same labels, the same
|
|
835
|
+
order and the same kinds. Those positions ARE the port's stops, through a
|
|
836
|
+
lens-owned `TimeTravelStrategy`. The library decides *where a move lands*; the
|
|
837
|
+
lens decides *what there is to land on*.
|
|
838
|
+
|
|
839
|
+
**Still one cursor.** The port instance is a calculator, not a position: it is
|
|
840
|
+
re-seated on the step the lens owns before every question and remembers nothing
|
|
841
|
+
between them. `<Lens step onStepChange>` is unchanged, and so is everything a
|
|
842
|
+
panel reads.
|
|
843
|
+
|
|
844
|
+
### The port, headless
|
|
845
|
+
|
|
846
|
+
```ts
|
|
847
|
+
import { scrubAxisFor, openLensCursor } from 'agentfootprint-lens/core';
|
|
848
|
+
|
|
849
|
+
const positions = scrubAxisFor(recorder, 'group'); // the ruler, as data
|
|
850
|
+
const cursor = openLensCursor(positions);
|
|
851
|
+
|
|
852
|
+
cursor.next(4).step; // 5
|
|
853
|
+
cursor.next(positions.length - 1);
|
|
854
|
+
// { step: <last>, moved: false, reason: 'clamped', clamped: false }
|
|
855
|
+
|
|
856
|
+
cursor.toStep(2, 9999);
|
|
857
|
+
// { step: <last>, moved: true, clamped: true } ← off the axis, said so
|
|
858
|
+
|
|
859
|
+
cursor.toAddress(2, 'call-llm#18');
|
|
860
|
+
// { ok: true, step: 7 }
|
|
861
|
+
cursor.toAddress(2, 'never-ran#4');
|
|
862
|
+
// { ok: false, reason: 'miss', nearest: <the closest stop the library
|
|
863
|
+
// could name — the same stage at another execution index if this axis
|
|
864
|
+
// holds one, otherwise the last stop whose execution index is not past
|
|
865
|
+
// the one you asked for> }
|
|
866
|
+
// the cursor is still at 2 — a miss is offered, never taken
|
|
867
|
+
|
|
868
|
+
cursor.positionAt(7);
|
|
869
|
+
// the LENS position: runtimeGroupId, depth, coActiveGroupIds, milestone —
|
|
870
|
+
// everything the port's `Stop` has no slot for, unchanged and unflattened
|
|
871
|
+
```
|
|
872
|
+
|
|
873
|
+
`openLensCursor` answers **where**, never **what**: it has no `stateAt`, no
|
|
874
|
+
`changedSince`, no `drill`. Those are folds over the run's commit log, and a
|
|
875
|
+
fold wants the run's snapshot — which movement never reads. Want them over this
|
|
876
|
+
same ruler? Build the library's cursor directly, with the lens's stops:
|
|
877
|
+
|
|
878
|
+
```ts
|
|
879
|
+
import { timeTravel } from 'footprintjs/trace';
|
|
880
|
+
import { scrubAxisFor, lensStopsStrategy } from 'agentfootprint-lens/core';
|
|
881
|
+
|
|
882
|
+
// A LIVE run. `runner.getLastSnapshot()` IS footprintjs's own snapshot, so it
|
|
883
|
+
// is already a `TimeTravelSource` and the two libraries meet with no cast.
|
|
884
|
+
const snapshot = runner.getLastSnapshot();
|
|
885
|
+
if (snapshot) {
|
|
886
|
+
const positions = scrubAxisFor(recorder, 'group');
|
|
887
|
+
const tt = timeTravel(snapshot, { strategy: lensStopsStrategy(positions) });
|
|
888
|
+
tt.jumpTo(7);
|
|
889
|
+
tt.changedSince(); // the keys this stop's slice of the log wrote
|
|
890
|
+
tt.stateAt().state; // state as of that stop, detached
|
|
891
|
+
}
|
|
892
|
+
```
|
|
893
|
+
|
|
894
|
+
A **stored** recording needs one narrowing today, and the reason is honest on
|
|
895
|
+
both sides: the lens types `Recording.snapshot.commitLog` as `readonly
|
|
896
|
+
unknown[]` — a recording arrives as parsed JSON, and the lens will not claim
|
|
897
|
+
that what came back off disk is a `CommitBundle` — while `timeTravel` takes
|
|
898
|
+
`TimeTravelSource`, whose `commitLog` is `readonly CommitBundle[]`. So a
|
|
899
|
+
replayed run has to say so at the seam:
|
|
900
|
+
|
|
901
|
+
```ts
|
|
902
|
+
import type { TimeTravelSource } from 'footprintjs/trace';
|
|
903
|
+
|
|
904
|
+
const stored = recording.snapshot as unknown as TimeTravelSource;
|
|
905
|
+
const tt = timeTravel(stored, { strategy: lensStopsStrategy(positions) });
|
|
906
|
+
```
|
|
907
|
+
|
|
908
|
+
That cast disappears — with no change here — the day footprintjs widens
|
|
909
|
+
`TimeTravelSource.commitLog` to accept an unvalidated `readonly unknown[]` and
|
|
910
|
+
does the per-bundle narrowing where it folds, which is the only place that can
|
|
911
|
+
honestly do it. It is reported upstream as a port gap. **Movement never needs
|
|
912
|
+
this**: `openLensCursor` reads the stops and no snapshot at all, which is why
|
|
913
|
+
the lens's own cursor is unaffected either way.
|
|
914
|
+
|
|
915
|
+
### Two axes, and drilling
|
|
916
|
+
|
|
917
|
+
Rebuild the port when the positions change; its identity is that list's, which
|
|
918
|
+
is already memoised per (recording, axis, drill level):
|
|
919
|
+
|
|
920
|
+
```ts
|
|
921
|
+
const port = useMemo(() => openLensCursor(positions), [positions]);
|
|
922
|
+
```
|
|
923
|
+
|
|
924
|
+
Drilling rebuilds the axis — the drilled group's own stops, which is a
|
|
925
|
+
different set — so it rebuilds the port. The lens does **not** use the port's
|
|
926
|
+
`drill()` for this: `drill()` opens a subflow's own commit log, and a lens drill
|
|
927
|
+
level is not always a subflow (it is a group, and a subflow whose stages commit
|
|
928
|
+
in their own memory scope is reconstructed from the runtime overlay). Using it
|
|
929
|
+
would change which stops appear at a drill level, which is the one thing this
|
|
930
|
+
change refuses to do.
|
|
931
|
+
|
|
932
|
+
`snapSteps` also stays the lens's. Snaps narrow ◀ ▶ to a *subset* of the axis
|
|
933
|
+
while the cursor may be parked between two of them — a question `jumpTo` does
|
|
934
|
+
not answer, since it takes an exact stop.
|
|
935
|
+
|
|
936
|
+
---
|
|
937
|
+
|
|
811
938
|
## Rendering your own detail pane
|
|
812
939
|
|
|
813
940
|
`slots.detail` replaces the CONTENT of the shipped right column. The column
|
|
@@ -1112,6 +1239,12 @@ so instead of drawing an empty graph.
|
|
|
1112
1239
|
/ CLI view on the same primitives — see `ChangeNotifier`'s JSDoc for adapter
|
|
1113
1240
|
snippets.
|
|
1114
1241
|
|
|
1242
|
+
The cursor is headless too: `scrubAxisFor` builds the ruler, `openLensCursor`
|
|
1243
|
+
moves along it through footprintjs's `timeTravel()` port, `resolveNavigation`
|
|
1244
|
+
turns an address into a step with every rung named, and `stepForCommitIdx`
|
|
1245
|
+
carries a position between the two axes. See
|
|
1246
|
+
[Time travel through one port](#time-travel-through-one-port).
|
|
1247
|
+
|
|
1115
1248
|
---
|
|
1116
1249
|
|
|
1117
1250
|
## Why this design
|
|
@@ -4,7 +4,7 @@ import * as agentfootprint from 'agentfootprint';
|
|
|
4
4
|
import { CommentaryTemplates } from 'agentfootprint';
|
|
5
5
|
import React__default, { Ref } from 'react';
|
|
6
6
|
import { d as NavigationResult, C as CursorPosition, L as LensRecorder } from './resolveNavigation-o4E4cM_1.cjs';
|
|
7
|
-
import { C as ChartGroupHighlight, H as Humanizer } from './
|
|
7
|
+
import { C as ChartGroupHighlight, a as LensCursorPort, H as Humanizer } from './lensStops-hQ10t3Lt.cjs';
|
|
8
8
|
import { NodeTypes } from '@xyflow/react';
|
|
9
9
|
import { TraceGraph, TraceFlowLayout, RuntimeOverlay } from 'footprint-explainable-ui/flowchart';
|
|
10
10
|
|
|
@@ -153,6 +153,7 @@ declare const LensFlow: React__default.FC<LensFlowProps>;
|
|
|
153
153
|
* Omit `controlledStep` and nothing changes: the hook keeps today's internal
|
|
154
154
|
* state and today's auto-advance, byte for byte.
|
|
155
155
|
*/
|
|
156
|
+
|
|
156
157
|
/**
|
|
157
158
|
* Where the cursor landed, in all three units the lens knows — handed to
|
|
158
159
|
* `onStepChange` alongside the step so a host never has to reverse-engineer
|
|
@@ -178,9 +179,13 @@ interface LensCursorAt {
|
|
|
178
179
|
/** What kind of stop this is. Absent when the axis is empty. */
|
|
179
180
|
readonly kind?: string;
|
|
180
181
|
/**
|
|
181
|
-
* `true` when this call is Lens CORRECTING
|
|
182
|
-
*
|
|
183
|
-
*
|
|
182
|
+
* `true` when this call is Lens CORRECTING a step that is not a position on
|
|
183
|
+
* the axis it is now read against, not a move someone made. That is an
|
|
184
|
+
* out-of-range `step` you passed, one an internal jump produced, OR — when
|
|
185
|
+
* you passed no `step` at all — the lens's own remembered step after the
|
|
186
|
+
* axis shrank under it. Uncontrolled snaps are reported too, so this flag
|
|
187
|
+
* means the same thing in both modes. Store the corrected value and the two
|
|
188
|
+
* cursors agree again.
|
|
184
189
|
*/
|
|
185
190
|
readonly clamped: boolean;
|
|
186
191
|
}
|
|
@@ -201,6 +206,18 @@ interface UseLensCursorArgs {
|
|
|
201
206
|
readonly maxStep: number;
|
|
202
207
|
/** Resolve a step to its address. Called only when a move is reported. */
|
|
203
208
|
readonly describe: (step: number) => LensCursorPlace;
|
|
209
|
+
/**
|
|
210
|
+
* The MOVEMENT port — footprintjs 9.17's reader cursor over the Lens's own
|
|
211
|
+
* stops (`openLensCursor(positions)`). When present, every move this funnel
|
|
212
|
+
* makes is decided by the library: where a step lands, what happens at the
|
|
213
|
+
* ends of the axis, and what an out-of-range ask does. Omit it and the
|
|
214
|
+
* funnel keeps its own arithmetic, unchanged — which is what the hook's own
|
|
215
|
+
* tests drive, so the two readings can be compared.
|
|
216
|
+
*
|
|
217
|
+
* It is NOT a second cursor: the port is re-seated on the step this hook
|
|
218
|
+
* owns before every question and remembers nothing between them.
|
|
219
|
+
*/
|
|
220
|
+
readonly port?: LensCursorPort | undefined;
|
|
204
221
|
}
|
|
205
222
|
interface UseLensCursorResult {
|
|
206
223
|
/** The cursor to render. */
|
|
@@ -215,7 +232,7 @@ interface UseLensCursorResult {
|
|
|
215
232
|
* are not positions, so they clamp too — and the clamp is always reported.
|
|
216
233
|
*/
|
|
217
234
|
declare function clampStep(n: number, maxStep: number): number;
|
|
218
|
-
declare function useLensCursor({ controlledStep, onStepChange, maxStep, describe, }: UseLensCursorArgs): UseLensCursorResult;
|
|
235
|
+
declare function useLensCursor({ controlledStep, onStepChange, maxStep, describe, port, }: UseLensCursorArgs): UseLensCursorResult;
|
|
219
236
|
|
|
220
237
|
/**
|
|
221
238
|
* useLensNavigator — move the ONE cursor to a stage by its address.
|
|
@@ -4,7 +4,7 @@ import * as agentfootprint from 'agentfootprint';
|
|
|
4
4
|
import { CommentaryTemplates } from 'agentfootprint';
|
|
5
5
|
import React__default, { Ref } from 'react';
|
|
6
6
|
import { d as NavigationResult, C as CursorPosition, L as LensRecorder } from './resolveNavigation-o4E4cM_1.js';
|
|
7
|
-
import { C as ChartGroupHighlight, H as Humanizer } from './
|
|
7
|
+
import { C as ChartGroupHighlight, a as LensCursorPort, H as Humanizer } from './lensStops-DAc3GB8G.js';
|
|
8
8
|
import { NodeTypes } from '@xyflow/react';
|
|
9
9
|
import { TraceGraph, TraceFlowLayout, RuntimeOverlay } from 'footprint-explainable-ui/flowchart';
|
|
10
10
|
|
|
@@ -153,6 +153,7 @@ declare const LensFlow: React__default.FC<LensFlowProps>;
|
|
|
153
153
|
* Omit `controlledStep` and nothing changes: the hook keeps today's internal
|
|
154
154
|
* state and today's auto-advance, byte for byte.
|
|
155
155
|
*/
|
|
156
|
+
|
|
156
157
|
/**
|
|
157
158
|
* Where the cursor landed, in all three units the lens knows — handed to
|
|
158
159
|
* `onStepChange` alongside the step so a host never has to reverse-engineer
|
|
@@ -178,9 +179,13 @@ interface LensCursorAt {
|
|
|
178
179
|
/** What kind of stop this is. Absent when the axis is empty. */
|
|
179
180
|
readonly kind?: string;
|
|
180
181
|
/**
|
|
181
|
-
* `true` when this call is Lens CORRECTING
|
|
182
|
-
*
|
|
183
|
-
*
|
|
182
|
+
* `true` when this call is Lens CORRECTING a step that is not a position on
|
|
183
|
+
* the axis it is now read against, not a move someone made. That is an
|
|
184
|
+
* out-of-range `step` you passed, one an internal jump produced, OR — when
|
|
185
|
+
* you passed no `step` at all — the lens's own remembered step after the
|
|
186
|
+
* axis shrank under it. Uncontrolled snaps are reported too, so this flag
|
|
187
|
+
* means the same thing in both modes. Store the corrected value and the two
|
|
188
|
+
* cursors agree again.
|
|
184
189
|
*/
|
|
185
190
|
readonly clamped: boolean;
|
|
186
191
|
}
|
|
@@ -201,6 +206,18 @@ interface UseLensCursorArgs {
|
|
|
201
206
|
readonly maxStep: number;
|
|
202
207
|
/** Resolve a step to its address. Called only when a move is reported. */
|
|
203
208
|
readonly describe: (step: number) => LensCursorPlace;
|
|
209
|
+
/**
|
|
210
|
+
* The MOVEMENT port — footprintjs 9.17's reader cursor over the Lens's own
|
|
211
|
+
* stops (`openLensCursor(positions)`). When present, every move this funnel
|
|
212
|
+
* makes is decided by the library: where a step lands, what happens at the
|
|
213
|
+
* ends of the axis, and what an out-of-range ask does. Omit it and the
|
|
214
|
+
* funnel keeps its own arithmetic, unchanged — which is what the hook's own
|
|
215
|
+
* tests drive, so the two readings can be compared.
|
|
216
|
+
*
|
|
217
|
+
* It is NOT a second cursor: the port is re-seated on the step this hook
|
|
218
|
+
* owns before every question and remembers nothing between them.
|
|
219
|
+
*/
|
|
220
|
+
readonly port?: LensCursorPort | undefined;
|
|
204
221
|
}
|
|
205
222
|
interface UseLensCursorResult {
|
|
206
223
|
/** The cursor to render. */
|
|
@@ -215,7 +232,7 @@ interface UseLensCursorResult {
|
|
|
215
232
|
* are not positions, so they clamp too — and the clamp is always reported.
|
|
216
233
|
*/
|
|
217
234
|
declare function clampStep(n: number, maxStep: number): number;
|
|
218
|
-
declare function useLensCursor({ controlledStep, onStepChange, maxStep, describe, }: UseLensCursorArgs): UseLensCursorResult;
|
|
235
|
+
declare function useLensCursor({ controlledStep, onStepChange, maxStep, describe, port, }: UseLensCursorArgs): UseLensCursorResult;
|
|
219
236
|
|
|
220
237
|
/**
|
|
221
238
|
* useLensNavigator — move the ONE cursor to a stage by its address.
|
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
describeReceived,
|
|
7
7
|
refusalDestinationFor,
|
|
8
8
|
useNarrowRow
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-AUGRQKRL.js";
|
|
10
10
|
import {
|
|
11
11
|
selectSkillBeatAt,
|
|
12
12
|
selectSkillBeats,
|
|
@@ -608,7 +608,7 @@ var CAUSE_LABEL = {
|
|
|
608
608
|
stay: "nothing moved it",
|
|
609
609
|
none: "no skill was in play"
|
|
610
610
|
};
|
|
611
|
-
function RouteDecisionCard({ beat, lens }) {
|
|
611
|
+
function RouteDecisionCard({ beat, turnStart, lens }) {
|
|
612
612
|
return /* @__PURE__ */ jsx4(
|
|
613
613
|
"aside",
|
|
614
614
|
{
|
|
@@ -736,6 +736,7 @@ function RouteDecisionCard({ beat, lens }) {
|
|
|
736
736
|
children: beat.notes.map((n, i) => /* @__PURE__ */ jsx4("li", { children: n }, i))
|
|
737
737
|
}
|
|
738
738
|
),
|
|
739
|
+
turnStart !== void 0 && (turnStart.by === "intent" || turnStart.by === "continuity") && /* @__PURE__ */ jsx4(ScoreTable, { start: turnStart }),
|
|
739
740
|
lens === "developer" && beat.runtimeStageId !== void 0 && /* @__PURE__ */ jsx4("div", { style: { marginTop: 8, fontFamily: T.fontMono, fontSize: 10, color: T.textMuted }, children: beat.runtimeStageId })
|
|
740
741
|
] })
|
|
741
742
|
}
|
|
@@ -761,6 +762,104 @@ function Evidence({
|
|
|
761
762
|
children
|
|
762
763
|
] });
|
|
763
764
|
}
|
|
765
|
+
function ScoreTable({ start }) {
|
|
766
|
+
if (start.scores.length === 0) return null;
|
|
767
|
+
const floor = start.policy?.floor;
|
|
768
|
+
const margin = start.policy?.nearTieMargin;
|
|
769
|
+
return /* @__PURE__ */ jsxs4("div", { style: { marginTop: 8 }, children: [
|
|
770
|
+
/* @__PURE__ */ jsxs4(
|
|
771
|
+
"div",
|
|
772
|
+
{
|
|
773
|
+
style: {
|
|
774
|
+
fontSize: 10,
|
|
775
|
+
letterSpacing: "0.08em",
|
|
776
|
+
textTransform: "uppercase",
|
|
777
|
+
color: T.textMuted,
|
|
778
|
+
marginBottom: 4
|
|
779
|
+
},
|
|
780
|
+
children: [
|
|
781
|
+
"Scored",
|
|
782
|
+
start.scorer ? ` by ${start.scorer}` : "",
|
|
783
|
+
floor !== void 0 ? ` \xB7 floor ${floor}` : "",
|
|
784
|
+
start.runnerUp !== void 0 && margin !== void 0 ? ` \xB7 gap ${fmt(start.runnerUp.gap)} of ${margin} needed` : ""
|
|
785
|
+
]
|
|
786
|
+
}
|
|
787
|
+
),
|
|
788
|
+
/* @__PURE__ */ jsxs4(
|
|
789
|
+
"table",
|
|
790
|
+
{
|
|
791
|
+
style: { borderCollapse: "collapse", width: "100%", fontSize: 12 },
|
|
792
|
+
children: [
|
|
793
|
+
/* @__PURE__ */ jsx4(
|
|
794
|
+
"caption",
|
|
795
|
+
{
|
|
796
|
+
style: {
|
|
797
|
+
captionSide: "top",
|
|
798
|
+
textAlign: "left",
|
|
799
|
+
fontSize: 11,
|
|
800
|
+
color: T.textMuted,
|
|
801
|
+
paddingBottom: 3
|
|
802
|
+
},
|
|
803
|
+
children: "Every candidate this turn was scored against, best first."
|
|
804
|
+
}
|
|
805
|
+
),
|
|
806
|
+
/* @__PURE__ */ jsx4("tbody", { children: start.scores.map((row) => {
|
|
807
|
+
const belowFloor = floor !== void 0 && row.score <= floor;
|
|
808
|
+
const won = row.id === start.to;
|
|
809
|
+
return /* @__PURE__ */ jsxs4("tr", { children: [
|
|
810
|
+
/* @__PURE__ */ jsxs4(
|
|
811
|
+
"td",
|
|
812
|
+
{
|
|
813
|
+
style: {
|
|
814
|
+
padding: "2px 6px 2px 0",
|
|
815
|
+
color: belowFloor ? T.textMuted : T.textPrimary,
|
|
816
|
+
fontWeight: won ? 700 : 400,
|
|
817
|
+
fontFamily: T.fontMono
|
|
818
|
+
},
|
|
819
|
+
children: [
|
|
820
|
+
won ? "\u2192 " : " ",
|
|
821
|
+
row.id
|
|
822
|
+
]
|
|
823
|
+
}
|
|
824
|
+
),
|
|
825
|
+
/* @__PURE__ */ jsx4(
|
|
826
|
+
"td",
|
|
827
|
+
{
|
|
828
|
+
style: {
|
|
829
|
+
padding: "2px 6px",
|
|
830
|
+
textAlign: "right",
|
|
831
|
+
fontFamily: T.fontMono,
|
|
832
|
+
color: belowFloor ? T.textMuted : T.textPrimary
|
|
833
|
+
},
|
|
834
|
+
children: fmt(row.score)
|
|
835
|
+
}
|
|
836
|
+
),
|
|
837
|
+
/* @__PURE__ */ jsxs4(
|
|
838
|
+
"td",
|
|
839
|
+
{
|
|
840
|
+
style: {
|
|
841
|
+
padding: "2px 6px",
|
|
842
|
+
textAlign: "right",
|
|
843
|
+
fontFamily: T.fontMono,
|
|
844
|
+
color: T.textMuted
|
|
845
|
+
},
|
|
846
|
+
children: [
|
|
847
|
+
Math.round(row.relevance * 100),
|
|
848
|
+
"%"
|
|
849
|
+
]
|
|
850
|
+
}
|
|
851
|
+
),
|
|
852
|
+
/* @__PURE__ */ jsx4("td", { style: { padding: "2px 0 2px 6px", color: T.textMuted, fontSize: 11 }, children: belowFloor ? "below floor" : won ? "" : "beaten" })
|
|
853
|
+
] }, row.id);
|
|
854
|
+
}) })
|
|
855
|
+
]
|
|
856
|
+
}
|
|
857
|
+
)
|
|
858
|
+
] });
|
|
859
|
+
}
|
|
860
|
+
function fmt(n) {
|
|
861
|
+
return String(Math.round(n * 1e3) / 1e3);
|
|
862
|
+
}
|
|
764
863
|
|
|
765
864
|
// src/react/skillgraph/skillTopologyPositions.ts
|
|
766
865
|
function skillTopologyPositions(nodeIds, edges) {
|
|
@@ -1123,6 +1222,10 @@ function SkillGraphDebugger({
|
|
|
1123
1222
|
[beats, cursorRuntimeStageId, cursorKind]
|
|
1124
1223
|
);
|
|
1125
1224
|
const activeIndex = activeBeat?.index;
|
|
1225
|
+
const activeTurnStart = useMemo2(
|
|
1226
|
+
() => activeBeat === void 0 || route === void 0 ? void 0 : route.turns.find((t) => t.turnIndex === activeBeat.turnIndex),
|
|
1227
|
+
[route, activeBeat]
|
|
1228
|
+
);
|
|
1126
1229
|
const topology = useMemo2(
|
|
1127
1230
|
() => route !== void 0 ? selectSkillTopology({
|
|
1128
1231
|
route,
|
|
@@ -1264,7 +1367,14 @@ function SkillGraphDebugger({
|
|
|
1264
1367
|
onPickSkill: jumpToSkill
|
|
1265
1368
|
}
|
|
1266
1369
|
) }),
|
|
1267
|
-
/* @__PURE__ */ jsx6(
|
|
1370
|
+
/* @__PURE__ */ jsx6(
|
|
1371
|
+
RouteDecisionCard,
|
|
1372
|
+
{
|
|
1373
|
+
...activeBeat !== void 0 ? { beat: activeBeat } : {},
|
|
1374
|
+
...activeTurnStart !== void 0 ? { turnStart: activeTurnStart } : {},
|
|
1375
|
+
lens
|
|
1376
|
+
}
|
|
1377
|
+
)
|
|
1268
1378
|
]
|
|
1269
1379
|
}
|
|
1270
1380
|
),
|
|
@@ -1382,4 +1492,4 @@ export {
|
|
|
1382
1492
|
SKILL_GRAPH_READS,
|
|
1383
1493
|
SkillGraphDebugger
|
|
1384
1494
|
};
|
|
1385
|
-
//# sourceMappingURL=chunk-
|
|
1495
|
+
//# sourceMappingURL=chunk-2UOQEE4U.js.map
|