Skip to content

feat(mocks): the deadline as a window, and a way into places from the desk - #15

Merged
tkgstrator merged 9 commits into
developfrom
feat/deadline-window
Sep 2, 2026
Merged

feat(mocks): the deadline as a window, and a way into places from the desk#15
tkgstrator merged 9 commits into
developfrom
feat/deadline-window

Conversation

@tkgstrator

@tkgstrator tkgstrator commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Mocks and design only. No app code changes — the screens still draw the old single line.

1. The deadline becomes a window

The board asserted a death estimate the player could not yet know.

The Tsukimisou record says the body was found around 20:30. The chart drew 20:15
「死亡推定」from the first turn
, before anyone had examined anything or spoken to the
doctor. The data was never at fault — db/scenarios/tsukimisou.yaml has carried
foundAt: "20:30" and estimatedDeathAt: "20:15" separately all along, and
scenario-definition.ts says in as many words that they are different things. Only the
drawing collapsed them, and foundAt reached nothing but the examination prompt: the
model knew, the player did not.

This repo already refuses to let the screen know more than the player — the suspects'
pigments are matched in value and chroma so the board never suspects anyone first. The
deadline was the one place breaking that rule.

Discovery time is public and always drawn solid. The estimate is drawn by how it was
come by:

mark
確定 — examination or physical evidence solid, the time as it is
範囲 — "somewhere between" a span with returns at both ends
不明 — nothing yet dotted across the known width, ? in place of a time
第三者の推定 — someone says so dotted, ? beside the time, and whose word it is, in their ink

Splitting the first from the last is the point. The same 18:50 means one thing when the
detective established it and another when a bystander asserts it — and if that bystander
is the culprit, the two stop agreeing the moment the examination lands. That is the
existing clash line's trick, applied to the deadline.

Nothing is filled. The window is a line with returns at each end; a shaded band would
compete with the suspects' own bars.

mocks/desktop/deadline-states.html puts the four side by side, because switching
#death= shows each but never lets you compare them — and comparing is the point. The
marks come from Mock.deathMarks, the same call the alibi table makes, so the sheet
cannot drift from what the screens draw.

2. The desk can reach a place

The phone lists places in its swap nav. The desk had no way in at all: switching there is
done by the alibi table's column headings, and places hold no column. The mock said so,
with a 「まだ」 in it — a note left for later rather than a decision.

The consequence was that the same case played differently by device. On a phone you step
from the counter to the back room where you stand; on a desk you go back to the prep
screen first.

The desk now has its own way in, beside the nameplate rather than in the table. Grey, no
pigment — places do not answer, and the colours belong to those who do. The place you are
already looking at is left out, since an entry that does nothing when pressed is worse
than no entry.

Not here

  • The phone chart still draws the old single deadline line.
  • App-side work: AlibiChart takes one { at, label }; the disclosure flag on evidence
    in scenario-definition.ts; the screens still feed estimatedDeathAt from turn one;
    and places never reaches the real screens at all (ScenarioDetail has no such field,
    so only Storybook passes them). Sketched at the end of docs/design/deadline-window.md.

Test plan

  • bun run lint — no errors
  • all four deadline states rendered and read at 1440×900 (screenshots/death/)
  • desk place switch checked from both a person (帳場 / 奥の間 offered) and a place
    (only 奥の間 offered)
  • reviewer: 18:50 and 19:10 are twenty minutes apart here and the labels clear each
    other; Tsukimisou's 20:15/20:30 is fifteen, which is the tighter case to check once
    this reaches the app

tkgstrator and others added 3 commits September 2, 2026 14:02
The board asserted a death estimate the player could not yet know. In the
Tsukimisou case the record says the body was found around 20:30, but the chart
drew 20:15 "death estimate" from the first turn, before anyone had examined
anything. The data already separated foundAt from estimatedDeathAt; only the
drawing collapsed them.

So the deadline becomes a window rather than a line. The discovery time is
public and always drawn solid. The estimate is drawn by how it was come by:

1. fixed    solid, the time as it is
2. range    a span mark with end caps, both ends solid
3. unknown  dotted across the whole known window, with ? instead of a time
4. claimed  dotted, ? beside the time, and whose word it rests on, in their ink

Splitting 1 from 4 is the point. The same 18:50 means something different when
the detective examined the body than when a bystander says so, and if that
bystander is the culprit, the two will not agree once the examination lands.

Nothing is filled — the window is a line with returns at each end. A shaded
band would compete with the suspects' own bars.

Desktop only for now; the phone chart still draws the old single line.
Reasoning is written up in docs/design/deadline-window.md.

Co-Authored-By: Claude <noreply@anthropic.com>
Switching #death= one at a time shows each state but never lets you compare
them, and comparing is the whole point: the difference between a time the
detective established and the same time a bystander asserted is only legible
next to each other.

The marks come from Mock.deathMarks, the same call the alibi table makes, so
the sheet cannot drift from what the screens actually draw. The stage keeps the
table's scale for the same reason — a comparison at a different scale is a
comparison of something else.

Co-Authored-By: Claude <noreply@anthropic.com>
The phone lists places in its swap nav; the desk had no way in at all, because
switching there is done by the alibi table's column headings and places hold no
column. The mock said as much, with a "still" in it — a note left for later
rather than a decision.

The consequence was that the same case played differently by device: on a phone
you step from the counter to the back room where you stand, on a desk you go
back to the prep screen first.

So the desk gets its own way in, beside the nameplate rather than in the table.
Grey, no pigment: places do not answer, and the colours belong to those who do.
The one you are already looking at is left out — an entry that does nothing when
pressed is worse than no entry.

Co-Authored-By: Claude <noreply@anthropic.com>
@tkgstrator tkgstrator changed the title feat(mocks): draw the deadline as a window, in its four states feat(mocks): the deadline as a window, and a way into places from the desk Sep 2, 2026
tkgstrator and others added 6 commits September 2, 2026 14:42
Asking and examining are two different moves, each costing a turn. Listing them
together let you slip from a conversation into a search from the corner of the
screen, which blurs where one act ends and the next begins.

So the switcher now offers only what matches what you are already doing: people
while questioning, the body and the places while examining. Crossing between the
two goes back through the prep roster, which is where you chose in the first
place.

On the desk this means the place list appears only while examining; people were
never in that corner anyway, since the table's column headings have always been
the way to them, and they stay reachable throughout.

Co-Authored-By: Claude <noreply@anthropic.com>
- Introduce places as a first-class target for `ask`, alongside characters and the victim: schema, migration, compile-scenario split into public/truth findings, and location-typed evidence sources now resolve against places too.
- Add a deadline window derived from victim discovery/estimated-death times, revealed only after the body has been examined, and render it across AlibiChart, CaseOverviewScreen, InterrogationScreen, and ResultScreen.
- Update scenario YAMLs, fixtures, stories, and docs to cover the new places and deadline data.

Co-Authored-By: Claude <noreply@anthropic.com>
The schema, the server and the screens could all handle places, but nothing
joined them: only Storybook ever passed any, so in the running app the section
never appeared no matter how far the case progressed. The two routes now pass
what the API already returns.

The nameplate takes `situation` rather than `introduction`. The latter is the
roster blurb — "the ground floor, the till and the ledger" — which describes the
place rather than what is in front of you. What belongs under the name while you
are standing there is the other line: the clearing-up stopped halfway.

The authoring guide gains a places section: the shape, why findings are
mandatory (a place on the roster is always worth examining), the ID rules and
why they exist, matching room IDs when there is a floor plan, and the line
between `situation` and `findings` — the first is public and keyword-checked,
the second is earned. Also a reminder that a place with nothing sourced from it
is a turn spent on nothing.

Co-Authored-By: Claude <noreply@anthropic.com>
…tcher

In easy mode every character carries a remaining count in the alibi table's
column heading, and every room on the floor plan carries one too. Places fall
between: they hold no column, and a place that is not also a drawn room appears
on no plan either. The count the server computes for them reached nothing.

So it goes beside the name in the switcher, which is the only surface a place
has. People and the body deliberately do not get one there — their number
already stands in the column heading, and the same figure in two places reads
as one of them being stale.

Co-Authored-By: Claude <noreply@anthropic.com>
The desk drew the window; the phone was still drawing one line. Same vocabulary
now, turned ninety degrees onto the rail.

Two things had to change rather than shrink. Labels cannot sit beside their mark
at 390px — discovery stands at 92% of the axis, so its label would fall off the
edge; they go on a row beneath instead, a point-mark's label right-aligned to it
and a window's centred on its span. And the accusation's shu tick, which defaults
to 18:50, was covering the deadline mark outright; it now stops at the row above,
so solid and dotted are told apart below it.

The enlarged rail also loses the 18:50 tick it used to print in the middle. That
was the board naming the estimate before anyone had earned it — the same fault
this whole change exists to remove.

Co-Authored-By: Claude <noreply@anthropic.com>
The estimate used to appear once the body had been examined. That was a
placeholder standing in for the real rule, and it closed the other door: a case
with a doctor in it should let you reach the same time by asking them.

Evidence now carries `revealsDeathTime`. Hold one such piece and the board's
dotted window resolves to a solid line; hold none and it stays unknown to the
end. The mark sits on evidence alone rather than also on findings, because the
server can tell whether a piece of evidence has been discovered — a finding only
records whether it may be shown, so a mark there could never be read back.

The server decides. Sending the client a table of which evidence opens the
estimate would hand the board a key to its own answer, so it computes the state
and ships the resolved time or null.

While here: `read/scenarios.ts` was putting `estimatedDeathAt` into the case
detail. The board drew "unknown" while the browser already held 20:15 — the
whole point of hiding it, undone one layer down. Removed.

Tsukimisou gets two ways in, the examination and the doctor's account, so that
choosing one route does not lock the deadline away for the rest of the case.

Co-Authored-By: Claude <noreply@anthropic.com>
@tkgstrator
tkgstrator merged commit f8e952f into develop Sep 2, 2026
9 of 10 checks passed
tkgstrator added a commit that referenced this pull request Sep 2, 2026
…ship the missing migration (#16)

The 0020 migration was left untracked when #15 was staged, so develop described
a column nothing created. And deadlineOf folded "no estimate in the scenario"
into "not discovered yet", drawing a dotted window with a question mark for 33
cases where no time was ever written — an invitation to search for nothing.
tkgstrator added a commit that referenced this pull request Sep 2, 2026
…e death estimate (#17)

Scenario data for the machinery #15 and #16 shipped. Places go from 2 cases to
17, and every case that names a death estimate now has evidence marked to
disclose it — the nine that had a time written and no route to it are gone.

Two migrations carry it to databases already seeded. The second rewrites only
the public half of each place entry, leaving the private findings alone: what
the roster and the nameplate show is public, what examining turns up is earned.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant