fix(ci): card points re-typed for the non-strict builds, formatting, strict ratchet and two assistant e2e checks

This commit is contained in:
Maurice
2026-10-22 16:44:46 +02:00
parent 162f2996d2
commit 88cd4fba6e
23 changed files with 143 additions and 67 deletions
@@ -16,7 +16,11 @@ const SHOWN = 8;
function listCard(input: AnswerInput, rows: Row[], toRow: (raw: Row) => BookingRow): TrekCard | null {
const scope = scopeOfCard(input.card);
return bookingCard('none', rows.slice(0, SHOWN).map((raw) => bookingItemOf(toRow(raw), scope)), rows.length);
return bookingCard(
'none',
rows.slice(0, SHOWN).map((raw) => bookingItemOf(toRow(raw), scope)),
rows.length,
);
}
/** A stay listed once: the list joins each booking that links it, so one stay can come twice. */
@@ -1,5 +1,5 @@
import { IMPORT_BOOKING_TOOL } from '../../assistant-tools.constants';
import type { TripCard } from '../../assistant-context';
import { IMPORT_BOOKING_TOOL } from '../../assistant-tools.constants';
import type { DomainCards, PreviewContext, ToolArgs } from '../card-types';
import { argId, clipped, idIn } from '../card-values';
import { BOOKING_ANSWERS } from './booking-answer';
@@ -28,7 +28,10 @@ function expenseName(ctx: PreviewContext, args: ToolArgs): string {
/** Who shares a stored expense, by name. */
function sharedBy(ctx: PreviewContext, row: Row | undefined): string {
return memberNames(ctx, rowsOf(row?.members).map((member) => member.user_id));
return memberNames(
ctx,
rowsOf(row?.members).map((member) => member.user_id),
);
}
/** "Ana → Ben", from the two people of a payment. */
@@ -117,7 +117,11 @@ export function splitOf(
max: number,
): Pick<CardExpense, 'split' | 'shares' | 'moreShares'> {
if (members.length === 0) return { split: 'none', shares: [], moreShares: 0 };
const equal = splitEqualShares(toMinor(total), members.map((member) => ({ user_id: member.id })), itemId);
const equal = splitEqualShares(
toMinor(total),
members.map((member) => ({ user_id: member.id })),
itemId,
);
const shares = members.map((member) => ({
person: personFrom(card, member.id, member.name, member.avatarUrl),
amount: member.amount ?? (equal[member.id] ?? 0) / 100,
@@ -73,12 +73,15 @@ export const COLLECTION_CARDS: DomainCards = {
list_collections: { answer: listsAnswer },
find_place_in_collections: { answer: membershipAnswer },
...WRITE_CARDS,
create_collection: { ...WRITE_CARDS.create_collection, undo: DELETE_CREATED_LIST },
create_collection: { ...writeCards('create_collection', WRITES.create_collection), undo: DELETE_CREATED_LIST },
save_place_to_collection: {
...WRITE_CARDS.save_place_to_collection,
...writeCards('save_place_to_collection', WRITES.save_place_to_collection),
undo: DELETE_SAVED_PLACE,
argPolicy: NO_IMAGE,
},
update_collection_place: { ...WRITE_CARDS.update_collection_place, argPolicy: NO_IMAGE },
update_collection_place: {
...writeCards('update_collection_place', WRITES.update_collection_place),
argPolicy: NO_IMAGE,
},
},
};
@@ -24,12 +24,7 @@ import {
type ListItem,
type PackingTier,
} from './packing-rows';
import {
resolvePackedState,
type PackingCardBag,
type PackingCardItem,
type PackingListCard,
} from '@trek/shared';
import { resolvePackedState, type PackingCardBag, type PackingCardItem, type PackingListCard } from '@trek/shared';
/**
* The card each packing change shows inside its change card, from the call's
@@ -330,37 +325,56 @@ export function packingAssigneesCard(ctx: PreviewContext, args: ToolArgs, loaded
const before = rowsOf(recordOf(recordOf(loaded).assignees)[raw]).flatMap((row) => positiveId(row.user_id) ?? []);
const inside = tripPacking(ctx.card).filter((item) => !item.placeholder && item.category === raw);
const personal = inside.length > 0 && inside.every((item) => item.isPrivate);
return packingCard({ type: 'trip' }, 'category', [], [
{
key: { by: 'category', name, slot: slotOf(ctx.card, raw, personal) },
assignees: peopleOf(ctx.card, chosen, 6),
assigneesRemoved: peopleOf(ctx.card, before.filter((id) => !chosen.includes(id)), 6),
items: [],
count: inside.length,
packed: inside.filter((item) => item.checked).length,
},
]);
return packingCard(
{ type: 'trip' },
'category',
[],
[
{
key: { by: 'category', name, slot: slotOf(ctx.card, raw, personal) },
assignees: peopleOf(ctx.card, chosen, 6),
assigneesRemoved: peopleOf(
ctx.card,
before.filter((id) => !chosen.includes(id)),
6,
),
items: [],
count: inside.length,
packed: inside.filter((item) => item.checked).length,
},
],
);
}
/** A bag head on a card of its own: what a change to one bag shows. */
function bagCard(card: TripCard, bag: PackingCardBag): PackingListCard {
const inside = tripPacking(card).filter((item) => !item.placeholder && bag.id !== null && item.bagId === bag.id);
return packingCard({ type: 'trip' }, 'bag', [bag], [
{
key: { by: 'bag', bagKey: bag.key },
assignees: [],
assigneesRemoved: [],
items: [],
count: inside.length,
packed: inside.filter((item) => item.checked).length,
},
]);
return packingCard(
{ type: 'trip' },
'bag',
[bag],
[
{
key: { by: 'bag', bagKey: bag.key },
assignees: [],
assigneesRemoved: [],
items: [],
count: inside.length,
packed: inside.filter((item) => item.checked).length,
},
],
);
}
/** The bag a call names (`bagId`), as the lookup read it. */
function namedBag(card: TripCard, args: ToolArgs, loaded: unknown): PackingCardBag | null {
const bagId = argId(args, 'bagId');
return bagId === null ? null : bagOf(card, rawBags(loaded).find((bag) => bag.id === bagId));
return bagId === null
? null
: bagOf(
card,
rawBags(loaded).find((bag) => bag.id === bagId),
);
}
/** `create_packing_bag`: the new bag's head, in its colour (indigo without one) and with its limit. */
@@ -204,7 +204,11 @@ export function slotOf(card: TripCard | null, category: string | null, personal:
/** The people of an assignee list (`[{ user_id }]`), as trip members. */
export function assigneesOf(card: TripCard, raw: unknown): CardPerson[] {
return peopleOf(card, rowsOf(raw).flatMap((row) => positiveId(row.user_id) ?? []), 6);
return peopleOf(
card,
rowsOf(raw).flatMap((row) => positiveId(row.user_id) ?? []),
6,
);
}
/** One bag as `list_packing_bags` answers it. */
@@ -302,7 +306,11 @@ export function packingGroups(
items: readonly ListItem[],
options: GroupOptions,
): { groups: PackingCardGroup[]; moreGroups: number } {
const buckets = bucketsOf(card, items.filter((item) => !item.placeholder), options);
const buckets = bucketsOf(
card,
items.filter((item) => !item.placeholder),
options,
);
let left = options.maxRows ?? MAX_PACKING_ROWS;
const perGroup = options.fillSingleGroup && buckets.length === 1 ? left : ROWS_PER_GROUP;
const groups = buckets.slice(0, MAX_CARD_GROUPS).map((bucket): PackingCardGroup => {
@@ -170,7 +170,11 @@ function todoAssigneesCard(ctx: PreviewContext, args: ToolArgs, loaded: TodoAssi
category,
slot: todoSlot(ctx.card, args.categoryName),
assignees: peopleOf(ctx.card, chosen, 6),
assigneesRemoved: peopleOf(ctx.card, before.filter((id) => !chosen.includes(id)), 6),
assigneesRemoved: peopleOf(
ctx.card,
before.filter((id) => !chosen.includes(id)),
6,
),
items: [],
count: inList.length,
open: inList.filter((todo) => !todo.checked).length,
@@ -113,7 +113,7 @@ export function describeSettings(ctx: PreviewContext, args: Args, loaded: SavedS
after: settingText(change.after),
});
}
return { subject: clip(ctx.card.title), rows, dayId: null, placeIds: [] };
return { subject: clip(ctx.card.title), rows, dayId: null, placeIds: [], tool: 'update_roadtrip_settings' };
}
export function describeDayEnd(ctx: PreviewContext, args: Args): Described {
@@ -129,7 +129,9 @@ export function describeImportRoute(ctx: PreviewContext, args: Args): Described
const names = Array.isArray(args.stops)
? args.stops.map((stop: unknown) => text(recordOf(stop).name)).filter((name) => name !== '')
: [];
const rows = dayRows(ctx, dayId).add('quantity', String(names.length)).add('route', clip(routeText(names)));
const rows = dayRows(ctx, dayId)
.add('quantity', String(names.length))
.add('route', clip(routeText(names)));
const ends = names.length > 0 ? routeText([names[0] ?? '', names[names.length - 1] ?? '']) : '';
return { subject: ends, rows, dayId, placeIds: [] };
}
@@ -1,6 +1,5 @@
import type { CardReader, PreviewContext, ToolArgs } from '../card-types';
import { canonicalJson, clipped, finite, recordOf, type Row } from '../card-values';
import { hikeCard } from './tour-route.cards';
import {
argText,
climbOf,
@@ -19,6 +18,7 @@ import {
straightMetres,
whole,
} from './tour-card-values';
import { hikeCard } from './tour-route.cards';
import {
hikingPreferencesOf,
TOUR_ROUTE_LIMITS,
@@ -104,7 +104,11 @@ export const VACAY_ANSWER_CARDS = {
const stats = statsOf(input.value);
if (!stats || stats.length === 0) return null;
const viewerId = input.card.viewerId;
const people = peopleOf(stats.map((row) => row.personId), knownPeople(null, [], stats), viewerId);
const people = peopleOf(
stats.map((row) => row.personId),
knownPeople(null, [], stats),
viewerId,
);
const order = new Map(people.map((person, index) => [person.id, index]));
const balances = keepKnown(stats, people)
.sort((a, b) => (order.get(a.personId) ?? 0) - (order.get(b.personId) ?? 0))
@@ -96,7 +96,10 @@ function toggleProposal(viewerId: number, args: ToolArgs, loaded: VacayLoaded, d
const was = existing ? counted(existing.kind, existing.fraction) : 0;
const will = outcome === 'remove' ? 0 : outcome === 'blocked' ? was : counted(kind, fraction);
const year = Number(date.slice(0, 4));
const periodYear = periodOf(date, loaded.stats.find((row) => row.personId === personId && row.year === year));
const periodYear = periodOf(
date,
loaded.stats.find((row) => row.personId === personId && row.year === year),
);
const counts = kind === 'vacation' && (outcome === 'add' || outcome === 'convert');
return {
date,
@@ -51,7 +51,9 @@ function tripDatesOf(card: TripCard): string[] {
/** The dated days of the trip inside `months`, as many as a card holds. */
export function tripDatesIn(card: TripCard, months: readonly CardMonth[]): string[] {
return tripDatesOf(card).filter((date) => inMonths(date, months)).slice(0, VACAY_CARD_MAX_DATES);
return tripDatesOf(card)
.filter((date) => inMonths(date, months))
.slice(0, VACAY_CARD_MAX_DATES);
}
/** The company holidays inside `months`, each date once. */
@@ -130,7 +130,10 @@ export class RoadtripPlanningMcp {
});
const betweenStops = (alongKm: number): [string, string] | null => {
if (anchors.length < 2) return null;
const index = insertIndexForAlong(anchors.map((anchor) => anchor.alongKm), alongKm);
const index = insertIndexForAlong(
anchors.map((anchor) => anchor.alongKm),
alongKm,
);
return [anchors[index - 1].name, anchors[index].name];
};
const hits = new Map<