diff --git a/.gitignore b/.gitignore index 94f9c26..1e56ace 100644 --- a/.gitignore +++ b/.gitignore @@ -11,6 +11,11 @@ env/ # Database *.db +# WAL leaves two sidecar files beside the database. They are as much a local +# artefact as the .db itself, and a committed -wal is a committed transaction +# log from somebody else's machine. +*.db-wal +*.db-shm *.sqlite *.sqlite3 @@ -48,3 +53,6 @@ site/.astro/ # Committing them would give every page two copies, and someone would edit # the wrong one. site/src/pages/*.md + +# Overleaf upload bundle is built from paper/ -- see paper/README.md +diresq-overleaf.zip diff --git a/CHANGELOG.md b/CHANGELOG.md index 4d8d156..d390ee1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,12 @@ Disaster response tracker. Logs the volunteers going in, not just where the disa ### Added +- The clock can be scaled, so the thing this project is about can be watched instead of described. DiresQ's mechanism is the absence of an event over time — a deadline passes, nobody hears from a responder, and fifteen minutes later the server files a report about them — which is correct and completely unwatchable. `DIRESQ_DEMO_SPEED` multiplies the rate incident time passes: at 60, a responder goes overdue five seconds after the page loads and the report about them arrives fifteen seconds after that. Nothing about the mechanism is faked for the camera. There is one `now()` and every deadline, comparison and query downstream is the production code, unchanged; only the rate time enters the system is scaled. Login lockout and the ICS-214 export filename deliberately stay on the real clock, the first because scaling a security control on a public instance is not a demo feature and the second because it names a file on somebody's disk. A scaled clock forces the demo banner on and makes it state the multiplier, for the same reason the board shows when the sweep last ran: a page showing accelerated time has to say so, or the honest version of this is indistinguishable from a faked one. +- The accountability board shows time remaining, not only time elapsed. Every row already said how long since we last heard from somebody, which states the past and leaves the future to be worked out. It now also says *due in 5 min*, counting down, and *20 min past due* once it isn't. The number is in the `/api/responders` payload as `due_in_seconds`, negative once the deadline has gone. +- A seeded responder whose deadline expires while you are looking at it. Everybody else on the demo board is in a state that has already settled — Sam is red, the Mayde Creek four are overstaffed, the rest have time in hand. `n.farrow` is the only one whose state changes on screen, because a transition needs a before, and the first attempt gave them the *longest* deadline on the board, so every other responder went red first and there was nothing to point a camera at. A test now asserts they lead the queue by at least three minutes, so a later change to the seed cannot quietly take the shot away again. +- `docs/filming.md`: the arithmetic that turns a speed into a shot (red at 300/S seconds, the auto-filed report at 1200/S), why speeds above about 120 look broken rather than fast — the board refreshes every three seconds, so the countdown starts jumping by more than it counts down — and a shot list that opens cold on a red board rather than on anybody introducing themselves. + +- Two buttons on the map for when you have lost the incidents. *Fit all* frames every report currently shown — including after the coverage filter has hidden some, so it frames what is left rather than what it just hid. *Next report* walks through them one at a time and opens each. Both say where they went to a screen reader, because moving a map is silent. - A `CONTRIBUTING.md` and a `CODE_OF_CONDUCT.md`. The contributing guide is specific rather than generic: a fix arrives with a test that fails without it, numbers in prose have to be true because a test reads them, a weakened guarantee gets a paragraph in `limits.md`, and nothing that stops being true when it is written may be cached. The code of conduct is the Contributor Covenant with two additions — one rule about not putting real emergency information into a demo that cannot summon help, and an honest note that two students are not a moderation team, with a pointer to GitHub's own report-abuse flow for anything urgent. - The board now shows when the silence check last ran — "checked 2s ago" beside the live indicator, turning amber if it has not run for five minutes. The check that files a report about somebody who has gone quiet has no scheduler: it runs whenever anybody reads the board, so it cannot be a timer that dies without anyone noticing. But that was a claim in a comment, and this project does not ask anyone to take a claim about an alarm on trust. On a board somebody is watching the number always reads a few seconds, because the watching is what runs it — which is the point. You can watch it move instead of believing it. - `app.py` opens with an index of what is in it: fifteen sections in running order, each one a banner comment you can search for. It is one file on purpose, and the cost of that is knowing where anything is. There are no line numbers, because they would be wrong by the next commit, and a test checks the index and the file still agree — including the order. @@ -14,10 +20,28 @@ Disaster response tracker. Logs the volunteers going in, not just where the disa ### Changed +- `docs/accessibility.md`, `docs/limits.md` and `docs/decisions.md` caught up with the demo clock. The accessibility page records the fourth pass and the three things it found, and its enforcement table now lists what the new tests actually check rather than what the old ones did — including the detail that the full-stylesheet contrast audit got its light/dark classification wrong on the first attempt and was caught by its own canary. `limits.md` records that screen reader users do not get the countdown at all, why the alternative was worse, and that the honest fix is not written. `decisions.md` records why time is injectable rather than the constants being shortened in demo mode, and what stays on the real clock. + + - The tests that read the project's own files stopped walking into `node_modules` before discarding it. They were the slowest thing in the suite and are now roughly thirty times faster. ### Fixed +- Six stylesheets were setting real text in `#6c7086` or `#45475a`, which are 1.4:1 to 1.9:1 against the surfaces they sit on where WCAG asks for 4.5:1 — the disclaimer's footer, the legal links under the login, signup and homepage forms, the offline page's "as of" stamp and footer, the triage footnote, and the stood-down vote and capability tags on a report. The test that was supposed to prevent this checked ten hand-listed colour pairs, so a colour used in a file nobody had thought to add to the list was never looked at. It now reads every `color:` declaration in every stylesheet, resolves `var()` against each file's own palette, and checks it against the backgrounds it can actually sit on. + + +- The countdown on the accountability board survived exactly one render. It was added to the server-rendered template and not to the JavaScript that replaces the list every three seconds, so it appeared on load and was wiped by the first poll — invisible in the test suite, which reads the template, and invisible by hand unless you happened to watch the same row for three seconds. A test now asserts both renderers draw it. The board's coordinates and its "not assigned" / "no position" / "no contact yet" states were using `--overlay` on the row background, which is 1.92:1 against WCAG's 4.5:1. That grey has been banned from `a11y.css` by a test since it was caught on capability tags; `board.css` was never covered by it and now is. + + +- The hosted demo stopped booting. The boot script asked for two gunicorn workers on a 512 MB instance, and the classifier trains when the app is imported, so each worker carried its own copy. Render prints the worker count it sized the box for — one — in its own deploy log, and passing `--workers 2` silently overrode it. The container was killed four seconds after starting, and the platform then spent seventeen minutes health-checking a process that was already dead, which is why the failure reported itself as a health check that never passed rather than as a boot that never survived. The count now comes from the host. +- Responders were drawn on the map in a way the legend no longer described. The legend key had been changed to a hollow ring — colour was already saying whether anyone is coming to a place, so it had nothing left to say about a person — but the map was still drawing them as solid circles in those same three colours. So the symbol people were told to look for did not exist, and the ones that did exist looked like reports. Fixing a label without fixing the thing it labels leaves a page telling two lies instead of one. +- The board, the map and the feed could return an error page under load. All three run the silence check before answering, the check writes to the database, and SQLite lets one writer lock out every reader — so with a few people watching a board that refreshes every three seconds, a write could wait past its timeout and fail the whole response. The pages that exist to be watched during an emergency were the ones that broke when watched. Three changes: the database now uses a journal mode where readers and the writer stop blocking each other, the check runs at most once every thirty seconds instead of once per visitor per refresh, and a failed check is caught rather than allowed to become an error page. It deliberately does not record itself as having run when it fails, because a board showing green while nothing is checking is the worst outcome available. +- A report could say somebody was on scene while the board had them forty-five minutes overdue, and the report page gave no sign of it. Status is what a responder last told us; whether they are still answering is a different fact, and only one of the two pages knew it. Anybody opening a report to decide whether the address needed more help was counting a person who had gone silent as help. The page now says how many have stopped answering, marks each of them, and says plainly not to count them. Somebody who has cleared is not chased, because going home is not going quiet. +- On a phone, the only way to file a report was to open a menu labelled "Filter". The button lived in the sidebar, which slides off-screen below 768 pixels, so the one thing this app exists to do was behind the one control nobody would press to do it. There is now a Create Report button in the page itself on small screens, and exactly one of the two is ever present so a screen reader never hears it twice. +- Seeded responders were on the map and could not be seen. They were placed within ninety metres of the report they had joined — close enough that the circle marking a person sat underneath the teardrop marking the place, and Leaflet draws places above people. Nothing was missing from the data, which is exactly why nothing looked wrong with it. They now stand off by about two hundred metres, so the thing this project is an argument about — several people converging on one address — is visible rather than inferred. +- The demo moved every time the server restarted. Responder positions were derived from Python's built-in string hashing, which is deliberately salted differently for each process, so a seed built on the promise that every visitor arrives at the same incident produced a different incident on every boot. It now uses a checksum that gives the same answer on every machine and every run. +- The map legend used the same red for *nobody going* and for *responder*, so two of its four keys said different things in the same colour. Colour was already carrying meaning — red, blue and green say whether anyone is coming — which left nothing for it to say about a person. The legend now uses shape the way the map already does: reports are teardrops, responders are a hollow ring. Colour means one thing on each. +- The map stopped telling the difference between having no signal and the server returning an error, so a failure looked like being offline. It now checks the response before believing it, and the warning appears above the map rather than underneath the statistics, where a phone screen never reached it. - The stamp that records when the silence check ran could take down the page it is displayed on. It runs before every read of the board, which polls every three seconds, so something that had been read-only started writing on every request — and a write that fails inside a before-request hook returns an error page instead of a board. It now fails quietly: the timestamp goes stale and the board reports that in amber, which is true, because a check we could not record is not a check we can claim. ## [1.0.2] - 2026-08-03 diff --git a/PAPER.md b/PAPER.md new file mode 100644 index 0000000..6d9ca67 --- /dev/null +++ b/PAPER.md @@ -0,0 +1,697 @@ +# "Can We Account for Everyone?" Silence-Triggered Escalation for Volunteers Who Self-Deploy + +**London Chowdhury** and **Jesslyn Caroline** + +> **DRAFT — NOT FOR SUBMISSION.** Assembled automatically from the section +> drafts in `research/`, which remain authoritative. Four items must be resolved +> first; see *Outstanding before submission* at the end. + +**Keywords:** crisis informatics; spontaneous volunteers; convergence; +unaffiliated volunteers; accountability; self-deployment; offline-first design + +## Abstract + +Convergence, the spontaneous movement of people toward a disaster, has been +documented since Fritz and Mathewson (1957). Practice manages converging +volunteers through credentialing: reception centres, badge systems, and +pre-disaster affiliation. Each presupposes an institution that has either +already arrived or reached the volunteer months beforehand. In the interval +before either holds, people are already going in, and no accountability +mechanism covers them. Interviewing Hurricane Harvey rescuers, Smith et al. +(2018) record a dispatcher asking whether "we [can] account for everyone." + +We report the design of DiresQ, an open-source system attempting +accountability for unaffiliated volunteers with no coordinator. It escalates +on silence rather than supervision: a responder states an expected arrival +time and checks in periodically, and if they stop, the system files a report +about them without anyone deciding to. + +DiresQ has no users, no field deployment, and no evaluation. We contribute a +design rationale, five design trade-offs stated with their costs, and five failure modes encountered during construction. + +## 1. Introduction + +When a disaster is large enough, people go toward it. This is among the oldest +findings in disaster sociology. Fritz and Mathewson named it in 1957 — +*"the informal, spontaneous movement of people, messages, and supplies toward +the disaster area"* — and catalogued five kinds of person who arrive: the +returnees, the anxious, the helpers, the curious, and the exploiters. Their +report is subtitled *A Problem in Social Control*, and the observation it opens +with has not dated: convergence *"brings needed aid to many victims, but at the +same time the resultant congestion makes organization and control of the rescue +and relief efforts more difficult."* Kendra and +Wachtendorf (2002), studying the response to the World Trade Center attack, +added a sixth and reframed the central question. Access to what they call the *response +milieu* is not granted; it is negotiated. A volunteer's admission depends on +whether the people already inside can afford them. + +The mechanism the field has developed for that negotiation is **credentialing**. +Volunteer reception centres, badge systems, affiliation with a recognised +organisation: these convert an unknown arrival into an accountable one. They +work. At the World Trade Center, identification requirements *"evolved and +intensified on almost a twice-daily basis"* as the response matured. + +Practitioner doctrine is more explicit still, and defines our population for us. +FEMA's guidance on managing spontaneous volunteers describes unaffiliated +volunteers as those who are *"no part of a recognized voluntary agency"*, who +*"often have no formal training in emergency response"*, and who — the phrase is +theirs — are *"not officially invited to become involved."* It adopts the +academic taxonomy directly, noting that *"researchers have identified six +different groups of people that tend to converge"*, and identifies the +operational task: *"the helpers must be identified from among the larger +population of convergent individuals."* + +The doctrine offers two mechanisms for doing that identification, and both +presuppose an institution. The first is the Volunteer Reception Centre, which +processes arrivals — and must therefore have been established. The second, and +the one the guidance treats as primary, is prevention: + +> "Turn spontaneous unaffiliated volunteers into affiliated ones **before a +> disaster occurs.** People who make a pre-disaster decision to become disaster +> volunteers and take training to prepare themselves will NOT become +> spontaneous, unaffiliated volunteers after a disaster." + +The same materials pose, as a training exercise, the question of how a community +can *"keep your community members from self-deploying"*, and describe organised +national service volunteers approvingly as members who *"never self-deploy, but +wait to be called."* + +We take this seriously rather than dismissively: pre-affiliation plainly works, +and a trained volunteer who arrives when called is better for everyone than one +who does not. But both mechanisms require an institution — one that reached the +volunteer months beforehand, or one that has arrived and opened a reception +centre. Neither covers the person who decides at two in the morning, on the +night, that they have a boat. Doctrine's answer to that person is that they +should not exist. They do exist, in thousands, and the events that produce them +are the events where the institution is least able to arrive. + +Kendra and Wachtendorf state the resulting tension directly, summarising Weick +and Perrow on decentralised coordination: effective decentralisation presupposes +prior socialisation into an organisation's norms, *"yet the volunteers who +appear to assist in the emergency response are, virtually by definition, +strangers to the response milieu."* The literature names the problem and, so far +as we have found, proposes no mechanism for the interval before command exists. + +Hurricane Harvey makes the interval concrete. In August 2017 flooding in the +Greater Houston area affected an estimated 30,000–40,000 homes, and city +officials and FEMA publicly asked citizens with boats to help reach people +trapped inside them (Smith et al., 2018). Thousands came. They organised through +Zello, a push-to-talk application, along with Facebook groups, NextDoor, ad hoc +Google spreadsheets, and applications written during the event itself. +Interviewing twenty of these volunteers, Smith et al. found at least twenty +distinct groups with, between them, *"no way to seamlessly share information and +coordinate activity."* Affiliation was nominal: membership of the loose "Cajun +Navy" was *"fleeting"*, leadership *"fluid and dispersed"*, boundaries unclear. + +What went wrong is documented in the volunteers' own words. One dispatcher +described the coordination problem exactly: + +> "it became overwhelming just trying to keep track of who was going out who was +> coming back who was out on a boat, **can we account for everyone**, and who's +> in their house and it was a mess." — Gary, in Smith et al. (2018) + +The gap this paper addresses is not one we inferred. It was stated by a person +who was in it. + +Smith et al. name three coordination failures — incomplete feedback loops, +unclear prioritisation, and communication overload — and close by calling for +*"the design of intuitive systems that can quickly be mastered by the novice +social media user."* This paper is an attempt at one narrow part of that. + +Two details from that study bear directly on the design that follows. First, the +accountability function was being performed — badly — by *families*: rescuers +reported phones "constantly blowing up" with relatives asking *"are you okay, +are you okay, are you okay."* Somebody was always going to ask the question; the +question simply had nowhere to be answered. Second, volunteers' phones were +destroyed by rain and floodwater in numbers large enough that many replaced them +afterwards — which is direct evidence that silence and danger are genuinely +different things, and that any system escalating on silence will produce false +alarms. + +This paper reports the design of **DiresQ**, a system that attempts +accountability for such volunteers without a coordinator. Its central move is to +escalate on **silence** rather than on supervision: a responder states an +expected arrival time and checks in periodically, and if they stop, the system +files a report about them automatically. Nobody has to notice. + +We are explicit about what this paper is not. DiresQ has never been used in a +real disaster. It has no users, no deployment beyond a public demonstration +instance, and no evaluation. We report a design, the reasoning behind five +specific trade-offs, and the failure modes we encountered building it — several +of which we consider more transferable than the system itself. Readers looking +for evidence that this approach works will not find it here, and we would +regard any such reading as a misuse of the paper. + +## 2. Background and related work + +### 2.1 Convergence + +People moving toward a disaster is one of the field's oldest documented +behaviours. Fritz and Mathewson (1957) named it *convergence behavior* — +*"the informal, spontaneous movement of people, messages, and supplies toward +the disaster area"* — and observed that it *"brings needed aid to many victims, +but at the same time the resultant congestion makes organization and control of +the rescue and relief efforts more difficult."* They separate movement *"toward +the struck area from the outside — external convergence"* from *"movement toward +specific points within a given disaster-related area or zone — internal +convergence"*, distinguish three forms (personal, informational, materiel), and +catalogue five types of personal converger: the returnees, the anxious, the +helpers, the curious, and the exploiters. + +It is worth noting that the founding treatment frames convergence as a control +problem — its subtitle is *A Problem in Social Control* — and that this framing +has been remarkably durable. The paper's own position is stated in §5. + +Kendra and Wachtendorf (2002), studying the response to the World Trade Center +attack across more than 750 collective hours of field observation, added a sixth +— supporters or fans — and, more importantly for us, reframed the question. +Access to what they term the *response milieu* is not a status a volunteer +holds but one they negotiate. + +The taxonomy has passed into practice. FEMA's guidance on managing spontaneous +volunteers reproduces it directly, noting that *"researchers have identified six +different groups of people that tend to converge"*, and derives an operational +task from it: *"the helpers must be identified from among the larger population +of convergent individuals."* Theory and doctrine here are a single +lineage rather than two literatures, which is why we cite them together. + +DiresQ's users are helpers, converging externally and then internally. + +### 2.2 Legitimacy, credentialing, and what both presuppose + +Kendra and Wachtendorf's central finding concerns who gets in. (We cite their +Disaster Research Center preliminary paper throughout, because it is the text +we read; the 2003 book chapter develops the same fieldwork and is listed in the +references for completeness.) At the World +Trade Center, identification requirements *"evolved and intensified on almost a +twice-daily basis"*, and volunteers became *"another group that needed to be +accounted for, and therefore potentially a distraction that outweighed their +utility."* The volunteers who succeeded in gaining access were those who +*"were able to work with minimal supervision by official emergency workers"* — +whose incorporation *"required little or no effort on the part of emergency +managers."* + +We take the scarce resource in that account to be emergency-manager attention, +and it is the frame we design against: a volunteer who accounts for themselves +spends none of it. + +Doctrine's mechanisms for conferring legitimacy are the Volunteer Reception +Centre and, prior to any event, pre-affiliation — *"turn spontaneous unaffiliated +volunteers into affiliated ones before a disaster occurs."* Both +presuppose an institution: one that has arrived and opened a centre, or one that +reached the volunteer months earlier. We develop the consequence in §1 and do +not repeat it here. + +### 2.3 Digital volunteers, and why they need no accounting for + +Starbird and Palen (2011) provide the foundational study of volunteers +self-organising through technology after a disaster, examining 292,928 tweets +and interviewing nineteen of the "voluntweeters" who emerged after the 2010 +Haiti earthquake. They read the phenomenon through Kreps and Bosworth's +structural theory, finding a resource → activity → task → domain progression in +which the *resource* — Twitter, and the individual capacities it made usable — +is what lets a stranger begin. + +The distinction that matters for this paper is one their scope makes for us: +their volunteers are remote by definition. The population is people helping from +other continents. No participant is in the hazard, so no participant needs +accounting for, and no mechanism for doing so appears in the paper. This is not +a gap in their work. It is the boundary of ours. + +Our question is what changes when that same self-organising sequence runs among +people who are physically inside the hazard. Accountability stops being optional +and there is still nobody to provide it. + +### 2.4 Citizen-led response in practice + +Smith et al. (2018) interviewed twenty participants in the citizen-led rescues +during Hurricane Harvey and found three roles — rescuer, dispatcher, information +compiler — distributed across at least twenty distinct groups with *"no way to +seamlessly share information and coordinate activity."* They report three +coordination failures: incomplete feedback loops, unclear prioritisation, and +communication overload. + +Incomplete feedback loops is our problem under another name. Their account of it +is mechanical rather than motivational: rescue platforms depended on someone +manually marking a case closed, and in practice the case number was forgotten, +the phone was destroyed, or a different boat reached the address first. The loop +stayed open not because anyone neglected it but because closing it required an +action at exactly the moment nobody had attention to spare. + +We note two of their findings as constraints on our design rather than support +for it. First, their participants wanted *more* coordination: one dispatcher +argued that *"people that are trained to do that need to be in charge of +prioritizing calls and assigning."* Second, over-convergence was itself a +failure mode — boats were turned away from neighbourhoods that already had too +many. We return to both in §5. + +### 2.5 Systems for crisis crowdsourcing + +Liu (2014) offers the field's most developed design framework, organising a +crowdsourcing system around why / who / what / when / where / how, and around +the social, technological, organisational and policy interfaces that manage the +articulation work of coordinating across them. We note that two of +those four interfaces presuppose an organisation conducting the effort, and that +the trajectory the framework describes runs toward formalisation and integration +*"into official products and services."* Our position is upstream of that +trajectory rather than opposed to it. + +Auferbauer and Tellioğlu (2017) describe *crowdtasking*, presented explicitly as +*"a centralized form of crowdsourcing for crisis and disaster management"*, with +a prototype and a first field trial. It is the clearest statement +of the opposite design position to ours, and we cite it as such: where +crowdtasking assumes an organisation able to task a registered crowd, we assume +neither the organisation nor the registration. + +Kankanamge et al. (2019) provide a systematic review of volunteer crowdsourcing +in disaster risk reduction. We have not obtained the full text and +therefore make no claim about its findings; it is listed here because a reader +working in this area will expect to see it and should know we are aware of it. + +Technical work on the classification side is considerably more advanced than +ours. Zhou et al. (2022) fine-tune BERT variants over a hand-labelled corpus of +Hurricane Harvey tweets to identify rescue requests, and substantially outperform +the earlier baselines they compare against. Our own priority suggestion (§3.3) is a naive +Bayes classifier over a small hand-labelled corpus, and is not competitive with +this work, nor intended to be: it exists to run in a browser with no network, +which is a different constraint rather than a weaker attempt at the same one. + +### 2.6 Where this leaves the gap + +Convergence is thoroughly theorised. Legitimacy is theorised and operationalised. +Digital volunteering is well studied among remote participants. Crowdsourcing +systems have a design framework and at least one field-trialled centralised +implementation. Classification of rescue requests is a mature technical problem. + +What we have not found, in the literature or the doctrine, is a mechanism for +accounting for physically converging helpers during the interval before an +institution exists to do it. Doctrine's answer is that those people should have +been affiliated beforehand. The academic literature describes their arrival as a +management problem. Neither addresses the person already in the water. + +That interval is this paper's subject, and the design in §3 is one attempt at it. + +## 3. Design + +DiresQ is a server-rendered web application: Flask, SQLite, no client framework, +no account approval step, and no dispatcher role. Thirty-three routes over six +tables. The stack is deliberately unremarkable, and we describe it only to +establish that nothing in what follows depends on infrastructure a volunteer +organisation would not already have. The contribution is not the stack. + +Anyone can sign up. There is no verification of identity, no vetting, and no +administrator who admits people. This is not an oversight we intend to fix; it +is the condition the system is designed for. A tool that requires somebody to +approve you has reintroduced the coordinator whose absence is the entire +problem. + +### 3.1 The mechanism + +A report is a place that needs help. A responder who decides to go there joins +the report and, in doing so, states an expected time of arrival. The ETA is +bounded between five and 240 minutes and warns above 120 — not because longer +journeys are invalid, but because an unbounded ETA makes the subsequent +arithmetic meaningless. From that point the responder is expected to check in; +the interval defaults to thirty minutes. + +If a responder stops checking in, they are marked overdue. Fifteen minutes past +that threshold, the system files a report *about them* — their last known +location becomes an incident in the same feed everyone else is reading. No human +decides this. No human is asked to notice. + +This is the whole mechanism, and its only novel property is what triggers it. +Existing accountability systems escalate when a coordinator observes that +somebody has not reported in. We escalate on the observation itself being +absent. Silence is available in circumstances where a supervisor is not. + +### 3.2 Five decisions, and what each one cost + +The design is small enough that the interesting content is not the architecture +but the trade-offs. We describe five, each of which we got wrong first. + +**Silence as the trigger.** The alternative designs all require somebody to be +watching: a dispatcher view, an alert queue, a supervisor role. Each of them +works, and each of them assumes the thing we cannot assume. Escalating on +absence needs nobody. The cost is that absence is ambiguous — a responder who +has stopped answering may be in trouble, or may have a dead phone, or may have +gone home without saying so. The system cannot tell these apart and does not +claim to. It reports *contact lost*, never *safe* or *unsafe*, and the interface +language was rewritten twice to stop implying otherwise. + +**No in-process timer.** Our first design ran the silence check on a background +thread inside the application. We removed it. A thread that dies takes the alarm +with it and leaves the interface showing green, and a green screen is read as a +positive result rather than an absent one. The check now runs on read: whenever +anyone loads the accountability board, the sweep runs first, rate-limited to +once every thirty seconds. An *external* scheduler is supported and optional +(`flask --app app sweep` from cron or Task Scheduler) — deliberately external, +because an external scheduler that fails is at least visible to the machine +running it, which an in-process timer is not. + +This trades one dependency for another. A timer that might die becomes a check +that depends on being watched. We consider that the better failure — an +unwatched board is a situation where nobody is relying on the result — but the +substantive move is that we made the dependency **visible** rather than +documenting it. The board displays how long since the last sweep and turns amber +past five minutes. On a board somebody is actually watching, the number always +reads a few seconds, because the watching is what runs it. A limitation you can +see on screen is a different claim from one the user has to be told about. + +**Status and contact are different facts.** What a responder last told us is one +thing; whether they are still answering is another. We conflated them, and the +result was a report page displaying "on scene" for somebody the accountability +board had forty-five minutes overdue. Anyone opening that report to decide +whether the address needed more help was counting a person who had gone silent +as help present. Both facts are now shown, and neither is inferred from the +other. Somebody who has explicitly cleared is not chased, because going home is +not going quiet. + +The general form of this: in a system whose purpose is knowing where people are, +*self-reported state* and *liveness* must never be collapsed into one field, +however tempting the simplification is at the schema level. + +**Refusing to cache claims about other people.** The offline layer keeps the +things you committed to — your own assignments, a queued report you filed +without signal — and refuses to keep the report feed or the accountability +board. A cached feed is a list of who needed help twenty minutes ago. Acting on +it sends somebody to an address that has been cleared, and the person reading it +has no way to know the difference between stale and current. A test fails if +either page is added to the service worker's shell list. + +The generalisable claim, and the one we would defend: **correct-when-written and +correct-when-read are different guarantees**, and disaster data has an unusually +short half-life between them. Offline-first design literature tends to treat +availability as an unalloyed good. For a class of data it is not, and the +distinction is not about staleness tolerance but about whether a stale answer is +*actionable* — whether a user can be sent somewhere by it. + +**Not storing triage answers.** The system includes a START triage helper that +orders which reports get attention first. The answers are health observations +about a person who did not consent and is likely in no position to. They are +used to compute an ordering and then discarded; nothing about a casualty's +breathing or perfusion is written to the database. The cost is that the ordering +cannot be audited after the fact, which is a real loss. We accepted it. + +### 3.3 Priority suggestion + +A report can be given a suggested priority by a multinomial naive Bayes +classifier over a severity lexicon, trained on a small hand-labelled corpus and +validated by leave-one-out cross-validation with a floor asserted in continuous +integration. + +We describe it in one paragraph deliberately. It is the least interesting +component and the one most likely to be mistaken for the contribution. It +suggests an ordering for human attention; it does not predict outcomes, assess +medical severity, or make any claim that survives the person reading the report +disagreeing with it. A model small enough to ship as a frozen table of word +counts is also small enough to run in the browser, which is why priority +suggestion works with no signal while the report feed deliberately does not. + +### 3.4 What the design does not attempt + +It does not summon help. No dispatcher reads it, it does not call emergency +services, and the disclaimer on every page is load-bearing rather than legal +decoration. It does not verify that anybody is who they say they are. It does +not know where anyone actually is — location is self-reported throughout. It +makes no claim that a responder is safe; only that we have or have not heard +from them. + +These are stated here rather than only in §5 because a reader who reaches the +limitations section still holding the wrong model of the system has already +misread the design. + +## 4. What building it taught us + +We report these as observations from construction, not as validated findings. +Each began as a specific bug or reversal and generalised afterwards. + +### 4.1 Correct-when-written and correct-when-read are different guarantees + +The offline layer was originally designed to cache what a user would want if +their signal dropped, which is nearly everything. We now cache almost nothing. + +The rule we arrived at: **do not store anything that stops being true when it is +written.** Your own commitments — the assignment you accepted, a report you +filed with no signal — remain true offline, because they are statements about +you. The report feed and the accountability board are statements about other +people, and both decay. A cached feed is a list of who needed help twenty +minutes ago; a responder acting on it is dispatched to an address that has since +been cleared, with no way to distinguish that from a current one. + +Offline-first design generally treats availability as an unalloyed good, with +staleness managed by tolerance windows and revalidation. We think the useful +distinction is not how stale the data is but whether a stale answer is +*actionable* — whether a user can be sent somewhere by it. Data that can move a +body should not be served from cache at all. A test fails if either page is +added to the service worker's shell list, because the rule is easy to forget and +the failure is silent. + +### 4.2 An alarm that dies quietly is worse than no alarm + +The silence check was first designed as a background thread inside the +application. We removed it. A timer that dies takes the alarm with it and leaves +the interface showing green, and a green screen is read as a positive result +rather than an absent one. + +The check now runs on read — whenever anyone loads the accountability board, +rate-limited to once every thirty seconds. An external scheduler is supported +(`flask --app app sweep`) and deliberately optional: an external scheduler that +fails is at least visible to the machine running it, which an in-process timer +is not. + +This does not remove the dependency, it relocates it. The system now works while +somebody is looking. We regard that as the better failure mode, because a board +nobody is watching is a situation where nobody is relying on the answer — but +the claim needs stating rather than assuming. + +### 4.3 A limitation on screen is a different claim from a limitation in a file + +The consequence of §4.2 is that the guarantee is conditional, and our first +response was to write that down in a limitations document. That is the standard +move and we now think it is insufficient. + +The board displays how long since the last sweep — *checked 2s ago* beside the +live indicator, amber past five minutes, which is ten minutes before the +fifteen-minute escalation it drives. On a board somebody is watching it always +reads a few seconds, because the watching is what runs it. If it stops moving, +that is visible too. + +The general form: **emergency software should surface its own liveness.** A user +deciding whether to trust a screen needs to know whether the thing behind it ran, +and that is a different question from whether the data looks reasonable. We would +extend this beyond our own system: any interface that reports on a periodic +check should display when the check last completed, not merely its result. + +### 4.4 The pages built to be watched were the ones that broke under watching + +The board, the map and the feed all run the silence check before answering, and +the check writes. SQLite's default journal mode lets one writer lock out every +reader. With several people watching a board that refreshes every three seconds, +a write could wait past its timeout and fail the entire response. + +The pages whose purpose is to be watched continuously during an emergency were +precisely the pages that failed when watched continuously. The fix was +unremarkable — write-ahead logging, rate-limiting the sweep, catching the +failure rather than letting it become an error page. The lesson is not about +SQLite. It is that **making a read-only page write is a change of kind, not of +degree**, and in this system it converted the most-loaded pages into the most +fragile ones. + +One deliberate detail: a failed sweep does not record itself as having run. The +timestamp goes stale and the board reports that in amber, which is true, because +a check we could not record is not a check we can claim. + +### 4.5 Prose about a system lags the system + +Our test suite verifies every count in our own documentation — routes, tables, +tests, lines — and fails when the prose and the repository disagree. It has +caught wrong numbers repeatedly, including several we wrote ourselves. + +It has never once caught the more common error, which is a *sentence* that +describes a previous version of a behaviour. Four times a change landed and the +paragraph explaining it stayed a revision behind. Numbers are checkable and were +checked; claims are not, and were not. + +We do not have a solution and offer this as an observation: automated +documentation checks create a real assurance about the class of statement they +can verify and no assurance whatever about the class they cannot, and the second +class is where the misleading statements live. + +## 5. Limitations + +The system has eighteen documented limitations, maintained as a first-class +document rather than an appendix. We summarise the ones that most constrain what +this paper claims. + +**It has never been used in a real disaster.** Everything here is reasoned from +published accounts of Harvey, Kathmandu and Mexico City, and from published +triage protocol. None of it has been tested by somebody standing in water at two +in the morning. We believe the reasoning is sound; that is not the same as +knowing it works, and no part of this paper should be read as evidence that it +does. + +**The switch depends on being run.** Described in §4.2. Neither the read-trigger +nor an external scheduler is guaranteed. A deployment nobody looks at and nobody +configures performs no checks. + +**Overdue measures contact, not safety.** The system reports that it has not +heard from somebody. It cannot distinguish danger from a dead battery, and it +does not try. The interface language was revised twice to stop implying +otherwise, and this is the limitation most likely to be misread by a user in a +hurry. + +**No identity verification.** Anyone can register. This is a design condition +rather than a defect — a system requiring approval has reintroduced the +coordinator whose absence is the problem — but it means the system cannot +distinguish a responder from someone claiming to be one. + +**Location is self-reported** throughout. The map shows where people said they +were. + +**One cautious responder can hold a report open**, which biases the system toward +over-reporting need. We prefer that direction and note that we chose it. + +**Lockouts live in memory** and do not survive a restart. + +**The volunteers we claim to serve asked for the opposite.** Smith et al. (2018) +interviewed twenty Harvey rescuers and dispatchers, and the structural complaint +that came back was a wish for *more* coordination, not less. One dispatcher, on +being unable to prioritise calls: *"people that are trained to do that need to be +in charge of prioritizing calls and assigning."* Another described sending boats +away because too many had converged on one neighbourhood. + +This is the strongest available argument against our design, and it comes from +the population the design is for. We do not think it defeats the argument — the +wish for a trained coordinator does not summon one, and the interval before one +exists is exactly our subject — but a reader should weigh it. A system that +makes self-deployment easier and better-accounted-for may also make it more +attractive, and Smith et al. document a response that suffered from too many +boats as well as too little information. + +### A position rather than a finding + +The literature we build on treats converging volunteers as a population to be +managed: Kendra and Wachtendorf document access as negotiated legitimacy, with +credentialing, liability and security as the operative concerns, and volunteers +as a potential distraction that must outweigh its own cost. Our design treats +the volunteer as somebody owed an accounting. + +These are different moral starting points, and the literature does not share +ours. We think ours is defensible — a person who walks into a hazard to help is +owed something regardless of whether an institution has authorised them — but it +is a position, not a result, and a reader is entitled to reject it and evaluate +the design on the field's own terms instead. + +## 6. Future work + +The obvious next step is the one we have not taken: contact with people who do +this work. Five structured interviews with volunteer-response coordinators — +people who have run a reception centre, or turned volunteers away, or gone in +unaffiliated themselves — would test the assumption the whole design rests on, +which is that the interval before credentialing exists is a real operational gap +rather than an artefact of how we read the literature. + +Beyond that, a simulated-event walkthrough is the tractable route to evaluation +without waiting for a disaster; the crisis informatics community has precedent +for this. It would let us observe whether the silence mechanism produces +escalations at useful times, or whether it mostly produces false alarms from +people whose phones died — a distinction we currently cannot make. + +Two smaller questions we would want answered. Whether the fifteen-minute +escalation delay is anywhere near right; we chose it by reasoning, not by +measurement, and it is the kind of parameter that ought to come from data. +And whether making system liveness visible on screen — the sweep timestamp +described in §4.3 — actually changes how much a user trusts what they are +reading, or whether it is a designer's satisfaction that no user notices. + +We are aware that all of this describes work requiring access to a professional +community that two secondary-school students do not have. We would welcome +collaboration, and we mention it here rather than in an acknowledgement because +it is a limitation on the research, not a courtesy. + +## References + +*Format to the venue's template when it is known. Alphabetical for now.* + +Auferbauer D, Tellioğlu H. Centralized Crowdsourcing in Disaster Management: +Findings and Implications. In: *Proceedings of the 8th International Conference +on Communities and Technologies (C&T '17)*; 2017 Jun 26–30; Troyes, France. New +York: ACM Press; 2017. p. 173–182. DOI: 10.1145/3083671.3083689 + +Baker ND, Deham M. For a short time, we were the best version of ourselves: +Hurricane Harvey and the ideal of community. *International Journal of Emergency +Services*. 2019. DOI: 10.1108/IJES-12-2018-0066. Open access via NSF-PAR 10126439. + +Federal Emergency Management Agency. *Managing Spontaneous Volunteers in Times +of Disaster: The Synergy of Structure* — participant materials. Washington DC: +FEMA / Points of Light Foundation. + +Fritz CE, Mathewson JH. *Convergence Behavior in Disasters: A Problem in Social +Control*. Committee on Disaster Studies. Washington DC: National Academy of +Sciences – National Research Council; 1957. + +Kankanamge N, Yigitcanlar T, Goonetilleke A, Kamruzzaman M. Can volunteer +crowdsourcing reduce disaster risk? A systematic review of the literature. +*International Journal of Disaster Risk Reduction*. 2019;35:101097. +DOI: 10.1016/j.ijdrr.2019.101097 + +Kendra JM, Wachtendorf T. *Rebel Food… Renegade Supplies: Convergence after the +World Trade Center Attack*. Preliminary Paper 316. Newark DE: Disaster Research +Center, University of Delaware; 2002. + +Kendra JM, Wachtendorf T. Reconsidering Convergence and Converger Legitimacy in +Response to the World Trade Center Disaster. In: *Terrorism and Disaster: New +Threats, New Ideas*. Research in Social Problems and Public Policy, vol. 11; +2003. p. 97–122. DOI: 10.1016/S0196-1152(03)11007-1 + +Liu SB. Crisis Crowdsourcing Framework: Designing Strategic Configurations of +Crowdsourcing for the Emergency Management Domain. *Computer Supported +Cooperative Work (CSCW)*. 2014;23(4–6):389–443. DOI: 10.1007/s10606-014-9204-3 + +Smith WR, Robertson BW, Murthy D, Stephens KK, Li J. Social Media in +Citizen-Led Disaster Response: Rescuer Roles, Coordination Challenges, and +Untapped Potential. In: *Proceedings of the 15th ISCRAM Conference*; 2018 May; +Rochester NY. p. 639–648. Open access via NSF-PAR 10076203. + +Starbird K, Palen L. "Voluntweeters": Self-Organizing by Digital Volunteers in +Times of Crisis. In: *Proceedings of CHI 2011*; 2011 May 7–12; Vancouver BC. + +Zhou B, Zou L, Mostafavi A, Lin B, Yang M, Gharaibeh N, Cai H, Abedin J, +Mandal D. VictimFinder: Harvesting rescue requests in disaster response from +social media with BERT. *Computers, Environment and Urban Systems*. +2022;95:101824. DOI: 10.1016/j.compenvurbsys.2022.101824 + +**Cited through other authors, not read directly.** Kreps & Bosworth (1994) via +Starbird & Palen; Weick (1987) and Perrow (1977) via Kendra & Wachtendorf; +Stallings & Quarantelli (1985) via Kendra & Wachtendorf and Smith et al. Each +must be read or explicitly marked as reported-by before submission. + +--- + +## Outstanding before submission + +**1. Which Kendra & Wachtendorf.** Every quotation attributed to them here — the +twice-daily badge escalation, volunteers as "another group that needed to be +accounted for", the "minimal supervision" finding, and the Weick/Perrow +"strangers to the response milieu" sentence — was read in **Preliminary Paper +316 (2002)**, not the 2003 book chapter. The chapter is the more citable work +and we have not read it. **Cite PP 316 for every quotation, or obtain the +chapter and re-verify each one.** Citing the chapter for words read elsewhere +would be precisely the failure §5 argues against. + +**2. Three sources still unread.** Liu (2014), Auferbauer & Tellioğlu (2017) and +Kankanamge et al. (2019) are cited only for positions their abstracts state +outright. Zhou et al. (2022) is Bronze open access and readable in a browser — +verify the F1 of 0.919 and the 3,191-tweet corpus there before printing them. + +**3. AI usage disclosure.** To be written by the authors in Overleaf. + +**4. Second author review.** At assembly, only the first author had read this +document. + +## Assembly notes + +Generated from `research/draft-*.md`; editorial annotations (`[CHECK]`, +`[CUT?]`, source-confidence markers) were stripped. Body length at assembly: +about 5,300 words, before the venue's page limit is known. §4.5 is retained — +the abstract's count of five failure modes assumes it stays. diff --git a/README.md b/README.md index 3ebc445..f06b961 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ DiresQ tracks the people going into it.** [![CI](https://github.com/Skythe7/DiresQ/actions/workflows/ci.yml/badge.svg)](https://github.com/Skythe7/DiresQ/actions/workflows/ci.yml) [![Security](https://github.com/Skythe7/DiresQ/actions/workflows/security.yml/badge.svg)](https://github.com/Skythe7/DiresQ/actions/workflows/security.yml) -[![Tests](https://img.shields.io/badge/tests-551%20passing-brightgreen)](tests/test_app.py) +[![Tests](https://img.shields.io/badge/tests-600%20passing-brightgreen)](tests/test_app.py) [![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff) [![Limitations](https://img.shields.io/badge/limitations-written_down-f38ba8)](docs/limits.md) @@ -67,8 +67,8 @@ board turns red; the report on the right filed itself. That table is the night itself and does not move. It has kept growing since: -**25,151 lines written** — **19,033 lines of code** and 6,118 of -documentation — across **551 test functions**, 696 cases after +**27,324 lines written** — **19,750 lines of code** and 6,130 of +documentation — across **600 test functions**, 745 cases after parametrisation. Every one of those is checked by a test, so unlike the snapshot they cannot @@ -149,11 +149,12 @@ packet carries an age rather than a timestamp, because a node running off a battery in a flood is the last clock you want to trust. [The threat model →](docs/security.md) -**The accessibility audit found nineteen issues and we fixed all nineteen.** -Six were critical. Nine came from the first pass; four from a second over the -offline report form, where contrast passed everywhere and the announcing -didn't. Six more on the last day — and those six are the ones worth reading -about, because each sat under a passing test written to catch exactly that +**The accessibility audit found twenty-two issues and we fixed all +twenty-two.** Six were critical. Nine came from the first pass; four from a +second over the offline report form, where contrast passed everywhere and the +announcing didn't. Six more on the last day, and three from a fourth pass over +the demo clock — and those last nine are the ones worth reading about, because +each sat under a passing test written to catch exactly that kind of bug. The contrast test listed ten colour pairs by hand and never opened a stylesheet, so instructional text at 1.38:1 went unseen. The label test listed four pages, none of them the report form, so the form this whole @@ -346,6 +347,7 @@ override the file, so your shell and CI always win. | `DIRESQ_DEV_USER` | Stay signed in as this user without logging in. **Development only — it is a full auth bypass.** Leave unset for the real login flow. | | `DIRESQ_DB` | Path to the SQLite file. Defaults to `diresq.db`. | | `DIRESQ_HTTPS_ONLY` | Set to `1` when the site is served over HTTPS, so session cookies are marked Secure. Leave unset on localhost or you will not stay signed in. | +| `DIRESQ_DEMO_SPEED` | Multiplies the rate incident time passes, for filming. At `60` a check-in deadline and the fifteen-minute silence escalation play out in twenty seconds, using the production escalation code unchanged. Forces the demo banner on. **Leave unset anywhere real** — at any value above 1 every deadline and elapsed-time display in the app is wrong by that factor. See `docs/filming.md`. | | `DIRESQ_DEMO` | Set to `1` on a public instance. Puts a banner on every page saying it is a demo, the data resets, and not to type a real address into it. | ## API @@ -396,7 +398,7 @@ pip install -r requirements-dev.txt pytest -q ``` -551 test functions, which parametrisation expands into 696 cases, covering +600 test functions, which parametrisation expands into 745 cases, covering every route, the permission rules, feed ordering, staffing resolution, ETA parsing, overdue calculation, packet signing, the offline queues for both check-ins and reports, arrival-time duplicate detection, the auth guardrails @@ -525,8 +527,8 @@ fork, offline, or if Pages is down. know is wrong - [Security](docs/security.md) — the threat model, packet signing, and the open redirect we shipped by accident -- [Accessibility](docs/accessibility.md) — the WCAG 2.1 AA audit: nineteen - issues found across three passes, six critical, all fixed and held in place +- [Accessibility](docs/accessibility.md) — the WCAG 2.1 AA audit: twenty-two + issues found across four passes, six critical, all fixed and held in place by tests - [Limits](docs/limits.md) — what this doesn't do - [Disclaimer](docs/disclaimer.md) — it does not call for help, and the triage diff --git a/app.py b/app.py index b64a0a1..de85740 100644 --- a/app.py +++ b/app.py @@ -44,6 +44,8 @@ import base64 import binascii import csv +import math +import zlib import io import os import re @@ -75,6 +77,13 @@ DATABASE = os.environ.get("DIRESQ_DB", "diresq.db") +# How long a statement waits for a lock before giving up. SQLite's own default +# is zero — it returns "database is locked" on the first attempt — and Python's +# driver default is five seconds. Named here because it is a real deadline: two +# gunicorn workers of four threads each are eight things contending, and this +# is how long the eighth is willing to queue. +SQLITE_BUSY_SECONDS = 5.0 + # How long a responder has to check in when they didn't give an ETA. DEFAULT_CHECKIN_MINUTES = 30 @@ -165,8 +174,32 @@ def note_login_failure(username: str) -> None: def get_db() -> sqlite3.Connection: if "db" not in g: - g.db = sqlite3.connect(DATABASE, detect_types=sqlite3.PARSE_DECLTYPES) + g.db = sqlite3.connect(DATABASE, detect_types=sqlite3.PARSE_DECLTYPES, + timeout=SQLITE_BUSY_SECONDS) g.db.row_factory = sqlite3.Row + + # busy_timeout first, so the journal_mode switch below waits its turn + # rather than failing outright on a database somebody else is using. + g.db.execute(f"PRAGMA busy_timeout = {int(SQLITE_BUSY_SECONDS * 1000)}") + + # WAL, because this app writes on reads. The board polls + # /api/responders every three seconds and that request runs the + # silence sweep and stamps the clock, so a read endpoint is also the + # busiest writer. In the default rollback journal a writer locks out + # every reader and a reader locks out the writer, so two people with + # the board open is enough to start returning "database is locked" — + # which Flask serves as a 500 on the exact endpoint the map needs. + # + # In WAL readers never block the writer and the writer never blocks + # readers, which is the shape of this workload. It is a property of + # the file, not the connection, so this is a no-op after the first. + g.db.execute("PRAGMA journal_mode = WAL") + + # Don't fsync on every commit. The durability being traded away is + # "the last few commits survive an OS crash"; on an instance whose + # whole filesystem is discarded when it sleeps, that was never true. + g.db.execute("PRAGMA synchronous = NORMAL") + g.db.execute("PRAGMA foreign_keys = ON") return g.db @@ -178,8 +211,50 @@ def close_db(exc=None) -> None: db.close() +# The clock. +# +# DiresQ's central mechanism is the absence of an event over time: a deadline +# passes, nobody hears from a responder, and fifteen minutes later the server +# files a report about them. That is correct and completely unwatchable. You +# cannot show it to anyone in ninety seconds, and a mechanism nobody can see is +# a mechanism nobody believes. +# +# So the clock is injectable. DIRESQ_DEMO_SPEED multiplies elapsed time since +# process start: at 120, half a second of real waiting is a minute of incident +# time, and the whole silence-to-escalation sequence plays out in about fifteen +# seconds -- while every deadline, comparison and query downstream stays +# literally the code that runs in production. Nothing about the mechanism is +# faked for the camera; only the rate at which time passes into it. +# +# Two deliberate exclusions. Login lockout stays on the real clock, because +# scaling it would quietly weaken a security control on a public instance. The +# ICS-214 export filename stays real, because it names a file on somebody's +# disk and that name should mean what it says. +# +# At speed 1 -- the default, and the only value a real deployment should ever +# use -- now() is now() with no arithmetic at all. +def _demo_speed() -> int: + try: + return max(1, int(os.environ.get("DIRESQ_DEMO_SPEED", "1"))) + except ValueError: + # A typo in an env var must not take down an emergency board. + return 1 + + +DEMO_SPEED = _demo_speed() +_CLOCK_EPOCH = datetime.now(timezone.utc) + + +def now() -> datetime: + """The current time, as the incident sees it.""" + real = datetime.now(timezone.utc) + if DEMO_SPEED == 1: + return real + return _CLOCK_EPOCH + (real - _CLOCK_EPOCH) * DEMO_SPEED + + def now_iso() -> str: - return datetime.now(timezone.utc).isoformat(timespec="seconds") + return now().isoformat(timespec="seconds") def parse_iso(value: str | None) -> datetime | None: @@ -280,7 +355,7 @@ def deadline_for(joined_at: str, eta: str | None, def is_overdue(joined_at: str, eta: str | None, last_checkin: str | None) -> bool: """Derived at read time so there's no cron job to forget to start.""" deadline = deadline_for(joined_at, eta, last_checkin) - return deadline is not None and datetime.now(timezone.utc) > deadline + return deadline is not None and now() > deadline REPORT_COLUMNS = f""" @@ -313,7 +388,7 @@ def age(item: dict) -> dict: item.get("received_at")) item["minutes_old"] = ( None if written is None - else max(0, int((datetime.now(timezone.utc) - written).total_seconds() // 60)) + else max(0, int((now() - written).total_seconds() // 60)) ) return item @@ -491,7 +566,14 @@ def inject_demo_mode(): anything filed here is thrown away, so nobody types a real address into a database that resets when the server sleeps. """ - return {"demo_mode": os.environ.get("DIRESQ_DEMO") == "1"} + # A scaled clock forces the banner on. A page showing time passing sixty + # times faster than the wall clock has to say so on the page -- the same + # rule the sweep timestamp follows, applied to the clock itself. Otherwise + # the honest version of this feature is indistinguishable from a fake one. + return { + "demo_mode": os.environ.get("DIRESQ_DEMO") == "1" or DEMO_SPEED > 1, + "demo_speed": DEMO_SPEED, + } @app.context_processor @@ -558,13 +640,35 @@ def fetch_report(report_id: int) -> dict | None: item["responders"] = [dict(x) for x in get_db().execute(""" SELECT asg.id, asg.status, asg.eta, asg.staffing_vote, asg.joined_at, asg.position_mismatch, - acc.username, acc.capabilities, acc.id AS account_id + acc.username, acc.capabilities, acc.id AS account_id, + (SELECT MAX(created_at) FROM checkins c + WHERE c.responder = asg.responder) AS last_checkin FROM assignments asg JOIN accounts acc ON acc.id = asg.responder WHERE asg.report_id = ? ORDER BY asg.joined_at """, (report_id,)).fetchall()] + # Whether each of them is still answering. + # + # This page listed status and nothing else, and status is what somebody + # last *told* us — not whether they are still there to tell us anything. + # So a responder could read "on scene" here while the board had them + # forty-five minutes overdue, and a coordinator deciding whether this + # address needs more help would count them as coverage. + # + # That is this project's own argument failing on its own page. The feed + # groups duplicates so that six people on one incident cannot read as two + # comfortable rows; the same honesty has to apply to one person who has + # stopped answering. An unresponsive responder is not coverage. + for responder in item["responders"]: + responder["overdue"] = ( + responder["status"] != "cleared" + and is_overdue(responder["joined_at"], responder["eta"], + responder["last_checkin"])) + + item["overdue_here"] = sum(1 for r in item["responders"] if r["overdue"]) + # What the person looking at this page is allowed to press. Working it out # here keeps the permission rules in one place instead of scattered # through the template. @@ -890,7 +994,7 @@ def create_report(*, subject: str, description: str, priority: str, "synced_late": late_sync(seen["created_at"], seen["received_at"])} - received = datetime.now(timezone.utc) + received = now() try: cur = db.execute(""" INSERT INTO reports @@ -1206,7 +1310,7 @@ def fetch_responders() -> list[dict]: ORDER BY acc.username, asg.joined_at DESC """).fetchall() - now = datetime.now(timezone.utc) + moment = now() board, seen = [], set() for row in rows: @@ -1217,11 +1321,25 @@ def fetch_responders() -> list[dict]: overdue = False minutes = None + due_in = None if row["assignment_id"] is not None: overdue = is_overdue(row["joined_at"], row["eta"], row["last_checkin"]) contact = parse_iso(row["last_checkin"]) or parse_iso(row["joined_at"]) if contact is not None: - minutes = int((now - contact).total_seconds() // 60) + minutes = int((moment - contact).total_seconds() // 60) + + # Seconds until this responder is expected to answer. Negative once + # the deadline has passed, so the board can say how far past it is + # rather than only that it is. + # + # The board used to show only elapsed time, which states the past + # and leaves the future to be inferred. A number counting toward + # zero is the difference between a viewer working out that + # something is about to happen and a viewer watching it happen. + deadline = deadline_for(row["joined_at"], row["eta"], + row["last_checkin"]) + if deadline is not None: + due_in = int((deadline - moment).total_seconds()) if row["assignment_id"] is None: state = "available" @@ -1237,6 +1355,7 @@ def fetch_responders() -> list[dict]: "state": state, "overdue": overdue, "minutes_since_contact": minutes, + "due_in_seconds": due_in, "assignment": None if row["assignment_id"] is None else { "id": row["assignment_id"], "report_id": row["report_id"], @@ -1306,14 +1425,14 @@ def sweep_silent_responders() -> list[int]: WHERE asg.status != 'cleared' """).fetchall() - now = datetime.now(timezone.utc) + moment = now() filed = [] for row in rows: deadline = deadline_for(row["joined_at"], row["eta"], row["last_checkin"]) if deadline is None: continue - if now < deadline + timedelta(minutes=SILENT_ESCALATE_MINUTES): + if moment < deadline + timedelta(minutes=SILENT_ESCALATE_MINUTES): continue already = db.execute(""" @@ -1334,7 +1453,7 @@ def sweep_silent_responders() -> list[int]: lat, lng = row["report_lat"], row["report_lng"] where = "the scene they were heading to, no position ever received" - silent = int((now - (seen or parse_iso(row["joined_at"]) or now)) + silent = int((moment - (seen or parse_iso(row["joined_at"]) or moment)) .total_seconds() // 60) db.execute(""" @@ -1459,13 +1578,46 @@ def security_headers(response): return response +# How often the sweep is actually worth running. The board polls +# /api/responders every three seconds *per viewer*, and the sweep is a join +# across every open assignment plus a write. Running it on each poll made the +# cost of the alarm scale with the number of people watching it, which is +# backwards: the sweep is about elapsed time, and elapsed time does not care +# how many browsers are open. +# +# Thirty seconds is thirty times inside the fifteen-minute escalation it +# guards, so nothing is ever noticed late, and it takes roughly nine writes +# in ten off the hot path. +SWEEP_EVERY_SECONDS = 30 + + @app.before_request def escalate_silence(): - if (request.method == "GET" - and request.endpoint in SWEEP_ON - and current_user() is not None): + if (request.method != "GET" + or request.endpoint not in SWEEP_ON + or current_user() is None): + return + + since = last_swept()["seconds"] + if since is not None and since < SWEEP_EVERY_SECONDS: + return + + try: sweep_silent_responders() - record_sweep() + except sqlite3.Error: + # Same reasoning as record_sweep below, and higher stakes. This runs in + # before_request, so an exception here does not fail the sweep — it + # fails the whole response, and the endpoints it is attached to are the + # board, the map and the feed. A lock contention blanking the three + # screens somebody uses during a flood is a far worse outcome than a + # sweep that runs thirty seconds later instead. + # + # Deliberately does not stamp: a sweep that did not finish must not + # claim it did, or the board shows green while nothing is checking. + get_db().rollback() + return + + record_sweep() def record_sweep() -> None: @@ -1509,7 +1661,7 @@ def last_swept() -> dict: if when is None: return {"at": None, "seconds": None, "stale": True} - seconds = int((datetime.now(timezone.utc) - when).total_seconds()) + seconds = int((now() - when).total_seconds()) return { "at": row["last_swept_at"], "seconds": max(seconds, 0), @@ -1536,24 +1688,24 @@ def claimed_time(raw: str) -> tuple[datetime, str | None]: barely in the future is clock drift, far in the future or very old is either a broken device or someone playing games. """ - now = datetime.now(timezone.utc) + moment = now() if not raw: - return now, None + return moment, None when = parse_iso(raw) if when is None: - return now, "Could not read that timestamp." + return moment, "Could not read that timestamp." if when.tzinfo is None: when = when.replace(tzinfo=timezone.utc) - if (when - now).total_seconds() > CLOCK_SKEW_SECONDS: - return now, "That check-in is dated in the future." - if (now - when).total_seconds() > MAX_BACKDATE_HOURS * 3600: - return now, f"Too old to accept, over {MAX_BACKDATE_HOURS} hours." + if (when - moment).total_seconds() > CLOCK_SKEW_SECONDS: + return moment, "That check-in is dated in the future." + if (moment - when).total_seconds() > MAX_BACKDATE_HOURS * 3600: + return moment, f"Too old to accept, over {MAX_BACKDATE_HOURS} hours." # Slightly ahead is a drifting clock, not a lie. Don't let it sit in the # future, but don't reject it either. - return min(when, now), None + return min(when, moment), None def position_looks_wrong(report_id: int, account_id: int) -> bool: @@ -1909,7 +2061,7 @@ def ics214_rows() -> list[list[str]]: is most of the argument for logging responders at all. """ db = get_db() - now = datetime.now(timezone.utc) + moment = now() responders = db.execute(""" SELECT acc.username, acc.capabilities, MIN(asg.joined_at) AS first_seen @@ -1979,7 +2131,7 @@ def ics214_rows() -> list[list[str]]: [], ["1. Incident Name", "DiresQ activation - Katy, TX"], ["2. Operational Period", "From", stamp(started), - "To", now.strftime("%m/%d/%Y %H:%M")], + "To", moment.strftime("%m/%d/%Y %H:%M")], ["3. Name", current_user()["username"], "ICS Position", "Resource Unit Leader", "Home Agency", "DiresQ (volunteer)"], @@ -2000,7 +2152,7 @@ def ics214_rows() -> list[list[str]]: [], ["6. Prepared by", current_user()["username"], "Position", "Resource Unit Leader", - "Date/Time", now.strftime("%m/%d/%Y %H:%M")], + "Date/Time", moment.strftime("%m/%d/%Y %H:%M")], [], ["Generated by DiresQ from logged activity. Times are UTC. Report " "resolution and staffing changes are not separately timestamped and " @@ -2172,7 +2324,7 @@ def stand_down_for(account_id: int) -> dict | None: "subject": row["subject"], "at": row["status_changed_at"], "minutes_ago": None if closed is None else max( - 0, int((datetime.now(timezone.utc) - closed).total_seconds() // 60)), + 0, int((now() - closed).total_seconds() // 60)), } @@ -2251,7 +2403,7 @@ def record_checkin(responder_id: int, lat, lng, happened_at: datetime, seen["received_at"]), } - received = datetime.now(timezone.utc) + received = now() try: db.execute(""" INSERT INTO checkins @@ -2391,7 +2543,7 @@ def api_uplink(): # The packet carries an age, not a timestamp — a node running off a # battery in a flood is the last clock you want to trust. - happened_at = (datetime.now(timezone.utc) + happened_at = (now() - timedelta(minutes=checkin.age_minutes)) result = record_checkin(checkin.responder_id, checkin.lat, checkin.lng, @@ -2437,6 +2589,12 @@ def init_db() -> None: # Two responders deliberately left unassigned. A board where everybody is # busy has nothing to say when a report needs a boat, and a real one # always has somebody between jobs. + # The one the camera is pointed at. Everybody else on this board is in a + # state that is already settled -- Sam is red, the Mayde Creek four are + # overstaffed, the rest are en route with time in hand. Farrow is the only + # one whose state is about to CHANGE while you watch, which is the whole + # point: the mechanism is a transition, and a transition needs a before. + ("n.farrow", "responder", "medical,generator"), ("r.castillo", "responder", "boat,swiftwater,medical"), ("t.oyelaran", "responder", "chainsaw,truck,generator"), # Two more with boats, who went to the *second* report of the flood on @@ -2524,6 +2682,23 @@ def init_db() -> None: # Oxygen: someone en route with a sensible ETA. (2, "a.whitlock", "en_route", None, 20, 30, 14), + # Oxygen, second responder: Farrow joined twenty minutes ago and gave an + # ETA that lands forty-five minutes from now. On a real clock that is a + # dull row on a board. With DIRESQ_DEMO_SPEED set it is a countdown, and + # then it is a red row, and then it is a report about a person -- which is + # the sequence the entire project exists to produce and the one thing we + # could never show anybody. + # + # They have checked in, so when the escalation fires it pins at a real + # last-known position rather than guessing from the scene. + # + # Five minutes, not forty-five. The first draft of this row put Farrow's + # deadline furthest out, which meant every other responder on the board + # went red first and the camera had nothing to point at. Farrow now leads + # the queue by four minutes, so the first row to turn and the first report + # to file itself are the same person. + (2, "n.farrow", "en_route", None, 20, 25, 6), + # Roof: Sam went, and nobody has heard from him since. (4, "s.reyes", "on_scene", None, 62, None, 47), @@ -2589,16 +2764,46 @@ def seed_minimal() -> tuple[int, int]: return len(accounts), len(reports) +def responder_position(username: str, lat: float, + lng: float) -> tuple[float, float]: + """Where to put a seeded responder relative to the report they joined. + + Two bugs lived in the one line this replaces. + + It used `hash(username)`, and Python salts string hashing per process — + so the demo moved every time the server booted. A seed whose whole point + is that every visitor arrives at the same incident cannot be built on a + number that changes at import. crc32 is stable across runs and versions. + + And it offset by at most ninety metres, which put the responder under the + report. Leaflet draws markers in a pane above circles, so the responder + was not missing from the map — it was painted underneath the teardrop and + invisible at any useful zoom. Standing them off on a ring is what makes + "six people on one street" a thing you can see rather than infer. + """ + n = zlib.crc32(username.encode()) + + bearing = math.radians(n % 360) + metres = 150 + (n // 360) % 120 + + # Degrees per metre. Longitude narrows with latitude, so the correction + # keeps the ring circular rather than an ellipse. + d_lat = metres * math.cos(bearing) / 111_320 + d_lng = metres * math.sin(bearing) / (111_320 * math.cos(math.radians(lat))) + + return round(lat + d_lat, 6), round(lng + d_lng, 6) + + def seed_data() -> tuple[int, int]: """Load a disaster already in progress. Seeding an empty board makes the app look like a to-do list. Seeding it mid-incident shows what it's for. """ - now = datetime.now(timezone.utc) + moment = now() def ago(minutes): - return (now - timedelta(minutes=minutes)).isoformat(timespec="seconds") + return (moment - timedelta(minutes=minutes)).isoformat(timespec="seconds") with app.app_context(): db = get_db() @@ -2646,7 +2851,7 @@ def ago(minutes): report_id = report_ids[idx] eta = None if eta_mins is not None: - eta = (now - timedelta(minutes=joined) + eta = (moment - timedelta(minutes=joined) + timedelta(minutes=eta_mins)).isoformat(timespec="seconds") # Someone still en route hasn't changed status since joining, so @@ -2667,17 +2872,16 @@ def ago(minutes): "AND status = 'unassigned'", (report_id,)) if checkin is not None: - # Scatter positions near the report so the map has something. report = db.execute( "SELECT lat, lng FROM reports WHERE id = ?", (report_id,) ).fetchone() - jitter = (hash(username) % 9 - 4) / 5000 + lat, lng = responder_position(username, report["lat"], + report["lng"]) db.execute(""" INSERT INTO checkins (responder, lat, lng, created_at, received_at) VALUES (?, ?, ?, ?, ?) - """, (who[username], report["lat"] + jitter, - report["lng"] - jitter, ago(checkin), ago(checkin))) + """, (who[username], lat, lng, ago(checkin), ago(checkin))) db.commit() return len(SEED_ACCOUNTS), len(SEED_REPORTS) diff --git a/docs/accessibility.md b/docs/accessibility.md index d843a54..a12e58d 100644 --- a/docs/accessibility.md +++ b/docs/accessibility.md @@ -8,12 +8,13 @@ Nine issues, three of them critical. Then four more when reports learned to work offline and the form grew a status message somebody cannot afford to miss. Then six more on the last day, when the audit finally read the stylesheets instead of the palette and the report form instead of the pages -that already had tests. +that already had tests. Then three more after that, reviewing the countdown +the board grew so the escalation could be filmed. -Nineteen in total, six of them critical, all fixed, and all now held in place -by tests that run in CI — because an audit nobody can repeat is a claim, not a -result. The last six are the interesting ones: every one of them sat under a -passing test whose job was to catch exactly that. +Twenty-two in total, six of them critical, all fixed, and all now held in +place by tests that run in CI — because an audit nobody can repeat is a claim, +not a result. The last nine are the interesting ones: every one of them sat +under a passing test whose job was to catch exactly that. --- @@ -194,6 +195,42 @@ found, not the rule that was broken. A test that lists pages will not cover the page added next week, and a test that lists colours will not see the one you are about to use. +### Found reviewing the demo clock, after submission + +The board grew a countdown — *due in 5 min*, falling to *20 min past due* — +so the escalation could be filmed. Reviewing it turned up three things, and +only one of them was an accessibility problem. + +**The countdown was drawn once and then erased.** It was added to +`templates/board.html` and not to `board.js`, which replaces the whole list +every three seconds. It rendered on load, and the first poll wiped it. No test +saw it, because the tests read the template. Nobody would see it by hand +unless they watched one row for three seconds. Not a WCAG issue at all — the +audit found it because auditing means reading the thing rather than the notes +about it. + +**A ticking number inside a live region.** `#responders` is +`aria-live="polite"` and is replaced wholesale on every poll. A countdown +changes on every repaint, and at `DIRESQ_DEMO_SPEED=60` that is every three +seconds forever — announcements queued faster than they can be spoken, burying +the one that matters, which is the badge changing to OVERDUE. The countdown is +`aria-hidden="true"`. That is a real trade and it is written down in +[limits.md](limits.md) rather than only here. *(4.1.3 Status Messages)* + +**Two more unreadable greys, on the board this time.** `--overlay` (`#45475a`) +on the row background is **1.92:1**, and it was the colour of the coordinates +and of every *"not assigned"*, *"no position"* and *"no contact yet"* state. +The test that exists to prevent exactly this — the one named after not +reintroducing the unreadable greys — only ever read `a11y.css`. Widening it to +every stylesheet found six more files doing the same thing: the disclaimer +footer, the legal links under three forms, the offline page's timestamp and +footer, the triage footnote, and the stood-down vote on a report. +*(1.4.3 Contrast (Minimum))* + +The pattern is the same one this page keeps recording. Each time, the test was +written around the file where the bug was found instead of the rule that was +broken. + ## What was already right Worth recording, because it was mostly by accident of building the boring way: @@ -223,6 +260,10 @@ Worth recording, because it was mostly by accident of building the boring way: | Board is polite, not assertive | A future "make it announce faster" | | Contrast of the palette pairs | Computes the ratio from the hex and fails below 4.5:1 | | No stylesheet sets text to an unreadable grey | Reads all fourteen stylesheets — the palette test could not see these | +| **Every `color:` in every stylesheet is readable** | Resolves `var()` against each file's own palette and checks the result against the backgrounds it can actually sit on. Not a list of colours — the declarations themselves | +| **The board's two renderers agree** | Every `r.` in `board.js` appears in `board.html` and back, with an explicit exception list | +| **Every fragment `rowHtml` builds is emitted** | Field parity alone stays green if the interpolation is deleted and the local left behind | +| **The countdown is out of the live region** | A number that changes every repaint would talk over the state change it counts toward | | The status region is unhidden before it is written | A live region announcing nothing | | Only one thing announces a queued report | Two regions talking over each other | | The suggestion panel does not rewrite identical markup | A paragraph repeated at somebody every few seconds | @@ -235,11 +276,24 @@ stylesheet. Any class using a colour that wasn't on the list was invisible to it, which is exactly how `.hint` sat at 1.38:1 for weeks under a test whose whole job was contrast, passing. -There are two tests now. The original still checks the palette. A second one +There are three tests now. The original still checks the palette. A second reads every stylesheet, finds the greys that are unreadable on anything we put -behind them, and fails unless `a11y.css` demonstrably lifts that selector — -so a fix cannot be quietly undone by a more specific rule, which is the other -way this went wrong. +behind them, and fails unless `a11y.css` demonstrably lifts that selector — so +a fix cannot be quietly undone by a more specific rule, which is the other way +this went wrong. + +The third stops listing anything. It reads every `color:` declaration in every +stylesheet, resolves `var()` against that file's own palette, and checks the +result against the backgrounds it can sit on — the page surfaces for ordinary +text, the bright accent fills for the near-black text that goes on badges. + +Getting that split right took two attempts and the second attempt was caught +by its own canary. The first version classified anything above 0.03 relative +luminance as light text; `#45475a` sits at 0.065, so it was compared against +yellow badges it never appears on, passed comfortably, and would have let +through the exact colour the test was written for. There is now an assertion +that the grey which caused all this is still classified as light text — a +check whose only job is to fail if the check above it stops working. ## What has not been done diff --git a/docs/api.md b/docs/api.md index f6415bd..ab40aef 100644 --- a/docs/api.md +++ b/docs/api.md @@ -243,6 +243,7 @@ nothing else would catch it. "state": "overdue", "overdue": true, "minutes_since_contact": 47, + "due_in_seconds": -900, "assignment": { "id": 3, "report_id": 1, @@ -256,6 +257,8 @@ nothing else would catch it. } ``` +`due_in_seconds` counts toward the responder's next expected check-in and goes negative once it has passed, so a client can show how far past due somebody is rather than only that they are. It is null when no deadline can be derived — nobody assigned, or an assignment with neither an ETA nor a check-in to count from. + `state` is `overdue`, `on_scene`, `en_route` or `available`, and rows arrive already sorted in that order. Switch on that one field — don't recompute the overdue rule client-side, and don't re-sort. diff --git a/docs/architecture.md b/docs/architecture.md index a4a4525..40082e7 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -12,8 +12,8 @@ something in the code, or take it apart. ## Shape Flask, SQLite through the `sqlite3` module, Jinja templates rendered on the -server, and a small amount of JavaScript that layers on top. Roughly 4,000 -lines of Python across six modules, 33 routes, six tables, 551 test +server, and a small amount of JavaScript that layers on top. Roughly 4,250 +lines of Python across six modules, 33 routes, six tables, 583 test functions. ``` @@ -290,7 +290,7 @@ by report and by responder, check-ins by `(responder, created_at DESC)`. ## Testing -551 test functions, which parametrisation expands into over six hundred +600 test functions, which parametrisation expands into over seven hundred cases. Each gets a throwaway database via `tmp_path`, so order never matters and a failure can't poison the next test. @@ -328,7 +328,7 @@ happens. | File | Lines | What it owns | | --- | --- | --- | -| `app.py` | 2,774 | Routes, queries, the rules, CLI commands | +| `app.py` | 2,891 | Routes, queries, the rules, CLI commands | | `classify.py` | 805 | The classifier, its corpus, and the browser export | | `transport.py` | 204 | The radio packet: layout, signing, verification | | `eta.py` | 175 | Free-text ETA parsing behind a confidence gate | diff --git a/docs/decisions.md b/docs/decisions.md index df75dda..e8ed22a 100644 --- a/docs/decisions.md +++ b/docs/decisions.md @@ -130,6 +130,43 @@ is nobody else to attribute it to. One `auto_filed_for` column stops it filing a second: while an open report points at someone, the alarm has already been raised. +## Time is injectable, and only ever for the camera + +The thing this project is about is an absence: a deadline passes, nobody hears +from a responder, and fifteen minutes later the server files a report about +them. Correct, and impossible to show anybody. You cannot demonstrate the +non-occurrence of an event in ninety seconds, and a mechanism nobody can watch +is a mechanism nobody believes. + +The options were to fake it — a scripted walkthrough, a video with a cut in the +middle, a "simulate escalation" button — or to make time itself the parameter. +We took the second. `DIRESQ_DEMO_SPEED` multiplies elapsed time since process +start, so at 60 a minute of incident time passes every second and the whole +sequence plays out in twenty. There is one `now()`; every deadline, comparison +and query downstream is the production code, untouched. Nothing about the +mechanism is special-cased for being watched. + +The alternative we rejected was shortening the constants in demo mode — +`SILENT_ESCALATE_MINUTES = 1` and so on. It is simpler and it is a lie of a +different shape: the page would then say "1 minute" where the real system says +fifteen, and every displayed duration would have to be reasoned about +separately. Scaling the clock keeps the numbers on screen the numbers the +system actually uses. + +Two things stay on the real clock. **Login lockout**, because scaling it +weakens a security control, and a demo instance is a public one. **The ICS-214 +export filename**, because it names a file on somebody's disk and that name +should mean what it says. + +The cost is that a misconfigured `DIRESQ_DEMO_SPEED` is invisible. Every other +environment variable here fails loudly or obviously; this one leaves an app +that looks completely plausible while every deadline, countdown and elapsed +time is wrong by a constant factor. It defaults to 1, an unparseable value +falls back to 1, 0 is refused because it would stop time, and any value above +1 forces the demo banner on and makes it state the multiplier — a page showing +accelerated time has to say so, for the same reason the board shows when the +sweep last ran. + ## The sweep rides on reads, not a scheduler There's no cron job and no background thread. The check for silence runs when diff --git a/docs/deploy.md b/docs/deploy.md index 36d508f..6484ba1 100644 --- a/docs/deploy.md +++ b/docs/deploy.md @@ -73,6 +73,12 @@ of `get_db()`. Not for a demo. `DIRESQ_DEV_USER` is **not** set. That's the auth bypass — on a public instance it would sign every visitor in as the same person. +`DIRESQ_DEMO_SPEED` is **not** set either, which leaves it at 1 and the clock +real. It exists so the silence escalation can be filmed (`docs/filming.md`); +set on a live instance it would make every deadline, countdown and elapsed +time on every page wrong by that factor, while still looking entirely +plausible. It is the one variable here whose misconfiguration is invisible. + ## gunicorn, not the dev server `start.sh` runs gunicorn with two workers and four threads. diff --git a/docs/devpost-story.md b/docs/devpost-story.md new file mode 100644 index 0000000..9e5f5d2 --- /dev/null +++ b/docs/devpost-story.md @@ -0,0 +1,136 @@ +## Inspiration + +During Hurricane Harvey, civilians took their own fishing boats out to pull neighbours off roofs. They rescued thousands of people. Some of them drowned doing it. + +One detail kept pulling us back. When a volunteer self-deploys, **nobody writes down that they went.** No dispatcher, no roster, no log. If they don't come back, there is no moment where a system notices — someone eventually realises they haven't heard from a person in a while. + +A dispatcher who was there put it better than we could. Interviewed afterwards by researchers at ISCRAM, he described trying to keep track of "who was going out who was coming back who was out on a boat, **can we account for everyone**, and who's in their house and it was a mess." The same study found at least twenty separate volunteer groups operating with, between them, "no way to seamlessly share information and coordinate activity." + +The detail that decided the design is smaller than either. The rescuers in that study described their phones constantly blowing up with relatives asking *"are you okay, are you okay, are you okay."* Somebody was always going to ask the question. The question simply had nowhere to be answered. + +Every disaster app we looked at maps the incident. We couldn't find one that keeps a list of the people walking into it. + +## What it does + +You file a report: what's happening, how bad, and where — pinned on a map or pulled from your phone's GPS. If you can't judge how bad it is, four questions run START, the triage protocol used at real multiple-casualty scenes, and pick for you. + +Responders join and give a rough ETA in plain English — "30 min", "back in a couple hours". That becomes a check-in deadline. + +Then the part the whole thing exists for: **if nobody hears from you by your deadline, the board turns red.** Your name, your last known position, how long since anyone heard from you. Nobody has to notice. Nobody has to remember you went out. + +Stay quiet fifteen minutes past that and the server stops waiting to be noticed. It files a report *about you*, at your last known position. It joins the feed like any other job, so somebody can go and find you. + +**You can watch this happen rather than take our word for it.** The mechanism is the *absence* of an event over fifteen minutes, which is the hardest thing in software to show anybody. So the clock is injectable: with `DIRESQ_DEMO_SPEED=60` a minute of incident time passes every second, a responder goes overdue five seconds after the page loads, and the report about them arrives fifteen seconds after that. Nothing is staged for the camera — there is one `now()`, and every deadline, comparison and query downstream is the production code untouched. Only the rate at which time enters the system changes, and the page says so while it does, because a screen showing accelerated time has to admit it. + +Any number of responders can join the same report — there's no claim lock, deliberately. Once you're physically on scene you can signal how staffed the site is, and that reorders the feed, so the next person who opens the app goes where the help isn't. + +## How we built it + +Flask and SQLite, server-rendered pages with a JSON API layered on top, Leaflet for maps. The whole app works with JavaScript switched off. + +**Four of the libraries are ours** — written from scratch, published to PyPI, then installed back into this project like anyone else's dependency: + +| Package | What it does here | +| --- | --- | +| `timefuzz` | turns "back in a couple hours" into a real deadline, with a confidence score | +| `vitalscore` | runs the START triage decision tree | +| `pygeospy` | distance, bearing and bounding-box maths | +| `patchnotes` | validates our changelog on every push | + +### The machine learning, and why it isn't a language model + +Somebody filing a report at 2am from a flooded house is being asked to pick a severity from a dropdown. They don't know. They aren't trained, they're frightened, and the honest answer to "how bad is this on a three-point scale" is *you tell me*. + +So we hand-wrote a multinomial naive Bayes classifier. One file, no dependencies, no model file, no network, 0.1 ms per call, trained on 55 hand-labelled reports. The whole decision is one line of maths: + +$$\hat{y} = \arg\max_{c} \left[ \log P(c) + \sum_{i} n_i \log P(w_i \mid c) \right]$$ + +Type *"water rising fast, grandmother upstairs and cannot walk down"* and it answers `HIGH`, and tells you it decided that from *rising, upstairs, cannot* — those are the top terms of that same sum, not a separate explanation. Touch the dropdown yourself and it stops adjusting it, permanently. + +The same maths spots when your description matches a report **somebody has already filed**, by cosine similarity over stemmed term counts: + +$$\text{sim}(a, b) = \frac{\mathbf{a} \cdot \mathbf{b}}{\lVert \mathbf{a} \rVert \, \lVert \mathbf{b} \rVert}$$ + +Duplicate reports are exactly how six people end up at one address while a street nearby has nobody. That threshold was measured, not guessed: + +| | Similarity | +| --- | --- | +| Two genuinely different reports | at most **0.157** | +| A restatement of the same incident | **0.409** | +| A *reworded* restatement using synonyms | **0.241** | + +We set it at **0.30** — nearly double the margin over the worst false positive. Note the third row: it misses the synonym case, and we left that in the table because it's the honest limit of counting words. "Flooding, couple on the second floor" and "water rising, two adults upstairs" share almost no vocabulary and describe the same house. Catching that needs embeddings, and embeddings need a model file, a download, and a machine to run it on. + +We deliberately did not use an LLM, for three reasons in the order they mattered: + +1. **It has to explain itself.** The words shown *are* the decision — the ranked log-odds — not a separately generated rationalisation that can disagree with it. "Trust me" isn't available when somebody is deciding where to send a boat. +2. **It has to be honest about being wrong.** Below 45% confidence it says nothing at all. A confident paragraph from a language model is much harder to disbelieve, and this is a domain where confidently wrong sends people to the wrong street. +3. **It has to run.** No download, no API key, no network, no GPU. Our check-ins already queue offline; a classifier that needed somebody else's datacentre would be the one part of the system that fails exactly when it's needed. + +### How we used AI + +Two different things get called AI here, and the paragraphs above are only about one of them, so to be unambiguous: + +**In the shipped product — none.** No LLM, no API, no model file. The classifier is the naive Bayes described above, and that is the only machine learning DiresQ contains. + +**In building it — yes.** We used AI for code, documentation including this page, and literature search. It was a working tool for fourteen hours, not a footnote. + +What that did and didn't cover. Every design decision reported here is ours, including the one we reversed — the claim lock came out because *we* read about Kathmandu and Mexico City and concluded it was wrong. Every number on this page was produced by running the code and reading the output, not by asking a model what it thought the answer was; the held-out 75%, the 0.30 threshold and the 0.157/0.409 margins are all measurements, and the test suite fails the build if any of them drift. The commit history is public if you want to see how it was actually built. + +## Challenges we ran into + +**Our first design was wrong, and we threw it out.** We built the dispatch model: one responder claims one report, it's locked, nobody else can take it. It felt obviously right. Then we read about Kathmandu in 2015 and Mexico City in 1985 — hundreds of neighbours converging on single collapse sites — and about Harvey, where whoever owned a boat went to whatever address they saw online. A claim lock would have fought the exact thing that saves people. The real failure mode isn't two people colliding on one job; it's fifty people on one street while the next one over has nobody. + +**The plan didn't survive contact.** We'd agreed the backend would push stub JSON endpoints in the first hour so the frontend could build against them — and then we put the one hard dependency in the whole plan on a single task and didn't treat it as one. It sat in the doc looking like a step rather than a blocker. The stubs never got written, and the frontend rightly kept moving instead of waiting, building five complete pages as server-rendered templates that ignore JSON entirely. + +The plan failing produced a better app — the whole thing works without JavaScript now. What it cost was the contract: with no stubs and no conversation instead of them, both sides assumed one, and three field names came out different. The lesson isn't "somebody should have waited." It's that a plan with a dependency in it needs that dependency named as one, out loud, with a time on it. + +**Deciding what not to build was harder than building.** LoRa mesh is roadmap-only. We don't have radios, so we couldn't test it, and untested code isn't a feature — it's a file that looks like one. + +## Accomplishments that we're proud of + +**We caught our own classifier lying, and published the number.** + +We checked it the obvious way first — run it over the corpus it was trained on. It scored **100%**. That number is worthless: it had memorised its 55 examples. Measured properly, holding one report out and retraining on the other 54, fifty-five times over: + +| | Held out | +| --- | --- | +| Always guess the commonest label | 36% | +| Naive Bayes alone | **45%** | +| Naive Bayes + severity lexicon | **75%** | + +Nine points above guessing, and wrong in the worst possible direction — *"child not breathing properly"* came back `MEDIUM`, *"gas smell, whole street evacuating"* came back `LOW`. + +The fix was a lexicon of the categories a triage protocol calls immediate, written from the START protocol rather than from our own failures, with a test asserting no phrase ever fires on a report labelled something else. That measurement runs in CI and fails the build if it regresses below 68%. + +It still gets one report in four wrong. That's survivable because it lands in a dropdown you control, next to the words that caused it — and it would be unacceptable if it were deciding anything. + +**600 tests, 745 cases with parameters** — including a WCAG 2.1 AA audit, adversarial input tests, and a suite that reads our own documentation and fails the build when the numbers in it go stale. That last one caught us mid-project: it went red because we'd added the research write-up to the repo and the README's line count silently became a lie. + +**We wrote the paper.** Somewhere around hour forty we realised the interesting claim wasn't the app, it was the gap — so we went and read the literature to find out whether the gap was real. It mostly wasn't the way we'd assumed: convergence has been documented since 1957, and the field's answer is credentialing. But credentialing presupposes an authority who has *arrived*, and FEMA's own guidance answers the 2am boat owner by saying they should have affiliated months earlier. There's an eleven-page preprint on that interval, with a real bibliography, and it says plainly that DiresQ has no users, no deployment and no evaluation. + +## What we learned + +**Tests found bugs that looked like working features.** Five of them. The backend was calling `flash()` in five places to report errors — no template rendered them, so every rejected form just sat there looking frozen. Nobody would have found that by clicking around, because the page looks *fine*. + +The report form marked its hidden latitude and longitude fields `required`. Hidden inputs are exempt from browser validation — so an untouched map submitted anyway and the report saved with no coordinates, invisible on the map, forever. + +**A safety check that fails silently is worse than no check.** Our CI greps for hardcoded secrets. The pattern needed both quote characters, and escaping that inside a YAML block scalar produced an unterminated string. The job went red having searched nothing. We rewrote it in Python and tested it against a deliberately broken file, to prove it still catches a real one. + +This turned out to be the project's actual theme. The dead man's switch started life as a background timer inside the app, and we deleted it for the same reason: a timer that dies takes the alarm with it and leaves the screen showing green, and a green screen reads as a positive result rather than an absent one. The check now runs whenever anybody loads the board, and the board displays how long since it last ran. + +**Test on a database that already has something in it.** A table added late to our schema got its `CREATE` and not its `DROP`, so rebuilding an *existing* database stopped halfway and left it in pieces. Every test passed, because tests build from empty and empty is the one case that works. + +**Measure the clever version before you keep it.** We learned this twice — once on equipment detection, where five binary classifiers confidently demanded a chainsaw for a downed power line, and once on priority, hidden behind a 100% accuracy figure measured on the training data. + +## What's next for DiresQ + +**The radio.** A check-in already packs into 22 signed bytes — small enough for a LoRa payload — and there's a gateway script that forwards them to the API. What's missing is hardware. That's a purchase and a weekend, not a rewrite. + +**Five conversations.** The one thing that would move this from a plausible design to a tested one is talking to people who have run a volunteer reception centre, or turned volunteers away, or gone in unaffiliated themselves. That would tell us whether the interval we designed for is a real operational gap or an artefact of how we read the literature. + +**Real data.** 55 training examples is a demonstration, not a dataset. Real deployment needs thousands of real reports, and real reports contain names and addresses, which is its own problem. + +**The things we've written down rather than hidden.** There's a `/limits` page in the app, with eighteen of them. No identity verification — anyone can register as a responder. Location is self-reported; we detect inconsistency, not intent. The overdue timer measures contact, not safety: a dead battery flags identically to a flooded basement. + +And it has never been used in a real disaster. Everything here is reasoned from published accounts of Harvey, Kathmandu and Mexico City, and from published triage protocol. We think the reasoning is sound. That is not the same as knowing it works. diff --git a/docs/devpost.md b/docs/devpost.md index 05abaff..0a69193 100644 --- a/docs/devpost.md +++ b/docs/devpost.md @@ -97,7 +97,7 @@ The fix was a lexicon of the categories a triage protocol calls immediate, writt It still gets one report in four wrong. That's survivable because it lands in a dropdown you control, next to the words that caused it — and it would be unacceptable if it were deciding anything. -**551 tests**, including 31 adversarial ones, a WCAG 2.1 AA audit, and a suite that reads our own documentation and fails the build when the numbers in it go stale. +**600 tests**, including 31 adversarial ones, a WCAG 2.1 AA audit, and a suite that reads our own documentation and fails the build when the numbers in it go stale. ## What we learned @@ -147,7 +147,7 @@ github-actions, ruff, wcag, start-triage, ics-214 ## Development tools -Sublime Text 4, Git and GitHub, GitHub Actions for CI, pytest (551 tests), +Sublime Text 4, Git and GitHub, GitHub Actions for CI, pytest (600 tests), ruff, bandit, pip-audit, gitleaks, Leaflet and OpenStreetMap, Astro for the documentation site, Adobe Premiere Pro for the demo video, Discord for team coordination. diff --git a/docs/filming.md b/docs/filming.md new file mode 100644 index 0000000..ff0761a --- /dev/null +++ b/docs/filming.md @@ -0,0 +1,97 @@ +# Filming the mechanism + +DiresQ's central claim is that a report files itself about a responder who has +gone quiet. On a real clock that takes forty-five minutes and nothing visible +happens for forty-four of them. `DIRESQ_DEMO_SPEED` scales the clock so the +whole sequence plays out on camera, using the production escalation code +unchanged. + +## Run it + +```bash +export DIRESQ_DEMO_SPEED=60 # 1 real second = 1 incident minute +flask --app app init-db +flask --app app seed +flask --app app run +``` + +Open `/board`, signed in as `londo` / `diresq`. The banner turns itself on and +states the speed — that is deliberate and should stay in frame. A page showing +accelerated time has to say so, for the same reason the board shows how long +since the last sweep. + +## What happens, and when + +The clock starts when the **server process** starts, not when you seed. Seed +and film in the same sitting or the numbers will have run away from you. + +At 60×, counting from page load: + +| Real time | On screen | +| --- | --- | +| 0s | `n.farrow` — *due in 5 min*, EN ROUTE | +| ~5s | farrow's row turns **red**, OVERDUE | +| ~9s | `h.lindqvist` follows, then adeyemi, skythe | +| **~20s** | **"No contact from n.farrow for 20 minutes" appears in the feed** | + +That last row is the shot. Nobody clicked anything. + +`s.reyes` is already red at seed and escalates on the first sweep — that is the +"before" state, not a bug. It is what a board looks like when the thing has +already happened to somebody. + +## Choosing a speed + +Two numbers set the pacing, both in `app.py`: + +- `DEFAULT_CHECKIN_MINUTES = 30` and the seeded ETA put farrow's deadline + **5 incident-minutes** after load +- `SILENT_ESCALATE_MINUTES = 15` is the silence the server waits out + +So at speed *S*: **red at 300/S seconds, report at 1200/S seconds.** + +| Speed | To red | To the auto-report | Use | +| --- | --- | --- | --- | +| 30 | 10s | 40s | a slow, legible walkthrough | +| **60** | **5s** | **20s** | **the default; fits a 90-second video** | +| 120 | 2.5s | 10s | a tight cut, countdown barely readable | +| 180 | 1.7s | 6.7s | too fast to watch — the board polls every 3s | + +Above ~120 the three-second board refresh becomes the limit: the countdown +jumps by more than it counts down, which looks broken rather than fast. + +## The shot list + +1. **Cold open on the red board.** No titles, no "hi we're team DiresQ". First + frame is a board with a red row. +2. Voiceover over that frame — the Harvey dispatcher, from Smith et al. (2018): + *"can we account for everyone."* +3. Cut back to a fresh load. `n.farrow`, EN ROUTE, *due in 5 min*, counting. +4. Hold. Let it turn red on camera. Do not cut away. +5. Hold again. The feed gains a report titled **"No contact from n.farrow for + 20 minutes"**, pinned at their last check-in. +6. Only now, thirty seconds of what's underneath: offline queue, signed radio + packets, 591 tests. + +Steps 3–5 are the product. Everything before is framing and everything after is +evidence. + +## Before you record + +- [ ] `DIRESQ_DEMO_SPEED` is set **in the shell that runs the server**, not the + one that seeds — it is read once at import +- [ ] re-seed immediately before recording (`init-db` then `seed`) +- [ ] the banner is visible in frame at least once +- [ ] window is wide enough that the countdown and the feed are both on screen, + so the causal link is visible in one shot rather than assembled in the cut + +## Never set this in production + +`DIRESQ_DEMO_SPEED` must be unset or `1` anywhere real. At any other value every +deadline, escalation and elapsed-time display in the app is wrong by that +factor. The default is 1, an unparseable value falls back to 1, and `0` is +rejected because it would stop time. + +Login lockout and the ICS-214 export filename deliberately stay on the real +clock — the first is a security control, the second names a file on somebody's +disk. diff --git a/docs/limits.md b/docs/limits.md index f439961..3cdb8d2 100644 --- a/docs/limits.md +++ b/docs/limits.md @@ -233,6 +233,24 @@ around the defect you just found will keep passing when the same defect appears somewhere the test does not list.** Both are now written against the rule instead — every control on every page, every colour in every stylesheet. +**Screen reader users do not get the countdown.** The board shows every +responder's time to their next check-in, falling to zero and then going +negative. That number is `aria-hidden`, so a screen reader never reads it. + +This is deliberate and it is still a loss. The responder list is a polite live +region replaced wholesale every three seconds; a value that changes on every +repaint queues announcements faster than they can be spoken, and the thing +being buried would be the state badge changing to OVERDUE — the one event on +the page worth interrupting for. We chose the badge over the countdown. + +What a screen reader user gets instead is the badge and *"last contact 47 min +ago"*, which is the same information stated backwards: elapsed rather than +remaining. That is not equivalent. Knowing somebody is due in four minutes is +a different thing from knowing they were last heard from twenty-six minutes +ago, and only one of them tells you to wait. The honest fix is a second, +non-live element that states the deadline once and does not tick, and it is +not written. + What has **not** happened is a person using a screen reader on it. Automated checks catch roughly a third of real accessibility problems, and the third they catch is the easy third. The map in particular is a Leaflet canvas with diff --git a/paper/README.md b/paper/README.md new file mode 100644 index 0000000..f630ba5 --- /dev/null +++ b/paper/README.md @@ -0,0 +1,137 @@ +# DiresQ paper — build bundle + +Upload the whole folder to Overleaf (New Project -> Upload Project -> zip). + + arxiv.tex preprint build (SocArXiv). Set this as the main document. + workshop.tex stub for a conference/workshop build; swap in the venue's + class file when the CfP publishes one + content.tex the paper body. Venue-neutral. Edit prose HERE only. + references.bib 11 entries, 10 of them cited (see note 1) + figures/ empty; see figures/README.md for the one figure worth adding + +`content.tex` is included by both wrappers, so the text has one source of truth +and changing venue does not mean copying the paper. + +## Read before submitting + +This bundle is a **draft**. Four things are outstanding; another was fixed on +4 August 2026 and is recorded below so the change is visible. + +**Verified to build.** pdfLaTeX + BibTeX + pdfLaTeX x2 completes with no errors, +no BibTeX warnings, and no undefined references. 11 pages. + +## 1. Citations — DONE (4 Aug 2026) + +The prose used to name sources in text without any `\cite{}`, so BibTeX produced +an empty References section. That is fixed. Both wrappers now load +`natbib` with `\bibliographystyle{plainnat}`, and the named mentions in +`content.tex` are `\citet{}` / `\citep{}` commands, so "Fritz and Mathewson +(1957)" is now generated from the .bib and cannot drift from it. + +Ten entries are cited and appear in the References list: + + fritz1957 kendra2002 kendra2003* starbird2011 + smith2018 fema_msv liu2014 auferbauer2017 + kankanamge2019 zhou2022 + +`*` via `\nocite`, because the prose says it is listed for completeness. + +**`baker2019` is in the .bib but is not cited anywhere**, so it does not appear +in the References. It was intended for Section 5 and the assembled text does not +use it. Cite it or delete the entry — an uncited entry is invisible, which means +nobody will notice it is wrong. + +Two smaller fixes made at the same time: + +- **The abstract was printing twice.** It was in both `arxiv.tex` and + `content.tex`, which compiles without error. The abstract and keywords now + live only in the wrappers, where they belong — venue classes disagree about + where the abstract goes, which is the reason for the wrapper split. +- **`fema_msv` has `year = {n.d.}`.** The participant materials carry no + publication date and a guessed year is worse than none. Pin it down before + final submission. It cites as "FEMA's guidance ... (n.d.)". + +If the venue supplies a class file, use theirs instead of `article` — and check +whether it already loads a citation package, since loading `natbib` twice will +error. + +## 2. Author block (added 4 Aug 2026) + +London's affiliation, email and ORCID are on the title page. Jesslyn is listed +as an author with no affiliation, by her choice. + +The title block is built by hand rather than with `authblk`. `authblk` was tried +first and is wrong for this paper: given an author with no affiliation marker it +silently attaches them to the previous `\affil`, which put Jesslyn at Cal Poly. +If a venue class requires `authblk`, give every author an explicit marker. + +**Section 6 says "two secondary-school students."** The title page now claims a +university affiliation. Those two statements cannot both be right, and +SocArXiv's red-flag list includes "enterprise misrepresentation (e.g., false or +misleading description of the research project)." Fix one of them: + +- if the work was done in secondary school and London has since started at Cal + Poly, say that — e.g. "this work was carried out while the authors were + secondary-school students"; it is accurate and it is not a weakness +- if that sentence is simply out of date, rewrite it + +The sentence is `content.tex`, in Section 6, last paragraph. + +## 3. Kendra & Wachtendorf — cite 2002, not 2003 + +Every quotation attributed to them was read in **Preliminary Paper 316 (2002)** +(`kendra2002`), not the 2003 book chapter (`kendra2003`), which is paywalled and +unread. Both are in the .bib. **Quote `kendra2002`.** `kendra2003` is there so a +reader can find the published version, and its `note` field says so. + +## 4. Three sources cited from abstracts only + +`liu2014`, `auferbauer2017`, `kankanamge2019` — each cited only for a position +its abstract states outright, never for a finding. **A Cal Poly login very +likely clears all three**: Springer (Liu), the ACM Digital Library (Auferbauer) +and Elsevier/ScienceDirect (Kankanamge, Zhou) are standard university +subscriptions. Try the library proxy before anything else. `kankanamge2019` is a +systematic review in this exact area; if a competing system exists, that is +where it would be named. + +`zhou2022` is Bronze open access — free to read at the DOI. The F1 and corpus +figures were removed from the text because they could not be verified; put them +back if you read it, they are more persuasive than the prose. + +## 5. Statement on the use of generative AI + +`content.tex` ends with two versions before the bibliography. **Use one, delete +the other.** + +**Version A** is accurate for the text as it stands: the prose was drafted by a +model and appears substantially as generated. + +**Version B** becomes accurate once you have rewritten the prose yourselves. It +describes literature search, retrieval and organisation — which is what +SocArXiv's AI Policy (8 March 2026) explicitly permits, provided it is disclosed +and the authors attest to verifying sources. + +**Why this matters for SocArXiv specifically.** Their policy lists as +unacceptable: *"generating text which is used verbatim (including whole +paragraphs and sections)."* Version A describes exactly that. It is provided so +the statement is honest, not because it will pass moderation. The policy also +says *"failure to disclose, or implausible disclosures, are grounds for +rejection"* — so an understated version is worse than either. + +The route to a paper SocArXiv will accept runs through rewriting the prose. The +research, argument, sources and design are already yours; the sentences are not. + +**Also required by SocArXiv:** the submitting author needs a publicly viewable +**ORCID** linked from their OSF profile, with a name matching the paper. Free, +a few minutes, at orcid.org. + +--- + +## Building + +Set `arxiv.tex` as the main document in Overleaf's menu. Compile with pdfLaTeX. +Overleaf runs BibTeX automatically; from a terminal the sequence is +`pdflatex` -> `bibtex` -> `pdflatex` -> `pdflatex`. + +Converted from `PAPER.md` via pandoc; section drafts in `research/` remain +authoritative. diff --git a/paper/arxiv.tex b/paper/arxiv.tex new file mode 100644 index 0000000..004625b --- /dev/null +++ b/paper/arxiv.tex @@ -0,0 +1,64 @@ +% Preprint build (SocArXiv / general). Compile: pdfLaTeX + BibTeX + pdfLaTeX x2. +\documentclass[11pt,a4paper]{article} +\usepackage[margin=1in]{geometry} +\usepackage[utf8]{inputenc} +\usepackage[T1]{fontenc} +\usepackage[english]{babel} +\usepackage{lmodern} +\usepackage{microtype} +\usepackage{csquotes} +\usepackage{parskip} +\usepackage[round,authoryear]{natbib} +\usepackage[hidelinks]{hyperref} +\usepackage{graphicx} +\graphicspath{{figures/}} + +% pandoc emits \tightlist for compact lists +\providecommand{\tightlist}{% + \setlength{\itemsep}{0pt}\setlength{\parskip}{0pt}} + +\title{``Can We Account for Everyone?''\\[0.3em] + \large Silence-Triggered Escalation for Volunteers Who Self-Deploy} +\author{London Chowdhury\\[0.35em] +\normalsize General Engineering Program, College of Engineering\\ +\normalsize California Polytechnic State University, San Luis Obispo\\ +\small\texttt{lchowdhu@calpoly.edu} \quad +ORCID \href{https://orcid.org/0009-0006-2895-2857}{0009-0006-2895-2857} +\and +Jesslyn Caroline\\[0.35em] +\small\texttt{skythe761@gmail.com}} +\date{\today} + +\begin{document} +\maketitle + +\begin{abstract} +Convergence, the spontaneous movement of people toward a disaster, has +been documented since Fritz and Mathewson (1957). Practice manages +converging volunteers through credentialing: reception centres, badge +systems, and pre-disaster affiliation. Each presupposes an institution +that has either already arrived or reached the volunteer months +beforehand. In the interval before either holds, people are already +going in, and no accountability mechanism covers them. Interviewing +Hurricane Harvey rescuers, Smith et al. (2018) record a dispatcher +asking whether ``we {[}can{]} account for everyone.'' + +We report the design of DiresQ, an open-source system attempting +accountability for unaffiliated volunteers with no coordinator. It +escalates on silence rather than supervision: a responder states an +expected arrival time and checks in periodically, and if they stop, the +system files a report about them without anyone deciding to. + +DiresQ has no users, no field deployment, and no evaluation. We +contribute a design rationale, five design trade-offs stated with their +costs, and five failure modes encountered during construction. +\end{abstract} + +\textbf{Keywords:} crisis informatics; spontaneous volunteers; convergence; +unaffiliated volunteers; accountability; self-deployment; offline-first design + +\input{content} + +\bibliographystyle{plainnat} +\bibliography{references} +\end{document} diff --git a/paper/content.tex b/paper/content.tex new file mode 100644 index 0000000..e683b10 --- /dev/null +++ b/paper/content.tex @@ -0,0 +1,692 @@ +% Venue-neutral body. Included by arxiv.tex / workshop.tex. +% Do not put \documentclass, packages, title or bibliography here. +% The abstract and keywords live in the wrapper (arxiv.tex / workshop.tex), +% not here: every venue formats them differently and some classes require +% them before \maketitle. They were duplicated in both places until 2026-08-04, +% which compiled without error and printed the abstract twice. + +\section{Introduction} + +When a disaster is large enough, people go toward it. This is among the +oldest findings in disaster sociology. \citet{fritz1957} named it --- \emph{``the informal, spontaneous movement of people, messages, +and supplies toward the disaster area''} --- and catalogued five kinds +of person who arrive: the returnees, the anxious, the helpers, the +curious, and the exploiters. Their report is subtitled \emph{A Problem +in Social Control}, and the observation it opens with has not dated: +convergence \emph{``brings needed aid to many victims, but at the same +time the resultant congestion makes organization and control of the +rescue and relief efforts more difficult.''} \citet{kendra2002}, studying the response to the World Trade Center attack, added a +sixth and reframed the central question. Access to what they call the +\emph{response milieu} is not granted; it is negotiated. A volunteer's +admission depends on whether the people already inside can afford them. + +The mechanism the field has developed for that negotiation is +\textbf{credentialing}. Volunteer reception centres, badge systems, +affiliation with a recognised organisation: these convert an unknown +arrival into an accountable one. They work. At the World Trade Center, +identification requirements \emph{``evolved and intensified on almost a +twice-daily basis''} as the response matured. + +Practitioner doctrine is more explicit still, and defines our population +for us. \citeauthor{fema_msv}'s guidance on managing spontaneous volunteers \citeyearpar{fema_msv} describes +unaffiliated volunteers as those who are \emph{``no part of a recognized +voluntary agency''}, who \emph{``often have no formal training in +emergency response''}, and who --- the phrase is theirs --- are +\emph{``not officially invited to become involved.''} It adopts the +academic taxonomy directly, noting that \emph{``researchers have +identified six different groups of people that tend to converge''}, and +identifies the operational task: \emph{``the helpers must be identified +from among the larger population of convergent individuals.''} + +The doctrine offers two mechanisms for doing that identification, and +both presuppose an institution. The first is the Volunteer Reception +Centre, which processes arrivals --- and must therefore have been +established. The second, and the one the guidance treats as primary, is +prevention: + +\begin{quote} +``Turn spontaneous unaffiliated volunteers into affiliated ones +\textbf{before a disaster occurs.} People who make a pre-disaster +decision to become disaster volunteers and take training to prepare +themselves will NOT become spontaneous, unaffiliated volunteers after a +disaster.'' +\end{quote} + +The same materials pose, as a training exercise, the question of how a +community can \emph{``keep your community members from +self-deploying''}, and describe organised national service volunteers +approvingly as members who \emph{``never self-deploy, but wait to be +called.''} + +We take this seriously rather than dismissively: pre-affiliation plainly +works, and a trained volunteer who arrives when called is better for +everyone than one who does not. But both mechanisms require an +institution --- one that reached the volunteer months beforehand, or one +that has arrived and opened a reception centre. Neither covers the +person who decides at two in the morning, on the night, that they have a +boat. Doctrine's answer to that person is that they should not exist. +They do exist, in thousands, and the events that produce them are the +events where the institution is least able to arrive. + +\citet{kendra2002} state the resulting tension directly, summarising +Weick and Perrow on decentralised coordination: effective +decentralisation presupposes prior socialisation into an organisation's +norms, \emph{``yet the volunteers who appear to assist in the emergency +response are, virtually by definition, strangers to the response +milieu.''} The literature names the problem and, so far as we have +found, proposes no mechanism for the interval before command exists. + +Hurricane Harvey makes the interval concrete. In August 2017 flooding in +the Greater Houston area affected an estimated 30,000--40,000 homes, and +city officials and FEMA publicly asked citizens with boats to help reach +people trapped inside them \citep{smith2018}. Thousands came. They +organised through Zello, a push-to-talk application, along with Facebook +groups, NextDoor, ad hoc Google spreadsheets, and applications written +during the event itself. Interviewing twenty of these volunteers, Smith +et al.~found at least twenty distinct groups with, between them, +\emph{``no way to seamlessly share information and coordinate +activity.''} Affiliation was nominal: membership of the loose ``Cajun +Navy'' was \emph{``fleeting''}, leadership \emph{``fluid and +dispersed''}, boundaries unclear. + +What went wrong is documented in the volunteers' own words. One +dispatcher described the coordination problem exactly: + +\begin{quote} +``it became overwhelming just trying to keep track of who was going out +who was coming back who was out on a boat, \textbf{can we account for +everyone}, and who's in their house and it was a mess.'' --- Gary, in +\citet{smith2018} +\end{quote} + +The gap this paper addresses is not one we inferred. It was stated by a +person who was in it. + +\citeauthor{smith2018} name three coordination failures --- incomplete feedback +loops, unclear prioritisation, and communication overload --- and close +by calling for \emph{``the design of intuitive systems that can quickly +be mastered by the novice social media user.''} This paper is an attempt +at one narrow part of that. + +Two details from that study bear directly on the design that follows. +First, the accountability function was being performed --- badly --- by +\emph{families}: rescuers reported phones ``constantly blowing up'' with +relatives asking \emph{``are you okay, are you okay, are you okay.''} +Somebody was always going to ask the question; the question simply had +nowhere to be answered. Second, volunteers' phones were destroyed by +rain and floodwater in numbers large enough that many replaced them +afterwards --- which is direct evidence that silence and danger are +genuinely different things, and that any system escalating on silence +will produce false alarms. + +This paper reports the design of \textbf{DiresQ}, a system that attempts +accountability for such volunteers without a coordinator. Its central +move is to escalate on \textbf{silence} rather than on supervision: a +responder states an expected arrival time and checks in periodically, +and if they stop, the system files a report about them automatically. +Nobody has to notice. + +We are explicit about what this paper is not. DiresQ has never been used +in a real disaster. It has no users, no deployment beyond a public +demonstration instance, and no evaluation. We report a design, the +reasoning behind five specific trade-offs, and the failure modes we +encountered building it --- several of which we consider more +transferable than the system itself. Readers looking for evidence that +this approach works will not find it here, and we would regard any such +reading as a misuse of the paper. + +\section{Background and related work} + +\subsection{Convergence} + +People moving toward a disaster is one of the field's oldest documented +behaviours. \citet{fritz1957} named it \emph{convergence +behavior} --- \emph{``the informal, spontaneous movement of people, +messages, and supplies toward the disaster area''} --- and observed that +it \emph{``brings needed aid to many victims, but at the same time the +resultant congestion makes organization and control of the rescue and +relief efforts more difficult.''} They separate movement \emph{``toward +the struck area from the outside --- external convergence''} from +\emph{``movement toward specific points within a given disaster-related +area or zone --- internal convergence''}, distinguish three forms +(personal, informational, materiel), and catalogue five types of +personal converger: the returnees, the anxious, the helpers, the +curious, and the exploiters. + +It is worth noting that the founding treatment frames convergence as a +control problem --- its subtitle is \emph{A Problem in Social Control} +--- and that this framing has been remarkably durable. The paper's own +position is stated in §5. + +\citet{kendra2002}, studying the response to the World Trade +Center attack across more than 750 collective hours of field +observation, added a sixth --- supporters or fans --- and, more +importantly for us, reframed the question. Access to what they term the +\emph{response milieu} is not a status a volunteer holds but one they +negotiate. + +The taxonomy has passed into practice. \citeauthor{fema_msv}'s guidance \citeyearpar{fema_msv} on managing +spontaneous volunteers reproduces it directly, noting that +\emph{``researchers have identified six different groups of people that +tend to converge''}, and derives an operational task from it: +\emph{``the helpers must be identified from among the larger population +of convergent individuals.''} Theory and doctrine here are a single +lineage rather than two literatures, which is why we cite them together. + +DiresQ's users are helpers, converging externally and then internally. + +\subsection{Legitimacy, credentialing, and what both presuppose} + +\citeauthor{kendra2002}'s \citeyearpar{kendra2002} central finding concerns who gets in. (We cite +their Disaster Research Center preliminary paper throughout, because it +is the text we read; the 2003 book chapter develops the same fieldwork +and is listed in the references for completeness \nocite{kendra2003}.) At the World Trade +Center, identification requirements \emph{``evolved and intensified on +almost a twice-daily basis''}, and volunteers became \emph{``another +group that needed to be accounted for, and therefore potentially a +distraction that outweighed their utility.''} The volunteers who +succeeded in gaining access were those who \emph{``were able to work +with minimal supervision by official emergency workers''} --- whose +incorporation \emph{``required little or no effort on the part of +emergency managers.''} + +We take the scarce resource in that account to be emergency-manager +attention, and it is the frame we design against: a volunteer who +accounts for themselves spends none of it. + +Doctrine's mechanisms for conferring legitimacy are the Volunteer +Reception Centre and, prior to any event, pre-affiliation --- +\emph{``turn spontaneous unaffiliated volunteers into affiliated ones +before a disaster occurs.''} Both presuppose an institution: one that +has arrived and opened a centre, or one that reached the volunteer +months earlier. We develop the consequence in §1 and do not repeat it +here. + +\subsection{Digital volunteers, and why they need no accounting for} + +\citet{starbird2011} provide the foundational study of volunteers +self-organising through technology after a disaster, examining 292,928 +tweets and interviewing nineteen of the ``voluntweeters'' who emerged +after the 2010 Haiti earthquake. They read the phenomenon through Kreps +and Bosworth's structural theory, finding a resource → activity → task → +domain progression in which the \emph{resource} --- Twitter, and the +individual capacities it made usable --- is what lets a stranger begin. + +The distinction that matters for this paper is one their scope makes for +us: their volunteers are remote by definition. The population is people +helping from other continents. No participant is in the hazard, so no +participant needs accounting for, and no mechanism for doing so appears +in the paper. This is not a gap in their work. It is the boundary of +ours. + +Our question is what changes when that same self-organising sequence +runs among people who are physically inside the hazard. Accountability +stops being optional and there is still nobody to provide it. + +\subsection{Citizen-led response in practice} + +\citet{smith2018} interviewed twenty participants in the citizen-led +rescues during Hurricane Harvey and found three roles --- rescuer, +dispatcher, information compiler --- distributed across at least twenty +distinct groups with \emph{``no way to seamlessly share information and +coordinate activity.''} They report three coordination failures: +incomplete feedback loops, unclear prioritisation, and communication +overload. + +Incomplete feedback loops is our problem under another name. Their +account of it is mechanical rather than motivational: rescue platforms +depended on someone manually marking a case closed, and in practice the +case number was forgotten, the phone was destroyed, or a different boat +reached the address first. The loop stayed open not because anyone +neglected it but because closing it required an action at exactly the +moment nobody had attention to spare. + +We note two of their findings as constraints on our design rather than +support for it. First, their participants wanted \emph{more} +coordination: one dispatcher argued that \emph{``people that are trained +to do that need to be in charge of prioritizing calls and assigning.''} +Second, over-convergence was itself a failure mode --- boats were turned +away from neighbourhoods that already had too many. We return to both in +§5. + +\subsection{Systems for crisis crowdsourcing} + +\citet{liu2014} offers the field's most developed design framework, +organising a crowdsourcing system around why / who / what / when / where +/ how, and around the social, technological, organisational and policy +interfaces that manage the articulation work of coordinating across +them. We note that two of those four interfaces presuppose an +organisation conducting the effort, and that the trajectory the +framework describes runs toward formalisation and integration +\emph{``into official products and services.''} Our position is upstream +of that trajectory rather than opposed to it. + +\citet{auferbauer2017} describe \emph{crowdtasking}, presented +explicitly as \emph{``a centralized form of crowdsourcing for crisis and +disaster management''}, with a prototype and a first field trial. It is +the clearest statement of the opposite design position to ours, and we +cite it as such: where crowdtasking assumes an organisation able to task +a registered crowd, we assume neither the organisation nor the +registration. + +\citet{kankanamge2019} provide a systematic review of volunteer +crowdsourcing in disaster risk reduction. We have not obtained the full +text and therefore make no claim about its findings; it is listed here +because a reader working in this area will expect to see it and should +know we are aware of it. + +Technical work on the classification side is considerably more advanced +than ours. \citet{zhou2022} fine-tune BERT variants over a +hand-labelled corpus of Hurricane Harvey tweets to identify rescue +requests, and substantially outperform the earlier baselines they +compare against. Our own priority suggestion (§3.3) is a naive Bayes +classifier over a small hand-labelled corpus, and is not competitive +with this work, nor intended to be: it exists to run in a browser with +no network, which is a different constraint rather than a weaker attempt +at the same one. + +\subsection{Where this leaves the gap} + +Convergence is thoroughly theorised. Legitimacy is theorised and +operationalised. Digital volunteering is well studied among remote +participants. Crowdsourcing systems have a design framework and at least +one field-trialled centralised implementation. Classification of rescue +requests is a mature technical problem. + +What we have not found, in the literature or the doctrine, is a +mechanism for accounting for physically converging helpers during the +interval before an institution exists to do it. Doctrine's answer is +that those people should have been affiliated beforehand. The academic +literature describes their arrival as a management problem. Neither +addresses the person already in the water. + +That interval is this paper's subject, and the design in §3 is one +attempt at it. + +\section{Design} + +DiresQ is a server-rendered web application: Flask, SQLite, no client +framework, no account approval step, and no dispatcher role. +Thirty-three routes over six tables. The stack is deliberately +unremarkable, and we describe it only to establish that nothing in what +follows depends on infrastructure a volunteer organisation would not +already have. The contribution is not the stack. + +Anyone can sign up. There is no verification of identity, no vetting, +and no administrator who admits people. This is not an oversight we +intend to fix; it is the condition the system is designed for. A tool +that requires somebody to approve you has reintroduced the coordinator +whose absence is the entire problem. + +\subsection{The mechanism} + +A report is a place that needs help. A responder who decides to go there +joins the report and, in doing so, states an expected time of arrival. +The ETA is bounded between five and 240 minutes and warns above 120 --- +not because longer journeys are invalid, but because an unbounded ETA +makes the subsequent arithmetic meaningless. From that point the +responder is expected to check in; the interval defaults to thirty +minutes. + +If a responder stops checking in, they are marked overdue. Fifteen +minutes past that threshold, the system files a report \emph{about them} +--- their last known location becomes an incident in the same feed +everyone else is reading. No human decides this. No human is asked to +notice. + +This is the whole mechanism, and its only novel property is what +triggers it. Existing accountability systems escalate when a coordinator +observes that somebody has not reported in. We escalate on the +observation itself being absent. Silence is available in circumstances +where a supervisor is not. + +\subsection{Five decisions, and what each one cost} + +The design is small enough that the interesting content is not the +architecture but the trade-offs. We describe five, each of which we got +wrong first. + +\textbf{Silence as the trigger.} The alternative designs all require +somebody to be watching: a dispatcher view, an alert queue, a supervisor +role. Each of them works, and each of them assumes the thing we cannot +assume. Escalating on absence needs nobody. The cost is that absence is +ambiguous --- a responder who has stopped answering may be in trouble, +or may have a dead phone, or may have gone home without saying so. The +system cannot tell these apart and does not claim to. It reports +\emph{contact lost}, never \emph{safe} or \emph{unsafe}, and the +interface language was rewritten twice to stop implying otherwise. + +\textbf{No in-process timer.} Our first design ran the silence check on +a background thread inside the application. We removed it. A thread that +dies takes the alarm with it and leaves the interface showing green, and +a green screen is read as a positive result rather than an absent one. +The check now runs on read: whenever anyone loads the accountability +board, the sweep runs first, rate-limited to once every thirty seconds. +An \emph{external} scheduler is supported and optional +(\texttt{flask\ -\/-app\ app\ sweep} from cron or Task Scheduler) --- +deliberately external, because an external scheduler that fails is at +least visible to the machine running it, which an in-process timer is +not. + +This trades one dependency for another. A timer that might die becomes a +check that depends on being watched. We consider that the better failure +--- an unwatched board is a situation where nobody is relying on the +result --- but the substantive move is that we made the dependency +\textbf{visible} rather than documenting it. The board displays how long +since the last sweep and turns amber past five minutes. On a board +somebody is actually watching, the number always reads a few seconds, +because the watching is what runs it. A limitation you can see on screen +is a different claim from one the user has to be told about. + +\textbf{Status and contact are different facts.} What a responder last +told us is one thing; whether they are still answering is another. We +conflated them, and the result was a report page displaying ``on scene'' +for somebody the accountability board had forty-five minutes overdue. +Anyone opening that report to decide whether the address needed more +help was counting a person who had gone silent as help present. Both +facts are now shown, and neither is inferred from the other. Somebody +who has explicitly cleared is not chased, because going home is not +going quiet. + +The general form of this: in a system whose purpose is knowing where +people are, \emph{self-reported state} and \emph{liveness} must never be +collapsed into one field, however tempting the simplification is at the +schema level. + +\textbf{Refusing to cache claims about other people.} The offline layer +keeps the things you committed to --- your own assignments, a queued +report you filed without signal --- and refuses to keep the report feed +or the accountability board. A cached feed is a list of who needed help +twenty minutes ago. Acting on it sends somebody to an address that has +been cleared, and the person reading it has no way to know the +difference between stale and current. A test fails if either page is +added to the service worker's shell list. + +The generalisable claim, and the one we would defend: +\textbf{correct-when-written and correct-when-read are different +guarantees}, and disaster data has an unusually short half-life between +them. Offline-first design literature tends to treat availability as an +unalloyed good. For a class of data it is not, and the distinction is +not about staleness tolerance but about whether a stale answer is +\emph{actionable} --- whether a user can be sent somewhere by it. + +\textbf{Not storing triage answers.} The system includes a START triage +helper that orders which reports get attention first. The answers are +health observations about a person who did not consent and is likely in +no position to. They are used to compute an ordering and then discarded; +nothing about a casualty's breathing or perfusion is written to the +database. The cost is that the ordering cannot be audited after the +fact, which is a real loss. We accepted it. + +\subsection{Priority suggestion} + +A report can be given a suggested priority by a multinomial naive Bayes +classifier over a severity lexicon, trained on a small hand-labelled +corpus and validated by leave-one-out cross-validation with a floor +asserted in continuous integration. + +We describe it in one paragraph deliberately. It is the least +interesting component and the one most likely to be mistaken for the +contribution. It suggests an ordering for human attention; it does not +predict outcomes, assess medical severity, or make any claim that +survives the person reading the report disagreeing with it. A model +small enough to ship as a frozen table of word counts is also small +enough to run in the browser, which is why priority suggestion works +with no signal while the report feed deliberately does not. + +\subsection{What the design does not attempt} + +It does not summon help. No dispatcher reads it, it does not call +emergency services, and the disclaimer on every page is load-bearing +rather than legal decoration. It does not verify that anybody is who +they say they are. It does not know where anyone actually is --- +location is self-reported throughout. It makes no claim that a responder +is safe; only that we have or have not heard from them. + +These are stated here rather than only in §5 because a reader who +reaches the limitations section still holding the wrong model of the +system has already misread the design. + +\section{What building it taught us} + +We report these as observations from construction, not as validated +findings. Each began as a specific bug or reversal and generalised +afterwards. + +\subsection{Correct-when-written and correct-when-read are different guarantees} + +The offline layer was originally designed to cache what a user would +want if their signal dropped, which is nearly everything. We now cache +almost nothing. + +The rule we arrived at: \textbf{do not store anything that stops being +true when it is written.} Your own commitments --- the assignment you +accepted, a report you filed with no signal --- remain true offline, +because they are statements about you. The report feed and the +accountability board are statements about other people, and both decay. +A cached feed is a list of who needed help twenty minutes ago; a +responder acting on it is dispatched to an address that has since been +cleared, with no way to distinguish that from a current one. + +Offline-first design generally treats availability as an unalloyed good, +with staleness managed by tolerance windows and revalidation. We think +the useful distinction is not how stale the data is but whether a stale +answer is \emph{actionable} --- whether a user can be sent somewhere by +it. Data that can move a body should not be served from cache at all. A +test fails if either page is added to the service worker's shell list, +because the rule is easy to forget and the failure is silent. + +\subsection{An alarm that dies quietly is worse than no alarm} + +The silence check was first designed as a background thread inside the +application. We removed it. A timer that dies takes the alarm with it +and leaves the interface showing green, and a green screen is read as a +positive result rather than an absent one. + +The check now runs on read --- whenever anyone loads the accountability +board, rate-limited to once every thirty seconds. An external scheduler +is supported (\texttt{flask\ -\/-app\ app\ sweep}) and deliberately +optional: an external scheduler that fails is at least visible to the +machine running it, which an in-process timer is not. + +This does not remove the dependency, it relocates it. The system now +works while somebody is looking. We regard that as the better failure +mode, because a board nobody is watching is a situation where nobody is +relying on the answer --- but the claim needs stating rather than +assuming. + +\subsection{A limitation on screen is a different claim from a limitation in a file} + +The consequence of §4.2 is that the guarantee is conditional, and our +first response was to write that down in a limitations document. That is +the standard move and we now think it is insufficient. + +The board displays how long since the last sweep --- \emph{checked 2s +ago} beside the live indicator, amber past five minutes, which is ten +minutes before the fifteen-minute escalation it drives. On a board +somebody is watching it always reads a few seconds, because the watching +is what runs it. If it stops moving, that is visible too. + +The general form: \textbf{emergency software should surface its own +liveness.} A user deciding whether to trust a screen needs to know +whether the thing behind it ran, and that is a different question from +whether the data looks reasonable. We would extend this beyond our own +system: any interface that reports on a periodic check should display +when the check last completed, not merely its result. + +\subsection{The pages built to be watched were the ones that broke under watching} + +The board, the map and the feed all run the silence check before +answering, and the check writes. SQLite's default journal mode lets one +writer lock out every reader. With several people watching a board that +refreshes every three seconds, a write could wait past its timeout and +fail the entire response. + +The pages whose purpose is to be watched continuously during an +emergency were precisely the pages that failed when watched +continuously. The fix was unremarkable --- write-ahead logging, +rate-limiting the sweep, catching the failure rather than letting it +become an error page. The lesson is not about SQLite. It is that +\textbf{making a read-only page write is a change of kind, not of +degree}, and in this system it converted the most-loaded pages into the +most fragile ones. + +One deliberate detail: a failed sweep does not record itself as having +run. The timestamp goes stale and the board reports that in amber, which +is true, because a check we could not record is not a check we can +claim. + +\subsection{Prose about a system lags the system} + +Our test suite verifies every count in our own documentation --- routes, +tables, tests, lines --- and fails when the prose and the repository +disagree. It has caught wrong numbers repeatedly, including several we +wrote ourselves. + +It has never once caught the more common error, which is a +\emph{sentence} that describes a previous version of a behaviour. Four +times a change landed and the paragraph explaining it stayed a revision +behind. Numbers are checkable and were checked; claims are not, and were +not. + +We do not have a solution and offer this as an observation: automated +documentation checks create a real assurance about the class of +statement they can verify and no assurance whatever about the class they +cannot, and the second class is where the misleading statements live. + +\section{Limitations} + +The system has eighteen documented limitations, maintained as a +first-class document rather than an appendix. We summarise the ones that +most constrain what this paper claims. + +\textbf{It has never been used in a real disaster.} Everything here is +reasoned from published accounts of Harvey, Kathmandu and Mexico City, +and from published triage protocol. None of it has been tested by +somebody standing in water at two in the morning. We believe the +reasoning is sound; that is not the same as knowing it works, and no +part of this paper should be read as evidence that it does. + +\textbf{The switch depends on being run.} Described in §4.2. Neither the +read-trigger nor an external scheduler is guaranteed. A deployment +nobody looks at and nobody configures performs no checks. + +\textbf{Overdue measures contact, not safety.} The system reports that +it has not heard from somebody. It cannot distinguish danger from a dead +battery, and it does not try. The interface language was revised twice +to stop implying otherwise, and this is the limitation most likely to be +misread by a user in a hurry. + +\textbf{No identity verification.} Anyone can register. This is a design +condition rather than a defect --- a system requiring approval has +reintroduced the coordinator whose absence is the problem --- but it +means the system cannot distinguish a responder from someone claiming to +be one. + +\textbf{Location is self-reported} throughout. The map shows where +people said they were. + +\textbf{One cautious responder can hold a report open}, which biases the +system toward over-reporting need. We prefer that direction and note +that we chose it. + +\textbf{Lockouts live in memory} and do not survive a restart. + +\textbf{The volunteers we claim to serve asked for the opposite.} Smith +et al.~(2018) interviewed twenty Harvey rescuers and dispatchers, and +the structural complaint that came back was a wish for \emph{more} +coordination, not less. One dispatcher, on being unable to prioritise +calls: \emph{``people that are trained to do that need to be in charge +of prioritizing calls and assigning.''} Another described sending boats +away because too many had converged on one neighbourhood. + +This is the strongest available argument against our design, and it +comes from the population the design is for. We do not think it defeats +the argument --- the wish for a trained coordinator does not summon one, +and the interval before one exists is exactly our subject --- but a +reader should weigh it. A system that makes self-deployment easier and +better-accounted-for may also make it more attractive, and \citeauthor{smith2018} document a response that suffered from too many boats as well as too +little information. + +\subsection{A position rather than a finding} + +The literature we build on treats converging volunteers as a population +to be managed: \citet{kendra2002} document access as negotiated +legitimacy, with credentialing, liability and security as the operative +concerns, and volunteers as a potential distraction that must outweigh +its own cost. Our design treats the volunteer as somebody owed an +accounting. + +These are different moral starting points, and the literature does not +share ours. We think ours is defensible --- a person who walks into a +hazard to help is owed something regardless of whether an institution +has authorised them --- but it is a position, not a result, and a reader +is entitled to reject it and evaluate the design on the field's own +terms instead. + +\section{Future work} + +The obvious next step is the one we have not taken: contact with people +who do this work. Five structured interviews with volunteer-response +coordinators --- people who have run a reception centre, or turned +volunteers away, or gone in unaffiliated themselves --- would test the +assumption the whole design rests on, which is that the interval before +credentialing exists is a real operational gap rather than an artefact +of how we read the literature. + +Beyond that, a simulated-event walkthrough is the tractable route to +evaluation without waiting for a disaster; the crisis informatics +community has precedent for this. It would let us observe whether the +silence mechanism produces escalations at useful times, or whether it +mostly produces false alarms from people whose phones died --- a +distinction we currently cannot make. + +Two smaller questions we would want answered. Whether the fifteen-minute +escalation delay is anywhere near right; we chose it by reasoning, not +by measurement, and it is the kind of parameter that ought to come from +data. And whether making system liveness visible on screen --- the sweep +timestamp described in §4.3 --- actually changes how much a user trusts +what they are reading, or whether it is a designer's satisfaction that +no user notices. + +We are aware that all of this describes work requiring access to a +professional community that two secondary-school students do not have. +We would welcome collaboration, and we mention it here rather than in an +acknowledgement because it is a limitation on the research, not a +courtesy. + +% --------------------------------------------------------------------------- +% STATEMENT ON THE USE OF GENERATIVE AI +% +% Two versions below. Use ONE. Delete the other. +% +% Version A is accurate for the text as it currently stands. +% Version B becomes accurate only once the authors have rewritten the prose in +% their own words. Do not use B before that is true. +% +% Note: SocArXiv's AI Policy (8 March 2026) lists "generating text which is used +% verbatim (including whole paragraphs and sections)" as an unacceptable use. +% Version A therefore describes a use that SocArXiv does not accept. It is here +% so the statement is honest, not so that it passes. +% --------------------------------------------------------------------------- + +% ---- VERSION A: accurate for the current text ---- +\section*{Statement on the use of generative AI} + +The text of this paper was drafted by a large language model (Claude, +Anthropic) from sources and an argument structure specified by the authors. +The authors set the research question, chose the sources, made every design +decision reported in Section~3, and reviewed and revised the result. Sections +of the drafted text appear substantially as generated. Three cited works +(Liu 2014; Auferbauer and Tellio\u{g}lu 2017; Kankanamge et al. 2019) are +referenced only for positions stated in their abstracts, which is noted where +they appear. + +% ---- VERSION B: use only after the authors rewrite the prose ---- +% \section*{Statement on the use of generative AI} +% +% A large language model (Claude, Anthropic) was used for literature search, +% source retrieval, and organisation of material during the preparation of this +% paper. All prose is the authors' own. The authors verified every source cited, +% including confirming that quoted passages appear in the works attributed to +% them, and made every design decision reported in Section~3. diff --git a/paper/figures/README.md b/paper/figures/README.md new file mode 100644 index 0000000..6052e46 --- /dev/null +++ b/paper/figures/README.md @@ -0,0 +1,27 @@ +# Figures + +Empty on purpose. There are no figures yet, and inventing one would be worse +than having none. + +## The one figure this paper probably needs + +A state diagram of a responder's lifecycle, because §3 describes it in prose and +prose is a bad medium for a state machine: + + joined (ETA stated, 5-240 min) + -> checked in [resets the clock, default interval 30 min] + -> overdue [interval elapsed with no check-in] + -> escalated [SILENT_ESCALATE_MINUTES = 15 after overdue; + a report is filed about them, automatically] + -> cleared [responder says they are done; not chased] + +Two things the diagram should make visible that the prose struggles with: + +1. `cleared` is reachable from any state and is *not* a failure — going home is + not going quiet. +2. Nothing on this diagram is a human decision. That is the argument of the + paper, and a reader should be able to see it in one glance. + +Draw it in TikZ (keeps the source in the repo, no binary blobs) or export a PDF +from a diagram tool and drop it here. `\graphicspath{{figures/}}` is already set +in both wrappers, so `\includegraphics{lifecycle}` will find it. diff --git a/paper/references.bib b/paper/references.bib new file mode 100644 index 0000000..2cc3bc8 --- /dev/null +++ b/paper/references.bib @@ -0,0 +1,133 @@ +@techreport{fritz1957, + author = {Fritz, Charles E. and Mathewson, John H.}, + title = {Convergence Behavior in Disasters: A Problem in Social Control}, + institution = {Committee on Disaster Studies, National Academy of Sciences -- + National Research Council}, + address = {Washington, DC}, + year = {1957}, + note = {Read via the Internet Archive: + \url{https://archive.org/details/convergencebehav00fritrich}} +} + +@techreport{kendra2002, + author = {Kendra, James M. and Wachtendorf, Tricia}, + title = {Rebel Food\ldots{} Renegade Supplies: Convergence after the + World Trade Center Attack}, + institution = {Disaster Research Center, University of Delaware}, + address = {Newark, DE}, + number = {Preliminary Paper 316}, + year = {2002}, + note = {The text quoted throughout this paper} +} + +@incollection{kendra2003, + author = {Kendra, James M. and Wachtendorf, Tricia}, + title = {Reconsidering Convergence and Converger Legitimacy in Response + to the World Trade Center Disaster}, + booktitle = {Terrorism and Disaster: New Threats, New Ideas}, + series = {Research in Social Problems and Public Policy}, + volume = {11}, + pages = {97--122}, + year = {2003}, + publisher = {Emerald Group Publishing}, + address = {Bingley, UK}, + doi = {10.1016/S0196-1152(03)11007-1}, + note = {Listed for completeness; quotations in this paper are from + Preliminary Paper 316} +} + +@inproceedings{starbird2011, + author = {Starbird, Kate and Palen, Leysia}, + title = {``Voluntweeters'': Self-Organizing by Digital Volunteers in + Times of Crisis}, + booktitle = {Proceedings of the SIGCHI Conference on Human Factors in + Computing Systems (CHI '11)}, + address = {Vancouver, BC, Canada}, + year = {2011} +} + +@inproceedings{smith2018, + author = {Smith, William Roth and Robertson, Brett W. and Murthy, Dhiraj + and Stephens, Keri K. and Li, Jing}, + title = {Social Media in Citizen-Led Disaster Response: Rescuer Roles, + Coordination Challenges, and Untapped Potential}, + booktitle = {Proceedings of the 15th ISCRAM Conference}, + address = {Rochester, NY, USA}, + pages = {639--648}, + year = {2018}, + note = {Open access via NSF-PAR 10076203} +} + +% NOTE: the participant materials carry no publication date; year = {n.d.} is +% deliberate rather than a guessed year. Pin it down before final submission. +% (BibTeX has no in-entry comment syntax -- keep notes like this ABOVE the entry.) +@manual{fema_msv, + author = {{FEMA}}, + organization = {Federal Emergency Management Agency}, + title = {Managing Spontaneous Volunteers in Times of Disaster: The + Synergy of Structure --- participant materials}, + address = {Washington, DC}, + year = {n.d.}, + note = {FEMA / Points of Light Foundation} +} + +@article{liu2014, + author = {Liu, Sophia B.}, + title = {Crisis Crowdsourcing Framework: Designing Strategic + Configurations of Crowdsourcing for the Emergency Management + Domain}, + journal = {Computer Supported Cooperative Work (CSCW)}, + volume = {23}, + number = {4--6}, + pages = {389--443}, + year = {2014}, + doi = {10.1007/s10606-014-9204-3} +} + +@inproceedings{auferbauer2017, + author = {Auferbauer, Daniel and Tellio\u{g}lu, Hilda}, + title = {Centralized Crowdsourcing in Disaster Management: Findings and + Implications}, + booktitle = {Proceedings of the 8th International Conference on Communities + and Technologies (C\&T '17)}, + address = {Troyes, France}, + pages = {173--182}, + publisher = {ACM Press}, + year = {2017}, + doi = {10.1145/3083671.3083689} +} + +@article{kankanamge2019, + author = {Kankanamge, Nayomi and Yigitcanlar, Tan and Goonetilleke, + Ashantha and Kamruzzaman, Md.}, + title = {Can volunteer crowdsourcing reduce disaster risk? A systematic + review of the literature}, + journal = {International Journal of Disaster Risk Reduction}, + volume = {35}, + pages = {101097}, + year = {2019}, + doi = {10.1016/j.ijdrr.2019.101097} +} + +@article{zhou2022, + author = {Zhou, Bing and Zou, Lei and Mostafavi, Ali and Lin, Binbin and + Yang, Mingzheng and Gharaibeh, Nasir and Cai, Heng and Abedin, + Joynal and Mandal, Debayan}, + title = {VictimFinder: Harvesting rescue requests in disaster response + from social media with BERT}, + journal = {Computers, Environment and Urban Systems}, + volume = {95}, + pages = {101824}, + year = {2022}, + doi = {10.1016/j.compenvurbsys.2022.101824} +} + +@article{baker2019, + author = {Baker, Natalie D. and Deham, Magdalena}, + title = {For a short time, we were the best version of ourselves: + Hurricane Harvey and the ideal of community}, + journal = {International Journal of Emergency Services}, + year = {2019}, + doi = {10.1108/IJES-12-2018-0066}, + note = {Open access via NSF-PAR 10126439} +} diff --git a/paper/workshop.tex b/paper/workshop.tex new file mode 100644 index 0000000..b6b2848 --- /dev/null +++ b/paper/workshop.tex @@ -0,0 +1,68 @@ +% Workshop / conference build. +% +% STUB. Replace \documentclass and the preamble with the venue's own class file +% when the CfP publishes one (ISCRAM, CHI, CSCW all supply templates). The point +% of this file is that content.tex does not change when the venue does. +% +% Likely differences from arxiv.tex: two-column layout, a hard page limit, an +% ACM/IEEE reference style, and anonymisation for review. +\documentclass[11pt,a4paper]{article} +\usepackage[margin=1in]{geometry} +\usepackage[utf8]{inputenc} +\usepackage[T1]{fontenc} +\usepackage[english]{babel} +\usepackage{lmodern} +\usepackage{microtype} +\usepackage{csquotes} +\usepackage{parskip} +\usepackage[round,authoryear]{natbib} +\usepackage[hidelinks]{hyperref} +\usepackage{graphicx} +\graphicspath{{figures/}} + +% pandoc emits \tightlist for compact lists +\providecommand{\tightlist}{% + \setlength{\itemsep}{0pt}\setlength{\parskip}{0pt}} + +\title{``Can We Account for Everyone?''\\[0.3em] + \large Silence-Triggered Escalation for Volunteers Who Self-Deploy} +\author{London Chowdhury\\[0.35em] +\normalsize General Engineering Program, College of Engineering\\ +\normalsize California Polytechnic State University, San Luis Obispo\\ +\small\texttt{lchowdhu@calpoly.edu} \quad +ORCID \href{https://orcid.org/0009-0006-2895-2857}{0009-0006-2895-2857} +\and +Jesslyn Caroline\\[0.35em] +\small\texttt{skythe761@gmail.com}} +\date{\today} + +\begin{document} +\maketitle + +\begin{abstract} +Convergence, the spontaneous movement of people toward a disaster, has +been documented since Fritz and Mathewson (1957). Practice manages +converging volunteers through credentialing: reception centres, badge +systems, and pre-disaster affiliation. Each presupposes an institution +that has either already arrived or reached the volunteer months +beforehand. In the interval before either holds, people are already +going in, and no accountability mechanism covers them. Interviewing +Hurricane Harvey rescuers, Smith et al. (2018) record a dispatcher +asking whether ``we {[}can{]} account for everyone.'' + +We report the design of DiresQ, an open-source system attempting +accountability for unaffiliated volunteers with no coordinator. It +escalates on silence rather than supervision: a responder states an +expected arrival time and checks in periodically, and if they stop, the +system files a report about them without anyone deciding to. + +DiresQ has no users, no field deployment, and no evaluation. We +contribute a design rationale, five design trade-offs stated with their +costs, and five failure modes encountered during construction. +\end{abstract} + +\input{content} + +\bibliographystyle{plainnat} +\bibliography{references} +\end{document} diff --git a/research/draft-abstract.md b/research/draft-abstract.md new file mode 100644 index 0000000..3638109 --- /dev/null +++ b/research/draft-abstract.md @@ -0,0 +1,83 @@ +# Abstract, title and keywords — first draft + +Status: **first draft, unreviewed.** Written last, as planned, so that it +describes the paper that exists rather than the one intended. + +--- + +## Title + +**Front-runner (new):** + +> **"Can We Account for Everyone?" Silence-Triggered Escalation for Volunteers +> Who Self-Deploy** + +The quoted phrase is a Hurricane Harvey dispatcher's, recorded in Smith et al. +(2018). Using it signals in the title that the problem was named by somebody who +had it, not by us, and the subtitle carries the technical content. Quotation +titles are common at ISCRAM and in CSCW generally. + +Previous candidates, retained: + +1. *Accounting for the Unaffiliated: Silence-Triggered Escalation for Volunteers + Who Self-Deploy* +2. *Nobody Is Coming to Check: Designing Volunteer Accountability Without a + Coordinator* +3. *Legible Without a Gatekeeper: A Self-Service Accountability Tool for + Converging Helpers* + +**Check before submitting:** whether the venue permits a quotation title, and +whether quoting a pseudonymous interview participant from another team's study +in our title is appropriate. It is their data. Attribute in the first footnote +if we use it, and consider emailing Smith or Stephens as a courtesy — which is +also a reason to make contact. + +--- + +## Abstract (~165 words — trim to the CfP's limit) + +> Convergence, the spontaneous movement of people toward a disaster, has been +> documented since Fritz and Mathewson (1957). Practice manages converging +> volunteers through credentialing: reception centres, badge systems, and +> pre-disaster affiliation. Each presupposes an institution that has either +> already arrived or reached the volunteer months beforehand. In the interval +> before either holds, people are already going in, and no accountability +> mechanism covers them. Interviewing Hurricane Harvey rescuers, Smith et al. +> (2018) record a dispatcher asking whether "we [can] account for everyone." +> +> We report the design of DiresQ, an open-source system attempting +> accountability for unaffiliated volunteers with no coordinator. It escalates +> on silence rather than supervision: a responder states an expected arrival +> time and checks in periodically, and if they stop, the system files a report +> about them without anyone deciding to. +> +> DiresQ has no users, no field deployment, and no evaluation. We contribute a +> design rationale, five trade-offs stated with their costs, and four failure +> modes encountered during construction. + +**Why the last paragraph is there.** Most abstracts bury the absence of +evaluation or omit it. Putting it in the abstract means a reviewer cannot feel +misled at page four, and a WiP track is the one place where saying it plainly +costs nothing. + +--- + +## Keywords + +crisis informatics; spontaneous volunteers; convergence; unaffiliated +volunteers; accountability; self-deployment; offline-first design + +*(Check the CfP — ISCRAM papers typically list 4–6.)* + +--- + +## Consistency checks before this is final + +- [ ] "five trade-offs" — §3 currently has five. Recount at assembly. +- [ ] "four failure modes" — §4 has five subsections, one marked `[CUT?]`. If + §4.5 stays, this says five. **These two numbers are the easiest thing in + the paper to get wrong**, and they are in the abstract, where they are + most visible. +- [ ] The abstract says "open-source". Confirm the licence is stated in the + paper body, not only in the repository. +- [ ] Word count against the CfP limit once published. diff --git a/research/draft-s1-s6.md b/research/draft-s1-s6.md new file mode 100644 index 0000000..0649c5f --- /dev/null +++ b/research/draft-s1-s6.md @@ -0,0 +1,178 @@ +# §1 and §6 — first draft + +Status: **first draft, unreviewed.** + +> **Harvey material is now sourced.** Every figure and quotation in §1 comes from +> Smith, Robertson, Murthy, Stephens & Li (2018), *"Social Media in Citizen-Led +> Disaster Response: Rescuer Roles, Coordination Challenges, and Untapped +> Potential"*, Proceedings of the 15th ISCRAM Conference, pp. 639–648. Open +> access via NSF-PAR 10076203. Nothing here is written from memory. +> +> Baker & Deham (2019) was the intended source and turned out to be critical +> theory with no Harvey specifics to cite. It is still useful — see §5. + +--- + +## 1. Introduction + +When a disaster is large enough, people go toward it. This is among the oldest +findings in disaster sociology. Fritz and Mathewson named it in 1957 — +*"the informal, spontaneous movement of people, messages, and supplies toward +the disaster area"* — and catalogued five kinds of person who arrive: the +returnees, the anxious, the helpers, the curious, and the exploiters. Their +report is subtitled *A Problem in Social Control*, and the observation it opens +with has not dated: convergence *"brings needed aid to many victims, but at the +same time the resultant congestion makes organization and control of the rescue +and relief efforts more difficult."* Kendra and +Wachtendorf (2002), studying the response to the World Trade Center attack, +added a sixth and reframed the central question. Access to what they call the *response +milieu* is not granted; it is negotiated. A volunteer's admission depends on +whether the people already inside can afford them. + +The mechanism the field has developed for that negotiation is **credentialing**. +Volunteer reception centres, badge systems, affiliation with a recognised +organisation: these convert an unknown arrival into an accountable one. They +work. At the World Trade Center, identification requirements *"evolved and +intensified on almost a twice-daily basis"* as the response matured. + +Practitioner doctrine is more explicit still, and defines our population for us. +FEMA's guidance on managing spontaneous volunteers describes unaffiliated +volunteers as those who are *"no part of a recognized voluntary agency"*, who +*"often have no formal training in emergency response"*, and who — the phrase is +theirs — are *"not officially invited to become involved."* It adopts the +academic taxonomy directly, noting that *"researchers have identified six +different groups of people that tend to converge"*, and identifies the +operational task: *"the helpers must be identified from among the larger +population of convergent individuals."* + +The doctrine offers two mechanisms for doing that identification, and both +presuppose an institution. The first is the Volunteer Reception Centre, which +processes arrivals — and must therefore have been established. The second, and +the one the guidance treats as primary, is prevention: + +> "Turn spontaneous unaffiliated volunteers into affiliated ones **before a +> disaster occurs.** People who make a pre-disaster decision to become disaster +> volunteers and take training to prepare themselves will NOT become +> spontaneous, unaffiliated volunteers after a disaster." + +The same materials pose, as a training exercise, the question of how a community +can *"keep your community members from self-deploying"*, and describe organised +national service volunteers approvingly as members who *"never self-deploy, but +wait to be called."* + +We take this seriously rather than dismissively: pre-affiliation plainly works, +and a trained volunteer who arrives when called is better for everyone than one +who does not. But both mechanisms require an institution — one that reached the +volunteer months beforehand, or one that has arrived and opened a reception +centre. Neither covers the person who decides at two in the morning, on the +night, that they have a boat. Doctrine's answer to that person is that they +should not exist. They do exist, in thousands, and the events that produce them +are the events where the institution is least able to arrive. + +Kendra and Wachtendorf state the resulting tension directly, summarising Weick +and Perrow on decentralised coordination: effective decentralisation presupposes +prior socialisation into an organisation's norms, *"yet the volunteers who +appear to assist in the emergency response are, virtually by definition, +strangers to the response milieu."* The literature names the problem and, so far +as we have found, proposes no mechanism for the interval before command exists. + +Hurricane Harvey makes the interval concrete. In August 2017 flooding in the +Greater Houston area affected an estimated 30,000–40,000 homes, and city +officials and FEMA publicly asked citizens with boats to help reach people +trapped inside them (Smith et al., 2018). Thousands came. They organised through +Zello, a push-to-talk application, along with Facebook groups, NextDoor, ad hoc +Google spreadsheets, and applications written during the event itself. +Interviewing twenty of these volunteers, Smith et al. found at least twenty +distinct groups with, between them, *"no way to seamlessly share information and +coordinate activity."* Affiliation was nominal: membership of the loose "Cajun +Navy" was *"fleeting"*, leadership *"fluid and dispersed"*, boundaries unclear. + +What went wrong is documented in the volunteers' own words. One dispatcher +described the coordination problem exactly: + +> "it became overwhelming just trying to keep track of who was going out who was +> coming back who was out on a boat, **can we account for everyone**, and who's +> in their house and it was a mess." — Gary, in Smith et al. (2018) + +The gap this paper addresses is not one we inferred. It was stated by a person +who was in it. + +Smith et al. name three coordination failures — incomplete feedback loops, +unclear prioritisation, and communication overload — and close by calling for +*"the design of intuitive systems that can quickly be mastered by the novice +social media user."* This paper is an attempt at one narrow part of that. + +Two details from that study bear directly on the design that follows. First, the +accountability function was being performed — badly — by *families*: rescuers +reported phones "constantly blowing up" with relatives asking *"are you okay, +are you okay, are you okay."* Somebody was always going to ask the question; the +question simply had nowhere to be answered. Second, volunteers' phones were +destroyed by rain and floodwater in numbers large enough that many replaced them +afterwards — which is direct evidence that silence and danger are genuinely +different things, and that any system escalating on silence will produce false +alarms. + +This paper reports the design of **DiresQ**, a system that attempts +accountability for such volunteers without a coordinator. Its central move is to +escalate on **silence** rather than on supervision: a responder states an +expected arrival time and checks in periodically, and if they stop, the system +files a report about them automatically. Nobody has to notice. + +We are explicit about what this paper is not. DiresQ has never been used in a +real disaster. It has no users, no deployment beyond a public demonstration +instance, and no evaluation. We report a design, the reasoning behind five +specific trade-offs, and the failure modes we encountered building it — several +of which we consider more transferable than the system itself. Readers looking +for evidence that this approach works will not find it here, and we would +regard any such reading as a misuse of the paper. + +--- + +## 6. Future work + +The obvious next step is the one we have not taken: contact with people who do +this work. Five structured interviews with volunteer-response coordinators — +people who have run a reception centre, or turned volunteers away, or gone in +unaffiliated themselves — would test the assumption the whole design rests on, +which is that the interval before credentialing exists is a real operational gap +rather than an artefact of how we read the literature. + +Beyond that, a simulated-event walkthrough is the tractable route to evaluation +without waiting for a disaster; the crisis informatics community has precedent +for this. It would let us observe whether the silence mechanism produces +escalations at useful times, or whether it mostly produces false alarms from +people whose phones died — a distinction we currently cannot make. + +Two smaller questions we would want answered. Whether the fifteen-minute +escalation delay is anywhere near right; we chose it by reasoning, not by +measurement, and it is the kind of parameter that ought to come from data. +And whether making system liveness visible on screen — the sweep timestamp +described in §4.3 — actually changes how much a user trusts what they are +reading, or whether it is a designer's satisfaction that no user notices. + +We are aware that all of this describes work requiring access to a professional +community that two secondary-school students do not have. We would welcome +collaboration, and we mention it here rather than in an acknowledgement because +it is a limitation on the research, not a courtesy. + +--- + +## Notes for revision + +- Harvey paragraph **written from Smith et al. (2018)**, ISCRAM 15, NSF-PAR + 10076203. Every figure and quotation above is from that paper. Re-verify the + 30,000–40,000 homes figure against their wording before submission — they + attribute it loosely and we should not sharpen it. +- **A complication we must not hide, for §5.** The volunteers in Smith et al. + wanted *more* structure, not less. Harriett: *"people that are trained to do + that need to be in charge of prioritizing calls and assigning."* That is an + argument against a coordinator-free design, made by the population we claim to + serve. It must appear in the limitations, stated as plainly as this, or a + reviewer who has read Smith et al. will conclude we read it selectively. +- §1 currently quotes Kendra & Wachtendorf twice. One quotation is stronger than + two; consider paraphrasing the credentialing one and keeping the Weick/Perrow + sentence verbatim, since that one is doing structural work. +- §6's last paragraph is a judgement call. It is honest and it may read as either + disarming or as an excuse. Ask a reader who is not us. +- "Secondary-school students" vs "high school students" — pick one and match the + spelling convention of the venue. diff --git a/research/draft-s2-related.md b/research/draft-s2-related.md new file mode 100644 index 0000000..9577385 --- /dev/null +++ b/research/draft-s2-related.md @@ -0,0 +1,208 @@ +# §2 Background and related work — first draft + +Status: **first draft, unreviewed.** + +> **Citation honesty markers used below.** +> `[FULL]` — read in full. +> `[ABSTRACT]` — abstract only; cited **only** for a position the abstract +> states outright, never for a finding. +> `[SECONDARY]` — cited through another author's summary, not read directly. +> +> Every `[ABSTRACT]` and `[SECONDARY]` must either become `[FULL]` or have its +> sentence weakened before submission. They are listed at the foot of this file. + +--- + +## 2. Background and related work + +### 2.1 Convergence + +People moving toward a disaster is one of the field's oldest documented +behaviours. Fritz and Mathewson (1957) named it *convergence behavior* — +*"the informal, spontaneous movement of people, messages, and supplies toward +the disaster area"* — and observed that it *"brings needed aid to many victims, +but at the same time the resultant congestion makes organization and control of +the rescue and relief efforts more difficult."* They separate movement *"toward +the struck area from the outside — external convergence"* from *"movement toward +specific points within a given disaster-related area or zone — internal +convergence"*, distinguish three forms (personal, informational, materiel), and +catalogue five types of personal converger: the returnees, the anxious, the +helpers, the curious, and the exploiters. `[FULL]` + +It is worth noting that the founding treatment frames convergence as a control +problem — its subtitle is *A Problem in Social Control* — and that this framing +has been remarkably durable. The paper's own position is stated in §5. + +Kendra and Wachtendorf (2002), studying the response to the World Trade Center +attack across more than 750 collective hours of field observation, added a sixth +— supporters or fans — and, more importantly for us, reframed the question. +Access to what they term the *response milieu* is not a status a volunteer +holds but one they negotiate. `[FULL]` + +The taxonomy has passed into practice. FEMA's guidance on managing spontaneous +volunteers reproduces it directly, noting that *"researchers have identified six +different groups of people that tend to converge"*, and derives an operational +task from it: *"the helpers must be identified from among the larger population +of convergent individuals."* `[FULL]` Theory and doctrine here are a single +lineage rather than two literatures, which is why we cite them together. + +DiresQ's users are helpers, converging externally and then internally. + +### 2.2 Legitimacy, credentialing, and what both presuppose + +Kendra and Wachtendorf's central finding concerns who gets in. (We cite their +Disaster Research Center preliminary paper throughout, because it is the text +we read; the 2003 book chapter develops the same fieldwork and is listed in the +references for completeness.) At the World +Trade Center, identification requirements *"evolved and intensified on almost a +twice-daily basis"*, and volunteers became *"another group that needed to be +accounted for, and therefore potentially a distraction that outweighed their +utility."* The volunteers who succeeded in gaining access were those who +*"were able to work with minimal supervision by official emergency workers"* — +whose incorporation *"required little or no effort on the part of emergency +managers."* `[FULL]` + +We take the scarce resource in that account to be emergency-manager attention, +and it is the frame we design against: a volunteer who accounts for themselves +spends none of it. + +Doctrine's mechanisms for conferring legitimacy are the Volunteer Reception +Centre and, prior to any event, pre-affiliation — *"turn spontaneous unaffiliated +volunteers into affiliated ones before a disaster occurs."* `[FULL]` Both +presuppose an institution: one that has arrived and opened a centre, or one that +reached the volunteer months earlier. We develop the consequence in §1 and do +not repeat it here. + +### 2.3 Digital volunteers, and why they need no accounting for + +Starbird and Palen (2011) provide the foundational study of volunteers +self-organising through technology after a disaster, examining 292,928 tweets +and interviewing nineteen of the "voluntweeters" who emerged after the 2010 +Haiti earthquake. They read the phenomenon through Kreps and Bosworth's +structural theory, finding a resource → activity → task → domain progression in +which the *resource* — Twitter, and the individual capacities it made usable — +is what lets a stranger begin. `[FULL]` + +The distinction that matters for this paper is one their scope makes for us: +their volunteers are remote by definition. The population is people helping from +other continents. No participant is in the hazard, so no participant needs +accounting for, and no mechanism for doing so appears in the paper. This is not +a gap in their work. It is the boundary of ours. + +Our question is what changes when that same self-organising sequence runs among +people who are physically inside the hazard. Accountability stops being optional +and there is still nobody to provide it. + +### 2.4 Citizen-led response in practice + +Smith et al. (2018) interviewed twenty participants in the citizen-led rescues +during Hurricane Harvey and found three roles — rescuer, dispatcher, information +compiler — distributed across at least twenty distinct groups with *"no way to +seamlessly share information and coordinate activity."* They report three +coordination failures: incomplete feedback loops, unclear prioritisation, and +communication overload. `[FULL]` + +Incomplete feedback loops is our problem under another name. Their account of it +is mechanical rather than motivational: rescue platforms depended on someone +manually marking a case closed, and in practice the case number was forgotten, +the phone was destroyed, or a different boat reached the address first. The loop +stayed open not because anyone neglected it but because closing it required an +action at exactly the moment nobody had attention to spare. + +We note two of their findings as constraints on our design rather than support +for it. First, their participants wanted *more* coordination: one dispatcher +argued that *"people that are trained to do that need to be in charge of +prioritizing calls and assigning."* Second, over-convergence was itself a +failure mode — boats were turned away from neighbourhoods that already had too +many. We return to both in §5. + +### 2.5 Systems for crisis crowdsourcing + +Liu (2014) offers the field's most developed design framework, organising a +crowdsourcing system around why / who / what / when / where / how, and around +the social, technological, organisational and policy interfaces that manage the +articulation work of coordinating across them. `[ABSTRACT]` We note that two of +those four interfaces presuppose an organisation conducting the effort, and that +the trajectory the framework describes runs toward formalisation and integration +*"into official products and services."* Our position is upstream of that +trajectory rather than opposed to it. + +Auferbauer and Tellioğlu (2017) describe *crowdtasking*, presented explicitly as +*"a centralized form of crowdsourcing for crisis and disaster management"*, with +a prototype and a first field trial. `[ABSTRACT]` It is the clearest statement +of the opposite design position to ours, and we cite it as such: where +crowdtasking assumes an organisation able to task a registered crowd, we assume +neither the organisation nor the registration. + +Kankanamge et al. (2019) provide a systematic review of volunteer crowdsourcing +in disaster risk reduction. `[ABSTRACT]` We have not obtained the full text and +therefore make no claim about its findings; it is listed here because a reader +working in this area will expect to see it and should know we are aware of it. + +Technical work on the classification side is considerably more advanced than +ours. Zhou et al. (2022) fine-tune BERT variants over a hand-labelled corpus of +Hurricane Harvey tweets to identify rescue requests, and substantially outperform +the earlier baselines they compare against. `[ABSTRACT]` Our own priority suggestion (§3.3) is a naive +Bayes classifier over a small hand-labelled corpus, and is not competitive with +this work, nor intended to be: it exists to run in a browser with no network, +which is a different constraint rather than a weaker attempt at the same one. + +### 2.6 Where this leaves the gap + +Convergence is thoroughly theorised. Legitimacy is theorised and operationalised. +Digital volunteering is well studied among remote participants. Crowdsourcing +systems have a design framework and at least one field-trialled centralised +implementation. Classification of rescue requests is a mature technical problem. + +What we have not found, in the literature or the doctrine, is a mechanism for +accounting for physically converging helpers during the interval before an +institution exists to do it. Doctrine's answer is that those people should have +been affiliated beforehand. The academic literature describes their arrival as a +management problem. Neither addresses the person already in the water. + +That interval is this paper's subject, and the design in §3 is one attempt at it. + +--- + +## Citation debts to clear before submission + +**`[FULL]` — Fritz & Mathewson (1957). DEBT CLEARED.** Obtained via the Internet +Archive (`archive.org/details/convergencebehav00fritrich`); the 1957 National +Academy of Sciences / National Research Council report carries no copyright +notice and the scan is openly readable. Every claim we make about it — the three +forms, the five types, the external/internal distinction, the definition — is +now verified against the original text rather than against two secondary +summaries. Both summaries were, for the record, accurate. + +**`[ABSTRACT]` — Liu (2014).** Paywalled at Springer; abstract read, framework +tables unseen. Every sentence citing Liu above is a restatement of her abstract. +Acceptable as written; would not be acceptable if we described what the +framework's dimensions contain. + +**`[ABSTRACT]` — Auferbauer & Tellioğlu (2017).** ACM DL; abstract read. We cite +only their self-description as centralised, which their abstract states in those +words. **Read before submission anyway** — their field trial is the evaluation +design §6 proposes, and we should not describe the nearest neighbouring system +from its abstract if we can avoid it. + +**`[ABSTRACT]` — Kankanamge et al. (2019).** Cited as existing, with an explicit +statement that we make no claim about its findings. This is honest but weak; a +systematic review in our exact area that we have not read is the most likely +place for a reviewer to find something we missed. + +**`[ABSTRACT]` — Zhou et al. (2022). Resolved by removing the numbers.** The +F1 of 0.919 and the 3,191-tweet corpus were taken from the abstract, and an +abstract is not good enough to print somebody else's results from. The sentence +now makes only the qualitative claim the abstract clearly supports. If you read +the paper (Bronze OA — `doi.org/10.1016/j.compenvurbsys.2022.101824` opens free +in a browser), put the figures back; they are more persuasive than the prose. + +## Notes for revision + +- §2.3's last two paragraphs carry the paper's central argument. They should + probably move to §1 and leave §2.3 purely descriptive — decide once §1 and §2 + are read end to end together. +- §2.5 currently reads as a list. If length allows, restructure around the axis + that actually matters — whether the system assumes an organisation — rather + than around who wrote what. +- Check whether ISCRAM's template wants related work as §2 or folded into §1. diff --git a/research/draft-s3-design.md b/research/draft-s3-design.md new file mode 100644 index 0000000..2e2e22b --- /dev/null +++ b/research/draft-s3-design.md @@ -0,0 +1,144 @@ +# §3 Design — first draft + +Status: **first draft, unreviewed.** Prose is written to be cut. Every number +here was read out of the repository on the day of writing and must be re-checked +against it before submission. + +Notation: `[CHECK]` marks a claim that is true of the system but that I have not +verified reads correctly to somebody outside the project. `[CUT?]` marks +something I suspect is too much detail for a WiP paper. + +--- + +## 3. Design + +DiresQ is a server-rendered web application: Flask, SQLite, no client framework, +no account approval step, and no dispatcher role. Thirty-three routes over six +tables. The stack is deliberately unremarkable, and we describe it only to +establish that nothing in what follows depends on infrastructure a volunteer +organisation would not already have. The contribution is not the stack. + +Anyone can sign up. There is no verification of identity, no vetting, and no +administrator who admits people. This is not an oversight we intend to fix; it +is the condition the system is designed for. A tool that requires somebody to +approve you has reintroduced the coordinator whose absence is the entire +problem. + +### 3.1 The mechanism + +A report is a place that needs help. A responder who decides to go there joins +the report and, in doing so, states an expected time of arrival. The ETA is +bounded between five and 240 minutes and warns above 120 — not because longer +journeys are invalid, but because an unbounded ETA makes the subsequent +arithmetic meaningless. From that point the responder is expected to check in; +the interval defaults to thirty minutes. + +If a responder stops checking in, they are marked overdue. Fifteen minutes past +that threshold, the system files a report *about them* — their last known +location becomes an incident in the same feed everyone else is reading. No human +decides this. No human is asked to notice. + +This is the whole mechanism, and its only novel property is what triggers it. +Existing accountability systems escalate when a coordinator observes that +somebody has not reported in. We escalate on the observation itself being +absent. Silence is available in circumstances where a supervisor is not. + +### 3.2 Five decisions, and what each one cost + +The design is small enough that the interesting content is not the architecture +but the trade-offs. We describe five, each of which we got wrong first. + +**Silence as the trigger.** The alternative designs all require somebody to be +watching: a dispatcher view, an alert queue, a supervisor role. Each of them +works, and each of them assumes the thing we cannot assume. Escalating on +absence needs nobody. The cost is that absence is ambiguous — a responder who +has stopped answering may be in trouble, or may have a dead phone, or may have +gone home without saying so. The system cannot tell these apart and does not +claim to. It reports *contact lost*, never *safe* or *unsafe*, and the interface +language was rewritten twice to stop implying otherwise. + +**No in-process timer.** Our first design ran the silence check on a background +thread inside the application. We removed it. A thread that dies takes the alarm +with it and leaves the interface showing green, and a green screen is read as a +positive result rather than an absent one. The check now runs on read: whenever +anyone loads the accountability board, the sweep runs first, rate-limited to +once every thirty seconds. An *external* scheduler is supported and optional +(`flask --app app sweep` from cron or Task Scheduler) — deliberately external, +because an external scheduler that fails is at least visible to the machine +running it, which an in-process timer is not. + +This trades one dependency for another. A timer that might die becomes a check +that depends on being watched. We consider that the better failure — an +unwatched board is a situation where nobody is relying on the result — but the +substantive move is that we made the dependency **visible** rather than +documenting it. The board displays how long since the last sweep and turns amber +past five minutes. On a board somebody is actually watching, the number always +reads a few seconds, because the watching is what runs it. A limitation you can +see on screen is a different claim from one the user has to be told about. +`[CHECK: does this read as insight or as excuse-making?]` + +**Status and contact are different facts.** What a responder last told us is one +thing; whether they are still answering is another. We conflated them, and the +result was a report page displaying "on scene" for somebody the accountability +board had forty-five minutes overdue. Anyone opening that report to decide +whether the address needed more help was counting a person who had gone silent +as help present. Both facts are now shown, and neither is inferred from the +other. Somebody who has explicitly cleared is not chased, because going home is +not going quiet. + +The general form of this: in a system whose purpose is knowing where people are, +*self-reported state* and *liveness* must never be collapsed into one field, +however tempting the simplification is at the schema level. + +**Refusing to cache claims about other people.** The offline layer keeps the +things you committed to — your own assignments, a queued report you filed +without signal — and refuses to keep the report feed or the accountability +board. A cached feed is a list of who needed help twenty minutes ago. Acting on +it sends somebody to an address that has been cleared, and the person reading it +has no way to know the difference between stale and current. A test fails if +either page is added to the service worker's shell list. + +The generalisable claim, and the one we would defend: **correct-when-written and +correct-when-read are different guarantees**, and disaster data has an unusually +short half-life between them. Offline-first design literature tends to treat +availability as an unalloyed good. For a class of data it is not, and the +distinction is not about staleness tolerance but about whether a stale answer is +*actionable* — whether a user can be sent somewhere by it. + +**Not storing triage answers.** The system includes a START triage helper that +orders which reports get attention first. The answers are health observations +about a person who did not consent and is likely in no position to. They are +used to compute an ordering and then discarded; nothing about a casualty's +breathing or perfusion is written to the database. The cost is that the ordering +cannot be audited after the fact, which is a real loss. We accepted it. +`[CUT? — may be a §5 limitation rather than a §3 decision.]` + +### 3.3 Priority suggestion + +A report can be given a suggested priority by a multinomial naive Bayes +classifier over a severity lexicon, trained on a small hand-labelled corpus and +validated by leave-one-out cross-validation with a floor asserted in continuous +integration. + +We describe it in one paragraph deliberately. It is the least interesting +component and the one most likely to be mistaken for the contribution. It +suggests an ordering for human attention; it does not predict outcomes, assess +medical severity, or make any claim that survives the person reading the report +disagreeing with it. A model small enough to ship as a frozen table of word +counts is also small enough to run in the browser, which is why priority +suggestion works with no signal while the report feed deliberately does not. +`[CHECK: is one paragraph too dismissive for a reviewer who wants numbers? If +so the numbers go in a footnote, not the body.]` + +### 3.4 What the design does not attempt + +It does not summon help. No dispatcher reads it, it does not call emergency +services, and the disclaimer on every page is load-bearing rather than legal +decoration. It does not verify that anybody is who they say they are. It does +not know where anyone actually is — location is self-reported throughout. It +makes no claim that a responder is safe; only that we have or have not heard +from them. + +These are stated here rather than only in §5 because a reader who reaches the +limitations section still holding the wrong model of the system has already +misread the design. diff --git a/research/draft-s4-s5.md b/research/draft-s4-s5.md new file mode 100644 index 0000000..7bc1261 --- /dev/null +++ b/research/draft-s4-s5.md @@ -0,0 +1,196 @@ +# §4 and §5 — first draft + +Status: **first draft, unreviewed.** Same conventions as `draft-s3-design.md`: +`[CHECK]` = true but I cannot tell how it reads from outside; `[CUT?]` = suspect +it is too much for a WiP paper. + +> **Correction to §3 — now applied.** `draft-s3-design.md` originally said the +> switch "has no scheduler," which overstated it: there is no *in-process +> thread*, but `flask --app app sweep` runs the same check from cron or Task +> Scheduler, supported and optional. §3 now says *no in-process timer; an +> external scheduler is available and unrequired.* Left recorded here because +> the near-miss is instructive: the overstatement was more quotable than the +> truth, which is how overstatements survive drafting. + +--- + +## 4. What building it taught us + +We report these as observations from construction, not as validated findings. +Each began as a specific bug or reversal and generalised afterwards. + +### 4.1 Correct-when-written and correct-when-read are different guarantees + +The offline layer was originally designed to cache what a user would want if +their signal dropped, which is nearly everything. We now cache almost nothing. + +The rule we arrived at: **do not store anything that stops being true when it is +written.** Your own commitments — the assignment you accepted, a report you +filed with no signal — remain true offline, because they are statements about +you. The report feed and the accountability board are statements about other +people, and both decay. A cached feed is a list of who needed help twenty +minutes ago; a responder acting on it is dispatched to an address that has since +been cleared, with no way to distinguish that from a current one. + +Offline-first design generally treats availability as an unalloyed good, with +staleness managed by tolerance windows and revalidation. We think the useful +distinction is not how stale the data is but whether a stale answer is +*actionable* — whether a user can be sent somewhere by it. Data that can move a +body should not be served from cache at all. A test fails if either page is +added to the service worker's shell list, because the rule is easy to forget and +the failure is silent. + +### 4.2 An alarm that dies quietly is worse than no alarm + +The silence check was first designed as a background thread inside the +application. We removed it. A timer that dies takes the alarm with it and leaves +the interface showing green, and a green screen is read as a positive result +rather than an absent one. + +The check now runs on read — whenever anyone loads the accountability board, +rate-limited to once every thirty seconds. An external scheduler is supported +(`flask --app app sweep`) and deliberately optional: an external scheduler that +fails is at least visible to the machine running it, which an in-process timer +is not. + +This does not remove the dependency, it relocates it. The system now works while +somebody is looking. We regard that as the better failure mode, because a board +nobody is watching is a situation where nobody is relying on the answer — but +the claim needs stating rather than assuming. `[CHECK]` + +### 4.3 A limitation on screen is a different claim from a limitation in a file + +The consequence of §4.2 is that the guarantee is conditional, and our first +response was to write that down in a limitations document. That is the standard +move and we now think it is insufficient. + +The board displays how long since the last sweep — *checked 2s ago* beside the +live indicator, amber past five minutes, which is ten minutes before the +fifteen-minute escalation it drives. On a board somebody is watching it always +reads a few seconds, because the watching is what runs it. If it stops moving, +that is visible too. + +The general form: **emergency software should surface its own liveness.** A user +deciding whether to trust a screen needs to know whether the thing behind it ran, +and that is a different question from whether the data looks reasonable. We would +extend this beyond our own system: any interface that reports on a periodic +check should display when the check last completed, not merely its result. + +### 4.4 The pages built to be watched were the ones that broke under watching + +The board, the map and the feed all run the silence check before answering, and +the check writes. SQLite's default journal mode lets one writer lock out every +reader. With several people watching a board that refreshes every three seconds, +a write could wait past its timeout and fail the entire response. + +The pages whose purpose is to be watched continuously during an emergency were +precisely the pages that failed when watched continuously. The fix was +unremarkable — write-ahead logging, rate-limiting the sweep, catching the +failure rather than letting it become an error page. The lesson is not about +SQLite. It is that **making a read-only page write is a change of kind, not of +degree**, and in this system it converted the most-loaded pages into the most +fragile ones. `[CHECK: is the SQLite detail too specific? The general point may +survive without naming the database.]` + +One deliberate detail: a failed sweep does not record itself as having run. The +timestamp goes stale and the board reports that in amber, which is true, because +a check we could not record is not a check we can claim. + +### 4.5 Prose about a system lags the system `[CUT?]` + +Our test suite verifies every count in our own documentation — routes, tables, +tests, lines — and fails when the prose and the repository disagree. It has +caught wrong numbers repeatedly, including several we wrote ourselves. + +It has never once caught the more common error, which is a *sentence* that +describes a previous version of a behaviour. Four times a change landed and the +paragraph explaining it stayed a revision behind. Numbers are checkable and were +checked; claims are not, and were not. + +We do not have a solution and offer this as an observation: automated +documentation checks create a real assurance about the class of statement they +can verify and no assurance whatever about the class they cannot, and the second +class is where the misleading statements live. + +*(Include only if length allows. It is the most generalisable thing here and the +least connected to disaster response.)* + +--- + +## 5. Limitations + +The system has eighteen documented limitations, maintained as a first-class +document rather than an appendix. We summarise the ones that most constrain what +this paper claims. + +**It has never been used in a real disaster.** Everything here is reasoned from +published accounts of Harvey, Kathmandu and Mexico City, and from published +triage protocol. None of it has been tested by somebody standing in water at two +in the morning. We believe the reasoning is sound; that is not the same as +knowing it works, and no part of this paper should be read as evidence that it +does. + +**The switch depends on being run.** Described in §4.2. Neither the read-trigger +nor an external scheduler is guaranteed. A deployment nobody looks at and nobody +configures performs no checks. + +**Overdue measures contact, not safety.** The system reports that it has not +heard from somebody. It cannot distinguish danger from a dead battery, and it +does not try. The interface language was revised twice to stop implying +otherwise, and this is the limitation most likely to be misread by a user in a +hurry. + +**No identity verification.** Anyone can register. This is a design condition +rather than a defect — a system requiring approval has reintroduced the +coordinator whose absence is the problem — but it means the system cannot +distinguish a responder from someone claiming to be one. + +**Location is self-reported** throughout. The map shows where people said they +were. + +**One cautious responder can hold a report open**, which biases the system toward +over-reporting need. We prefer that direction and note that we chose it. + +**Lockouts live in memory** and do not survive a restart. + +**The volunteers we claim to serve asked for the opposite.** Smith et al. (2018) +interviewed twenty Harvey rescuers and dispatchers, and the structural complaint +that came back was a wish for *more* coordination, not less. One dispatcher, on +being unable to prioritise calls: *"people that are trained to do that need to be +in charge of prioritizing calls and assigning."* Another described sending boats +away because too many had converged on one neighbourhood. + +This is the strongest available argument against our design, and it comes from +the population the design is for. We do not think it defeats the argument — the +wish for a trained coordinator does not summon one, and the interval before one +exists is exactly our subject — but a reader should weigh it. A system that +makes self-deployment easier and better-accounted-for may also make it more +attractive, and Smith et al. document a response that suffered from too many +boats as well as too little information. + +### A position rather than a finding + +The literature we build on treats converging volunteers as a population to be +managed: Kendra and Wachtendorf document access as negotiated legitimacy, with +credentialing, liability and security as the operative concerns, and volunteers +as a potential distraction that must outweigh its own cost. Our design treats +the volunteer as somebody owed an accounting. + +These are different moral starting points, and the literature does not share +ours. We think ours is defensible — a person who walks into a hazard to help is +owed something regardless of whether an institution has authorised them — but it +is a position, not a result, and a reader is entitled to reject it and evaluate +the design on the field's own terms instead. + +--- + +## Notes for revision + +- Fix the §3 scheduler overstatement first. +- §4.5 is the strongest general claim and the weakest fit for an emergency + management venue. Cut it before cutting anything else if length binds. +- §5 currently names seven of eighteen limitations. Check whether the CfP page + limit allows more; if it does, add the triage-storage decision here and remove + it from §3. +- Every number in §4.4 and §5 must be re-read out of the repository at + submission time. diff --git a/research/literature.md b/research/literature.md new file mode 100644 index 0000000..fa6980d --- /dev/null +++ b/research/literature.md @@ -0,0 +1,391 @@ +# Literature matrix + +Working notes for a possible paper. **This file is not a claim about DiresQ.** +It exists to find out whether there is a contribution here, and it is allowed +to conclude that there is not. + +One row per source: what it claims, what evidence backs it, and what it does +not cover. The third column is the only one that becomes a paper. + +Rule set before starting, so it cannot be bent later: **if three sources +already make our argument, we change the argument rather than the wording.** + +--- + +## Status: one paper read, and it widened the gap rather than closing it + +**Starbird & Palen is read.** It is the foundational paper on volunteers +self-organising after a disaster, and it contains nothing about keeping track +of anybody — because every person in it is safe at a desk on another continent. +That is not an oversight in the paper. It is the paper's scope: "digital +volunteers," remote by definition. + +So the sharper version of our question is not *"has anyone done peer-to-peer +accountability?"* It is: + +> The self-organising sequence Starbird & Palen document — resource, then +> activity, then task, then domain — was observed among volunteers who were +> never in danger. What changes when the same sequence runs among people who +> are physically inside the hazard? Accountability becomes a requirement rather +> than a nicety, and there is no coordinator to provide it. + +That framing has a theoretical home (Kreps & Bosworth's D/A/R/T), a documented +empirical precursor, and a gap the precursor cannot cover by construction. +DiresQ is a *resource* in exactly Kreps & Bosworth's sense — the thing a +stranger picks up to start organising — aimed at the population the existing +work excludes. + +**Two useful things fell out of its reference list**, both added to the table +below: Kendra & Wachtendorf on *physical* convergers and legitimacy at the WTC +(ref 8), which is the nearest prior work found so far, and Fritz & Mathewson +1957 (ref 4), which was already on the search list and is now confirmed as the +origin citation everyone routes through. + +**Still unverified**, and the reason the searches below are not yet ticked: +one paper cannot establish that a gap exists. It can only establish that this +paper does not fill it. + +## Earlier status: two searches in, the claim had narrowed twice + +The Devpost story says *"we couldn't find one that keeps a list of the people +walking into it."* That is not going to survive review. Two rounds of +searching have found: + +1. **Spontaneous volunteer management is established doctrine.** FEMA has a + publication on it. ASPR TRACIE has a topic collection. Volunteer Reception + Centers, credentialing, and deployment logging are standard practice, and + commercial software does it. +2. **Responder accountability is a mature technical field.** Fire services run + PAR (Personnel Accountability Report) processes. Commercial accountability + software tracks responder location in real time. There are granted US + patents on interlinking electronic identities for personnel tracking at an + incident scene. +3. **The self-deployment problem is already named.** Practitioner literature + describes uncontrolled self-deployment — volunteers going straight to a + damaged neighbourhood without accountability — as a known hazard. + +So the problem is real *and already recognised*. That is the honest position. + +### What might still be left + +Every system found so far assumes **a command structure exists**: an incident +commander running accountability, a reception centre issuing credentials, an +organisation accepting the volunteer. The Harvey boat owner has none of those, +and is the person the doctrine describes as the problem to be prevented rather +than the user to be served. + +The candidate gap, stated narrowly enough to be defensible: + +> Accountability mechanisms for disaster response assume an organisational +> structure — incident command, credentialing, a reception centre. Volunteers +> who self-deploy bypass all three by definition. Can accountability be made +> *peer-to-peer and self-service*, so that it functions with no dispatcher and +> no command structure at all? + +The dead man's switch is the mechanism for that: escalation triggered by +**silence** rather than by a coordinator noticing. + +**This is still unverified.** It needs the searches below run before anyone +writes it down as fact. + +--- + +## What Kendra & Wachtendorf actually changes + +It does not close the gap. It does something more useful: it tells us the gap +has a name in the literature, and that the field noticed it and moved on. + +**Stop saying "nobody tracks the people who go in."** That is not defensible and +a reviewer will know it. The accurate version is: + +> Convergence is well theorised — Fritz & Mathewson (1957) name the five +> personal converger types; Kendra & Wachtendorf add a sixth and reframe access +> as negotiated legitimacy. The established mechanism for handling converging +> helpers is **credentialing by an authority**. Credentialing presupposes an +> authority. Where none has arrived, no mechanism exists, and the literature +> does not propose one. + +**The sentence that hands us the problem.** Kendra & Wachtendorf, summarising +Weick (1987) and Perrow (1977): + +> "He also argues that experience with centralized direction, as in prior +> training or other socialization such as military service, is first required +> before decentralization can be effective. Yet the volunteers who appear to +> assist in the emergency response are, **virtually by definition, strangers to +> the response milieu**." + +That is our problem statement, written by the field in 2001, with no technical +answer offered then or found since. A paper that opens on that sentence is +standing on the literature rather than around it. + +**The finding that gives the design its argument:** + +> "The most 'successful' volunteers — those who negotiated access and got past +> gatekeepers — were those who were able to work with minimal supervision by +> official emergency workers… the incorporation of these volunteers into the +> response required little or no effort on the part of emergency managers." + +The scarce resource is *emergency-manager attention*. A volunteer who accounts +for themselves spends none of it. That reframes DiresQ from "a tool for +volunteers" to "a way for an unaffiliated helper to become legible without +costing the response anything" — which is the currency this paper says +determines who gets in. + +**Vocabulary to adopt, because it is theirs:** response milieu, converger, +personal / informational / materiel convergence, ad hoc vs. affiliated +volunteer, negotiated legitimacy, emergent group (Stallings & Quarantelli 1985). + +**Two caveats, recorded so they are not forgotten.** (1) The paper frames +volunteers as a *problem to be managed* — a security and liability risk to the +response. Our framing treats the volunteer as someone owed an accounting. Those +are different moral positions and the paper does not agree with ours; the +difference has to be argued, not assumed. (2) This is 2001 fieldwork at an +atypical event — crime scene and battlefield as well as disaster. Do not +generalise its security findings to a hurricane. + +## Sources read + +| Source | Claim | Evidence | Does not cover | +| --- | --- | --- | --- | +| Starbird & Palen, *Voluntweeters* (CHI 2011) | Digital volunteers self-organise after disaster with no prior structure. Fits Kreps & Bosworth's D/A/R/T model in an R→A→T→D order: Twitter itself is the *resource* that lets a stranger start. | 339 twitterers, 292,928 tweets (Haiti, Jan 10–Feb 1 2010); hand-coded 2,911 syntax tweets; 19 completed email interviews of 74 identified translators. | **Everyone in it is remote.** The population is defined as people helping from other continents. Nobody is in the hazard, so nobody needs accounting for. No safety mechanism, no check-in, no escalation — the problem does not arise. Organising runs on Twitter affordances (hashtags, @-addressivity) and interpersonal trust built over days, not on anything built for the purpose. | +| Starbird, *Crowdwork, Crisis and Convergence* (2012 diss.) | | | | +| Liu, *Crisis Crowdsourcing Framework* (CSCW 2014), 23(4):389–443 — **ABSTRACT ONLY. Paywalled at Springer (`meta-access: No`); no open-access copy found.** | A *design* framework for crowdsourcing systems: determine the why / who / what / when / where / how, then design the **STOP interfaces** — social, technological, organizational, policy — that manage the "articulation work" of coordinating across them. Built from vignettes tracing Haiti 2010 onward. | Vignettes plus synthesis of crisis informatics, disaster sociology and CSCW literature. Cannot assess the evidence properly without the body. | **Unknown — this is the open risk.** The framework tables (Table 3 and after) are behind the paywall and are exactly where a box that pre-empts us would live. What the abstract *does* show is directional: the arc described runs from spontaneous emergence toward "more established forms of public engagement" and being "integrated into official products and services." The organizational and policy interfaces presuppose an institution doing the crowdsourcing. Liu is USGS. That is the opposite direction from ours. | +| FEMA, *Managing Spontaneous Volunteers in Times of Disaster* | | | | +| ASPR TRACIE, Volunteer Management topic collection | | | | +| ERHMS framework (responder health monitoring) | | | | +| Fire service PAR / accountability software | | | | +| US 8995946 / 9497610 (personnel accountability patents) | | | | +| Kendra & Wachtendorf, *Rebel Food… Renegade Supplies* (DRC Preliminary Paper 316, 2001/02) — **read this, not the 2003 chapter.** Same authors, same fieldwork, adjacent argument; the 2003 book chapter is paywalled at Emerald. | Convergence at the WTC follows Fritz & Mathewson's types, plus a sixth (fans/supporters). Access to the *response milieu* is **negotiated legitimacy**, not a right. The volunteers who got in were those who could work unsupervised. | 750+ collective hours of field observation beginning within 48h of the attack; EOC, Javits Center, Family Assistance Center, command posts, staging areas; 500+ photographs. | **No technology of any kind.** Accountability appears only as *credentialing by an authority* — badge systems that 'evolved and intensified on almost a twice-daily basis.' The volunteer never accounts for themselves. And the volunteer's own safety is essentially absent: the hazard discussion concludes *keep untrained people out*, never *track the ones who go in*. Presupposes gatekeepers exist. | +| Kreps & Bosworth, *Organizing, Role Enactment, and Disaster* (1994) | | | *Found via Voluntweeters ref [9]. The D/A/R/T structural theory. Candidate theoretical frame.* | + +## Liu 2014: what the abstract settles, and what it does not + +**Settled.** Liu's contribution is a *framework for designing* crowdsourcing +systems, not a survey of systems that exist. That distinction matters more than +it sounds: a design framework cannot pre-empt a system's novelty the way a +catalogue could. It is a checklist to be applied, and applying it to DiresQ is a +thing we could do in the paper rather than a threat to be defended against. + +**Also settled, and useful.** The trajectory Liu describes runs *toward* +formalisation — spontaneous emergence after Haiti, then "more established forms +of public engagement," then integration "into official products and services." +Two of the four STOP interfaces are *organizational* and *policy*. Both +presuppose an institution running the crowdsourcing effort. Liu writes from +USGS. This is the same assumption Kendra & Wachtendorf make from the other +direction, and it is now the second independent source pointing at it. Our +position — the interval before any institution exists — is the one place this +literature consistently does not reach. + +**Not settled, and it is the live risk.** The framework's own tables are behind +the paywall. If a box exists that already describes self-service accountability +with no coordinator, it is in there. **Do not write §2 as though this is +resolved.** + +**Two ways to close it, in order of speed:** + +1. Email the author. Liu's address is on the paper: `sophialiu@usgs.gov`. She is + a US government scientist; authors routinely send copies on request, and a + high-school team saying plainly what they are building is a reasonable ask. + Cost: one email, a few days. +2. Interlibrary loan through a school or public library. + +Until one of those happens, §2's taxonomy paragraph stays marked `[UNREAD]`. + +## Leads from Liu's citation list (99 citing papers, via EUSSET) + +EUSSET's record for Liu is metadata-only — no full text — but it exposes every +paper that cites her. That list turned out to be worth more than the paper. Read +in this order: + +**1. Kankanamge, Yigitcanlar, Goonetilleke & Kamruzzaman (2019), "Can volunteer +crowdsourcing reduce disaster risk? A systematic review of the literature," +*IJDRR*.** `doi:10.1016/j.ijdrr.2019.101097` +A systematic review reads the field so we do not have to. Highest value per +hour of anything remaining on this list. If a system like ours exists, a +systematic review is where it will be named. **Read this before the Starbird +dissertation.** + +**2. Auferbauer & Tellioğlu (2017), "Centralized Crowdsourcing in Disaster +Management," C&T.** `doi:10.1145/3083671.3083689` +The title addresses our exact axis. Either it argues centralisation is +necessary — in which case we have a named position to argue against, which is +better than arguing into a vacuum — or it has already explored the +decentralised alternative, in which case we need to know now. **This is the +remaining novelty risk, more than Liu herself.** + +**3. Baker & Deham (2019), "For a short time, we were the best version of +ourselves: Hurricane Harvey and the ideal of community," *Int. J. Emergency +Services*.** `doi:10.1108/ijes-12-2018-0066` +Harvey is our motivating case and the outline flags every Harvey claim as +needing a source. This is that source, and it is peer-reviewed rather than +journalism. + +**Also noted, lower priority:** + +- Middelhoff et al. (2016), crowdsourcing field experiment simulating a flood in + The Hague — `doi:10.1109/ict-dm.2016.7857212`. Relevant as *evaluation + methodology*: a simulated event is how you evaluate a system like ours without + waiting for a disaster. Read when we get serious about moving to CoRe. +- Park & Johnston (2017), framework for analysing digital volunteer + contributions — `doi:10.1177/1461444817706877`. +- Alswailim, Hassanein & Zulkernine (2017), "A Participant Contribution Trust + Scheme for Crisis Response Systems" — `doi:10.1109/glocom.2017.8253927`. + Trust without a central authority. Adjacent to our problem from the security + direction. +- dos Santos Rocha et al. (2017), "Improving the Involvement of Digital + Volunteers in Disaster Management" — `doi:10.1007/978-3-319-68486-4_17`. +- Song, Zhang & Dolan (2020), self-organising processes of crowdsourcing, + *Sustainability* — `doi:10.3390/su12051862`. MDPI, so open access. + +**Note on strategy:** chasing Liu's PDF has become the wrong priority. Her +framework is a design checklist we can apply from the abstract. Items 1 and 2 +above are where an actual collision with prior work would show up. + +## Accessibility check — where the remaining papers actually are + +### Open, full text, free + +**Smith, Stephens, Robertson, Li & Murthy (2018), "Social Media in Citizen-Led +Disaster Response: Rescuer Roles, Coordination Challenges, and Untapped +Potential."** ISCRAM proceedings. NSF-PAR 10076203 → +`https://par.nsf.gov/servlets/purl/10076203` + +**This is the §1 Harvey source, not Baker & Deham.** Semi-structured interviews +and photo elicitation on how wide-scale rescues actually happened in Greater +Houston in 2017. Citizens took one of three roles — **rescuer, dispatcher, +information compiler** — and the three coordination problems they hit were +**incomplete feedback loops**, unclear prioritisation, and communication +overload. + +"Incomplete feedback loops" is our gap, named empirically, by people who +interviewed the volunteers. It is a stronger opening than anything we could +assert ourselves. + +Two bonuses: it is an ISCRAM paper, so it is *also* a template for the venue we +are targeting; and it is a **Work in Progress** paper, so it shows what that +track accepts. + +**Baker & Deham (2019).** NSF-PAR 10126439 → +`https://par.nsf.gov/servlets/purl/10126439` + +Open, but **not what we assumed.** It is co-autoethnographic critical theory — +"ephemeral utopia", modernity as domination, institutions appropriating the +public's response. Its own limitations section says: *"This work produces theory +rather than engage in testing theory."* Do not mine it for Harvey facts or +numbers; there are none to mine. It is useful for one thing only, and it is a +good thing: it argues that institutions should *defer to the potentials of +publics rather than disdain and appropriate them*, which is a citable ally for +our §5 moral position against Kendra & Wachtendorf's framing. + +### Metadata only — body still behind a paywall + +**Auferbauer & Tellioğlu (2017).** EUSSET and TU Wien both hold metadata with an +empty fulltext field; ACM DL is canonical. TU Wien points at +`comtech.community/papers-full-and-short/` as a public copy, which did not +render for me — **worth trying by hand.** + +**But the risk has dropped.** The full abstract is now in hand: crowdtasking is +described as *"a **centralized** form of crowdsourcing for crisis and disaster +management"*, with a prototype and a first field trial. Centralised by +declaration. That is the opposite pole from ours, which makes it a named +position to argue against rather than a claim that pre-empts us. Still read it — +their field trial is the evaluation method we want — but it is no longer the +thing most likely to sink the paper. + +**Kankanamge et al. (2019).** QUT ePrints record exists at +`eprints.qut.edu.au/127136` and is indexed as having full text; the page would +not render for me. Try it directly. + +### The finding that matters more than any single paper + +**NSF-PAR is an open corpus for exactly this field.** US-funded crisis +informatics work is deposited there free, and browsing outward from one record +surfaced four more relevant papers in one page. **ISCRAM's own proceedings are +open access** on `ojs.iscram.org` as well. Between them, most of what §2 needs +is probably free and we have been assuming otherwise. + +Also surfaced, all free on NSF-PAR, worth knowing: + +- **Zhou et al. (2022), "VictimFinder: Harvesting rescue requests in disaster + response from social media with BERT"** — 3,191 hand-labelled Harvey tweets, + best model F1 0.919. This is the closest thing to a comparable for our + classifier, and it is *far* stronger than ours. **Cite it in the classifier + paragraph and be modest.** A reviewer who knows this paper and reads an + immodest claim about our naive Bayes will not be gentle. +- Stephens et al. (2018), citizens sharing health information during a flood + (ISCRAM). +- Mittal, Jahanian & Ramakrishnan (2020), ONSIDE — routing social media posts to + the right first responders. +- Johnson et al. (2019), deep learning for hurricane image classification + (ISCRAM). + +## FEMA doctrine — read, and it underwrites the whole argument + +*Managing Spontaneous Volunteers in Times of Disaster* (FEMA / Points of Light / +CNCS), participant materials. Open PDF via the Humanitarian Library. + +This was the leg of the argument we had been **assuming rather than reading**. +§1 claimed "the field's answer is credentialing" on the strength of Kendra & +Wachtendorf watching badge systems appear at Ground Zero. That is an +observation. The doctrine is a prescription, and it says something sharper. + +**It defines our user, in its own words:** unaffiliated volunteers are *"no part +of a recognized voluntary agency"*, *"often have no formal training in emergency +response"*, and are *"not officially invited to become involved."* + +**It has absorbed the academic taxonomy.** *"Researchers have identified six +different groups of people that tend to converge"* — Fritz & Mathewson's five +plus the sixth Kendra & Wachtendorf added. Theory and doctrine are one lineage +here, which is useful connective tissue for §2. + +**It names the operational task:** *"the helpers must be identified from among +the larger population of convergent individuals."* + +**And its two mechanisms both presuppose an institution.** The Volunteer +Reception Centre processes arrivals, so it must first have been established. And +the primary mechanism is *prevention*: + +> "Turn spontaneous unaffiliated volunteers into affiliated ones **before a +> disaster occurs.** People who make a pre-disaster decision to become disaster +> volunteers and take training to prepare themselves will NOT become +> spontaneous, unaffiliated volunteers after a disaster." + +A training exercise asks how a community can *"keep your community members from +self-deploying"*. National service volunteers are described approvingly as +*"never self-deploy[ing], but wait[ing] to be called."* + +**This is the strongest version of our gap and it is doctrinal, not inferred.** +Doctrine's answer to the person who decides at 2am that they have a boat is that +they should not exist. Handle it with respect — pre-affiliation genuinely works +— but the argument now stands on what the field prescribes rather than on what +we observed it doing. + +**Still to read on the doctrine leg:** ASPR TRACIE's volunteer management topic +collection (their site did not render; try by hand). Barsky et al. (2007), +*"Managing volunteers: FEMA's Urban Search and Rescue programme and interactions +with unaffiliated responders"*, Disasters — surfaced in the same search, sounds +directly on point, not yet checked for access. + +## Searches still to run + +- [ ] ISCRAM proceedings: "spontaneous volunteer", "convergence", + "accountability", "self-deployment" +- [ ] Does anything cover accountability **without** an incident commander? +- [ ] Fritz & Mathewson (1957) on convergence — the origin of the term, and + whether physical convergence is still being studied or whether the field + moved to informational convergence after 2010 +- [ ] Crowdsource Rescue and similar Harvey-era tools: what did they actually + track, and is there any write-up of it? +- [ ] Prior art search on the two patents above — how close do they get? + +## Honest outcomes, ranked by likelihood + +1. **The gap is real but small.** A short design paper at a student venue or + ISCRAM, positioned as peer-to-peer accountability for the unaffiliated. +2. **The gap is already occupied.** Somebody has built or studied this. The + project stays a good system and a good story, and is not a paper. +3. **The gap is real and open.** Worth a proper venue — and would need user or + expert evaluation before submission, which does not exist yet. + +Outcome 2 is not a failure. Finding out early is the entire point of doing +this step first. diff --git a/research/liu-2014-references.md b/research/liu-2014-references.md new file mode 100644 index 0000000..b776f90 --- /dev/null +++ b/research/liu-2014-references.md @@ -0,0 +1,313 @@ +# Liu (2014) — reference list + +**Provenance: this is the bibliography only.** Captured from the free portion of +the Springer page. The article body and the framework tables are *not* here and +remain unread. Do not cite anything below as though we have read Liu's argument +about it. + +Kept because it is a map of the field as of 2014, drawn by someone who had read +all of it — useful for finding sources, not for making claims. + +--- + +Baker, Karen S. and Florence Millerand (2007). Articulation Work Supporting Information +Infrastructure Design: Coordination, Categorization, and Assessment in Practice. In +Proceedings of the 40th Annual Hawaii International Conference on System Sciences (HICSS +'07). IEEE Computer Society, Washington, DC, USA, 242a. +Bannon, Liam J. and Kjeld Schmidt (1989). CSCW: Four characters in search of a context. +ECSCW ’89. Proceedings of the First European Conference on Computer Supported +Cooperative Work, Gatwick, London, 13–15 September, 1989, pp. 358–372. - Reprinted in +Studies in Computer Supported Cooperative Work. Theory, Practice and Design, J. M. Bowers +and S. D. Benford, Eds. North-Holland, Amsterdam etc., 1991, pp. 3–16. +Barrington, Luke, Shubharoop Ghosh, Marjorie Greene, Shay Har-Noy, Jay Berger, Stuart +Gill, Albert Yu-Min Lin, and Charles Huyck. (2011). Crowdsourcing Earthquake Damage +Assessment Using Remote Sensing Imagery. Annals of Geophysics - Citizen Empowered +Seismology, vol. 54, no. 6, pp. 680–687.Bonney, Rick, Caren B. Cooper, Janis Dickinson, Steve Kelling, Tina Phillips, Kenneth V. +Rosenberg, and Jennifer Shirk (2009). Citizen Science: A Developing Tool for Expanding +Science Knowledge and Scientific Literacy. BioScience, vol. 59, no. 11, pp. 977–984.Boulos, Maged N. Kamel, Bernd Resch, David N. Crowley, John G. Breslin, Gunho Sohn, Russ +Burtner, William A. Pike, Eduardo Jezierski, and Kuo-Yu Slayer Chuang (2011). +Crowdsourcing, citizen sensing and sensor web technologies for public and environmental +health surveillance and crisis management: trends, OGC standards and application examples. +International Journal of Health Geographics, vol. 10, no. 67, pp. 1–29.Bowker, Geoffrey C. and Susan Leigh Star (1991). Situations vs. standards in long-term, +widescale decision-making: The case of the International Classification of Diseases. In J. F. +Nunamaker, Jr. and R. H. Sprague, Jr. (eds.): Proceedings of the Twenty-Fourth Annual +Hawaii International Conference on System Sciences, Kauai, Hawaii, January 7-11, 1991. +IEEE Computer Society Press, vol. 4, pp. 73–81. +Bowker, Geoffrey C. and Susan Leigh Star (1999). Sorting Things Out. MIT Press, Boston.Bowser, Anne and Lea Shanley (2013). New Visions in Citizen Science. Case study series v3. +Woodrow Wilson International Center for Scholars: Washington DC. +Brabham, Daren C. (2008). Crowdsourcing as a Model for Problem Solving: An Introduction +and Cases. Convergence: The International Journal of Research into New Media +Technologies, vol. 14, no. 1, pp. 75–90. +Brabham, Daren C. (2012). Crowdsourcing: A Model for Leveraging Online Communities. In: +A. Delwiche and J. Henderson (eds.), The Routledge Handbook of Participatory Culture. New +York: Taylor & Francis Inc.Capelo, Luis, Natalie Chang, and Andrej Verity (2012). Guidance for Collaborating with +Volunteer & Technical Communities. Digital Humanitarian Network. +https://www.box.com/shared/static/2b421a2b036c955aa4a3.pdf. Accessed 13 March 2013. +Clarke, Lee (2002). Panic: Myth or Reality? Contexts, vol. 1, no. 3, pp. 21–26.Cobb, Camille, Ted McCarthy, Annuska Perkins, Ankitha Bharadwaj, Jared Comis, Brian Do, +and Kate Starbird (2014). Designing for the Deluge: Understanding & Supporting the +Distributed, Collaborative Work of Crisis Volunteers. In Proceedings of the 17th ACM +conference on Computer supported cooperative work & social computing (CSCW '14). ACM, +New York, NY, USA, 888–899. +Cohn, Jeffrey P. (2008). Citizen science: Can volunteers do real research? BioScience, vol. 58, +no. 3, pp. 192–197.Divitini, Monica and Tuomo Tuikka (1996). Steps for Developing Coordination Support. In +Dahlbom, B., Ljungberg, F., Nuldén, U., Simon, K., Stage, J., Sørensen, C. (Eds.), Proceedings +of IRIS 19. pp. 823–841. Gothenburg Studies of Informatics. +Doran, Kara S., Hilary F. Stockdon, Kristin L. Sopkin, David M. Thompson, and Nathaniel G. +Plant (2012). National assessment of hurricane-induced coastal erosion hazards: Mid-Atlantic +Coast. U.S. Geological Survey Open-File Report 2013–1131, +http://pubs.usgs.gov/of/2013/1131. +Dynes, Russell Rowe (1970). Organized Behavior in Disaster. Lexington, MA: Heath +Lexington Books, D.C. Health and Company.Earle, Paul S. and Peter M. Shearer (1994). Characterization of global seismograms using an +automatic-picking algorithm. Bulletin of the Seismological Society of America, vol. 84, pp. +366–376. +Earle, Paul S., Daniel C. Bowden, and Michelle Guy (2011). Twitter Earthquake Detection: +Earthquake Monitoring in a Social World. Annals of Geophysics Special Section on Citizen +Empowered Seismology, vol. 54, no. 6, pp. 708–715.Earle, Paul S., Michelle Guy, Richard Buckmaster, Chris Ostrum, Scott Horvath, and Amy +Vaughan (2010). OMG Earthquake! Can Twitter Improve Earthquake Response? +Seismological Research Letters, vol. 81, no. 2, pp. 246–251.Elwood, Sarah (2008). Volunteered geographic information: Key questions, concepts and +methods to guide emerging research and practice. GeoJournal, vol. 72, no. 3–4, pp. 133–135. +Estellés-Arolas, Enrique and Fernando González-Ladrón-De-Guevara (2012). Towards an +integrated crowdsourcing definition. Journal Information Science, vol. 38, no. 2, pp. 189–200. +Fischer III, Henry W. (1998). Response to Disaster: Fact Versus Fiction & Perpetuation, 2nd +ed. New York: University Press of America.Fitzpatrick, Geraldine, William J. Tolone, and Simon M. Kaplan (1995). Work, locales and +distributed social worlds. In Proceedings of the fourth conference on European Conference on +Computer-Supported Cooperative Work (ECSCW'95), Hans Marmolin, Yngve Sundblad, and +Kjeld Schmidt (Eds.). Kluwer Academic Publishers, Norwell, MA, pp. 1–16.Fjuk, Annita, Markku I. Nuriminen, and Ole Smørdal (1997). Taking Articulation Work +Seriously — An Activity Theoretical Approach. Turku Centre for Computer Science, TUCS +Technical Report No 120. +Fritz, Charles E. and John H. Mathewson (1957). Convergence Behavior in Disasters: A +Problem in Social Control, Committee on Disaster Studies. Washington, DC: National +Academy of Sciences, National Research Council.Fujimura, Joan H. (1987). Constructing ‘Do-Able’ Problems in Cancer Research: Articulating +Alignment. Social Studies of Science, vol. 17, no. 2, pp. 257–293.Gao, Huiji, Geoffrey Barbier, and Rebecca Goolsby (2011). Harnessing the Crowdsourcing +Power of Social Media for Disaster Relief. IEEE Intelligent Systems, vol. 26, no. 3, pp. 10–14.Gerson, Elihu M. and Susan Leigh Star (1986). Analyzing due process in the workplace. ACM +Transactions on Information Systems (TOIS), vol. 4, no. 3, pp. 257–270.Goodchild, Michael F. (2007). Citizens as sensors: The world of volunteered geography. +GeoJournal, vol. 69, no. 4, pp. 211–221.Goodchild, Michael F. and J. Alan Glennon (2010). Crowdsourcing Geographic Information +for Disaster Response—A Research Frontier. International Journal of Digital Earth, vol. 3, no. +3, pp. 231–241.Grinter, Rebecca E. (1996). Supporting Articulation Work Using Software Configuration +Management Systems. Computer Supported Cooperative Work: The Journal of Collaborative +Computing, vol. 5, pp. 447–465.Guy, Michelle, Paul Earle, Chris Ostrum, Kenny Gruchalla, and Scott Horvath (2010). +Integration and Dissemination of Citizen Reported and Seismically Derived Earthquake +Information via Social Network Technologies. In Proceedings of the Advances in Intelligent +Data Analysis IX, vol. 6065, pp. 42–53. +Hagar, Christine and C. Haythornthwaite (2005). Crisis, Farming & Community. The Journal +of Community Informatics, vol. 1, no. 3, pp. 41–52.Haklay, Mordechai (2010). How good is volunteered geographical information? A comparative +study of OpenStreetMap and Ordnance survey datasets. Environment and Planning B: +Planning and Design, vol. 37, pp. 682–703.Mordechai (Muki) Haklay, Alex Singleton, and Chris Parker (2008). Web Mapping 2.0—The +Neogeography of the GeoWeb. Geography Compass, vol. 2, no. 6, pp. 2011–2039. +Harvard Humanitarian Initiative. (2011). Disaster Relief 2.0: The Future of Information +Sharing in Humanitarian Emergencies. Washington, D.C. and Berkshire, UK: UN Foundation +& Vodafone Foundation Technology Partnership. +Heath, Christian and Paul Luff (1992). Collaboration and Control: Crisis Management and +Multimedia Technology in London Underground Line Control Rooms. Computer Supported +Cooperative Work (CSCW), vol. 1, pp. 69–94.Heinzelman, Jessica and Carol Waters. (2010). Crowdsourcing Crisis Information in Disaster- +Affected Haiti. Special Report. Washington, D.C.: United States Institute of Peace.Heipke, Christian (2010). Crowdsourcing Geospatial Data. ISPRS Journal of Photogrammetry +and Remote Sensing, vol. 65, no. 6, pp. 550–557.Hester, Vaughn, Aaron Shaw, and Lukas Biewald (2010). Scalable crisis relief: Crowdsourced +SMS translation and categorization with Mission 4636. In Proceedings of the First ACM +Symposium on Computing for Development (ACM DEV '10). ACM, New York, NY, USA,15, 7 pages. +Hines, Megan, Abigail Benson, David Govoni, Derek Masaki, Barbara Poore, Annie Simpson, +and Steven Tessler (2013). Partnering for Science; Proceedings of the USGS Workshop on +Citizen Science. U.S. Geological Survey Open-File Report 2013–1234, +http://pubs.usgs.gov/of/2013/1234/. +Howe, Jeff (2006). The Rise of Crowdsourcing. Wired Magazine, vol. 14, pp. 1–4.Howe, Jeff (2008). Crowdsourcing: Why the Power of the Crowd is Driving the Future of +Business. New York: Crown Business.Hughes, Amanda and Leysia Palen, (2009). Twitter Adoption and Use in Mass Convergence +and Emergency Events. Proceedings of the 2009 Information Systems for Crisis Response and +Management Conference, (ISCRAM 2009). +Hughes, Amanda, Leysia Palen, Jeannette Sutton, Sophia B. Liu, and Sarah Vieweg (2008). +“Site-Seeing” in Disaster: An Examination of On-Line Social Convergence. Proceedings of the +Information Systems for Crisis Response and Management Conference (ISCRAM 2008). +Jackson, Steven P., William Mullen, Peggy Agouris, Andrew Crooks, Arie Croitoru, and +Anthony Stefanidis (2013). Assessing Completeness and Spatial Error of Features in +Volunteered Geographic Information. ISPRS International Journal of Geo-Information, vol. +2, no. 2, pp. 507–530.Kendra, James M. and Tricia Wachtendorf (2003). Reconsidering Convergence and +Converger: Legitimacy in Response to the World Trade Center Disaster. Research in Social +Problems and Public Policy, vol. 11, pp. 97–122. +Kreps, Gary A. and Susan Lovegren Bosworth. (1994). Organizing, Role Enactment, and +Disaster: A Structural Theory. Cranbury, NJ: Associated University Presses.Lewis, Clayton H. (1982). Using the “Thinking Aloud” Method In Cognitive Interface Design. +IBM Technical Research Report RC 9265, Yorktown Heights, NY.Little, Greg, Lydia B. Chilton, Max Goldman, and Robert C. Miller (2010). Exploring iterative +and parallel human computation processes. In Proceedings of the ACM SIGKDD Workshop on +Human Computation (HCOMP '10). ACM, New York, NY, USA, pp. 68–76. +Liu, Sophia B. (2010). Trends in Distributed Curatorial Technology to Manage Data in a +Networked World. UPGRADE Journal Emerging Information Technologies, vol. XI, no. 3, pp. +18–24. +Liu, Sophia B. (2011). Grassroots Heritage: A Multi-Method Investigation of How Social +Media Sustain the Living Heritage of Historic Crises. PhD dissertation. University of Colorado +at Boulder, Colorado: Alliance for Technology, Learning, and Society (ATLAS) Institute. +Liu, Sophia B. (2012). “Socially Distributed Curation of the Bhopal Disaster: A Case of +Grassroots Heritage in the Crisis Context.” In Elisa Giaccardi (Ed.), Heritage and Social +Media: Understanding and Experiencing Heritage in a Participatory Culture, Cambridge, UK: +Routledge.Liu, Sophia B. and Jen Ziemke. (2012). From Cultures of Participation to the Rise of Crisis +Mapping in a Networked World. In Aaron Delwiche and Jennifer Henderson (eds), The +Routledge Handbook of Participatory Cultures, New York: Routledge, pp. 185–196.Liu, Sophia B. and Leysia Palen. (2010). The New Cartographers: Crisis Map Mashups and the +Emergence of Neogeographic Practice. Cartography and Geographic Information Science +(CaGIS) Journal, 7(1): 69–90.Liu, Sophia B., Barbara S. Poore, Richard J. Snell, Aubrey Goodman, Nathaniel G. Plant, +Hilary Stockdon, Karen L. Morgan, and M. Dennis Krohn (2014). USGS iCoast – Did the Coast +Change? Designing a Crisis Crowdsourcing App to Validate Coastal Change Models. In +Proceedings of the companion publication of the 17th ACM conference on Computer +supported cooperative work & social computing (CSCW Companion '14). ACM, New York, +NY, USA, pp. 17–20. +Liu, Sophia B., Beau Bouchard, Daniel Bowden, Michelle Guy, and Paul Earle (2012). USGS +Tweet Earthquake Dispatch (@USGSted): Using Twitter for Earthquake Detection and +Characterization. Poster presented at the American Geophysical Union (AGU) 2012 Annual +Meeting for the “Citizen Empowered Seismology” paper session in San Francisco, CA. +http://fallmeeting.agu.org/2012/eposters/eposter/s21a-2431/. +Maisonneuve, Nicolas and Bastien Chopard (2012). Crowdsourcing satellite imagery analysis: +study of parallel and iterative models. Geographic Information Science, Lecture Notes in +Computer Science, vol. 7478, pp. 116–131. +Mark, Gloria, Mossaab Bagdouri, Leysia Palen, James Martin, Ban Al-Ani, and Kenneth +Anderson (2012). Blogs as a collective war diary. In Proceedings of the ACM 2012 conference +on Computer Supported Cooperative Work (CSCW '12). ACM, New York, NY, USA, pp. 37– +46. +Martineau, Eric (2012). A Typology of Crowdsourcing Participation Styles. Masters thesis. +Concordia University. +Meier, Patrick (2011). Verifying Crowdsourced Social Media Reports for Live Crisis Mapping: +An Introduction to Information Forensics. iRevolution blog. +http://irevolution.files.wordpress.com/2011/11/meier-verifying-crowdsourced-data- +casestudies.pdf. Accessed on December 29, 2011. +Meier, Patrick and Robert Munro (2010). The Unprecedented Role of SMS in Disaster +Response: Learning from Haiti. SAIS Review of International Affairs, vol. 30, no. 2, pp. 91–13.Mendonça, David (2007). Decision support for improvisation in response to extreme events: +Learning from the response to the 2011 World Trade Center attack. Decision Support Systems, +vol. 43, no. 3, pp. 952–967.Munro, Robert (2012). Crowdsourcing and the Crisis-affected Community: Lessons Learned +and Looking Forward from Mission 4636. Journal of Information Retrieval. +Munro, Robert, Tyler Schnoebelen, Schuyler Erle (2013). Quality Analysis After Action Report +for the Crowdsourced Aerial Imagery Assessment Following Hurricane Sandy. Proceedings of +the 10th International ISCRAM Conference. Available: http://idibon.com/wp- +content/uploads/2013/05/ISCRAM2013_Paper.pdf. +Newman, Greg, Andrea Wiggins, Alycia Crall, Eric Graham, Sarah Newman, and Kevin +Crowston (2012). The Future of Citizen Science: Emerging Technologies and Shifting +Paradigms. Frontiers in Ecology and the Environment, vol. 19, no. 6, pp. 298–304.Newman, Greg, Jim Graham, Alycia Crall, and Melinda Laituri (2011). The Art and Science of +Multi-Scale Citizen Science Support. Ecological Informatics, vol. 6, no. 3–4, pp. 217–227.Nourbakhsh, Illah, Randy Sargent, Anne Wright, Kathryn Cramer, Brian McClendon, and +Michael Jones (2006). Mapping disaster zones. Nature, vol. 439, pp. 787–788.Palen, Leysia and Sophia B. Liu (2007). Citizen Communications in Crisis: Anticipating a +Future of ICT-Supported Participation. Proceedings of the 2007 ACM Conference on Human +Factors in Computing System (CHI 2007). ACM, New York, NY, pp. 727–736.Palen, Leysia, Kenneth M. Anderson, Gloria Mark, James Martin, Douglas Sicker, Martha +Palmer, and Dirk Grunwald (2010). A vision for technology-mediated support for public +participation and assistance in mass emergencies and disasters. In Proceedings of the 2010 +ACM-BCS Visions of Computer Science Conference (ACM-BCS '10). British Computer Society, +Swinton, UK, 8, 12 pages. +Palen, Leysia, Sarah Vieweg, Sophia B. Liu, and Amanda Hughes (2009). Crisis in a +Networked World: Features of Computer- Mediated Communication in the April 16, 2007 +Virginia Tech Event. Social Science Computing Review, Sage, vol. 27, no. 4, pp. 467–480. +Plant, Nathaniel G. and Hilary F. Stockdon (2012). Probabilistic prediction of barrier-island +response to hurricanes. Journal of Geophysical Research, vol. 117, no. F3, pp. 2156–2202.Qu, Yan, Chen Huang, Pengyi Zhang, and Jun Zhang (2011). Microblogging after a major +disaster in China: A case study of the 2010 Yushu earthquake. In Proceedings of the ACM +2011 conference on Computer supported cooperative work (CSCW '11). ACM, New York, NY, +USA, pp. 25–34. +Quarantelli, E.L. and Russell R. Dynes (1977). Response to Social Crisis and Disaster. Annual +Review of Sociology, vol. 3, pp. 23–49.Roberts, Shadrock, Stephanie Grosser, and D. Ben Swartley (2012). Crowdsourcing to Geocode +Development Credit Authority Data: A Case Study. Washington, D.C.: U.S. Agency for +International Development. +http://transition.usaid.gov/our_work/economic_growth_and_trade/development_credit/pd +fs/2012/USAIDCrowdsourcingCaseStudy.pdf. Accessed 13 March 2013. +Roche, Stephane, Eliane Propeck-Zimmermann, and Boris Mericskay (2011). GeoWeb and +Crisis Management: Issues and Perspectives of Volunteered Geographic Information. +GeoJournal, Netherlands: Springer, vol. 78, no. 1, pp. 21–40. +Rouse, Anne C. (2010). A Preliminary Taxonomy of Crowdsourcing. In Proceedings of the +2010 Australasian Conferences on Information Systems (ACIS) on World Wide Web Internet +And Web Information Systems. http://aisel.aisnet.org/acis2010/76/. +Sarcevic, Aleksandra, Leysia Palen, Joanne White, Kate Starbird, Mossaab Bagdouri, and +Kenneth Anderson (2012). “Beacons of Hope” in Decentralized Coordination: Learning from +On-the-Ground Medical Twitterers During the 2010 Haiti Earthquake. In Proceedings of the +ACM 2012 conference on Computer Supported Cooperative Work (CSCW '12). ACM, New +York, NY, USA, pp. 47–56. +Schenk, Eric and Claude Guittard (2011). Towards a Characterization of Crowdsourcing +Practices. Journal of Innovation Economics, vol. 7, no. 1, pp. 93–107.Schmidt, Kjeld (1993). Cooperative Work and its Articulation: Requirement for Computer +Support. Le Travail Humain, Presses Universitaires de France, vol. 57, no. 4, pp. 345–366 +Schmidt, Kjeld (1994). Modes and Meachanisms of Interaction in Cooperative Work: Outline +of a Conceptual Framework. Risø National Laboratory, Roskilde, Denmark. +Schmidt, Kjeld and Liam Bannon (1992). Taking CSCW seriously: Supporting articulation +work. Computer Supported Cooperative Work, vol. 1, no. 1–2, pp. 7–40. +Sharma, Ankit (2010). Crowdsourcing Critical Success Factor Model: Strategies to harness the +collective intelligence of the crowd. Working paper. +http://irevolution.files.wordpress.com/2010/05/working-paper1.pdf. Accessed on 3 July 2010. +Shirk, Jennifer L., Heidi L. Ballard, Candie C. Wilderman, Tina Phillips, Andrea Wiggins, +Rebecca Jordan, Ellen McCallie, Matthew Minarchek, Bruce V. Lewenstein, Marianne E. +Krasny and Rick Bonney (2012). Public participation in scientific research: A framework for +deliberate design. Ecology and Society, vol. 17, no. 2, pp. 29. +Simone, Carla, Monica Divitini, and Kjeld Schmidt (1995). A notation for malleable and +interoperable coordination mechanisms for CSCW systems. In Proceedings of conference on +Organizational computing systems (COCS '95), Nora Comstock and Clarence Ellis (eds), +ACM, New York, NY, USA, pp. 44–54. +Chapter Sletholt, Magnus Thorstein, Jo Hannay, Dietmar Pfahl, Hans Christian Benestad, and Hans +Petter Langtangen (2011). A literature review of agile practices and their effects in scientific +software development. In Proceedings of the 4th International Workshop on Software +Engineering for Computational Science and Engineering (SECSE '11). ACM, New York, NY, +USA, pp. 1–9. +Snow, Rion, Brendan O'Connor, Daniel Jurafsky, and Andrew Y. Ng (2008). Cheap and Fast-- +But Is It Good?: Evaluating Non-Expert Annotations for Natural Language Tasks. +Proceedings of the Conference on Empirical Methods in Natural Language Processing +(EMNLP '08). Association for Computational Linguistics, Stroudsburg, PA, USA, pp. 254–263. +Stallings, Robert A. and E.L. Quarantelli (1985). Emergent Citizen Groups and Emergency +Management. Public Administration Review, vol. 45, pp. 93–100.Star, Susan Leigh and James R. Griesemer (1989). Institutional ecology, ‘translations’ and +boundary objects: Amateurs and professionals in Berkeley’s Museum of Vertebrate Zoology, +1907-39. Social Studies of Science, vol. 19, no. 3, pp. 387–420.Starbird, Kate (2012). Crowdwork, Crisis and Convergence: How the Connected Crowd +Organizes Information During Mass Disruption Events. PhD dissertation. University of +Colorado at Boulder, Colorado: Alliance for Technology, Learning, and Society (ATLAS) +Institute. +Starbird, Kate (2013). Delivering Patients to Sacré Coeur: Collective Intelligence in Digital +Volunteer Communities. In Proceedings of the ACM 2012 Conference on Human Factors in +Computing Systems (CHI 2013), ACM, New York, NY, USA, pp. 801–810.Starbird, Kate and Leysia Palen (2013). Working and Sustaining the Virtual Disaster Desk. In +Proceedings of the ACM Conference on Computer Supported Cooperative Work, ACM, New +York, NY, USA, pp. 491–502. +Starbird, Kate and Leysia Palen. (2011). “Voluntweeters”: Self-Organizing by Digital Volunteers +in Times of Crisis. In Proceedings of the 2011 ACM Human Factors in Computing Systems +(CHI 2011), ACM, New York, NY, USA, pp. 1071–1080.Starbird, Kate, Leysia Palen, Amanda Hughes, and Sarah Vieweg (2010). Chatter on The Red: +What Hazards Threat Reveals about the Social Life of Microblogged Information. In +Proceedings of the ACM 2010 Conference on Computer Supported Cooperative Work (CSCW +2010), ACM, New York, NY, USA, pp. 241–250.Steven J. Jackson, Tarleton Gillespie, and Sandy Payette (2014). The policy knot: Re- +integrating policy, practice and design in CSCW studies of social computing. Proceedings of the +17th ACM conference on Computer supported cooperative work & social computing (CSCW +'14). ACM, New York, NY, USA, pp. 588–602. +Stockdon, Hilary F., Kara J. Doran, David M. Thompson, Kristin L. Sopkin, and Nathaniel G. +Plant (2013). National assessment of hurricane-induced coastal erosion hazards: Southeast +Atlantic Coast. U.S. Geological Survey Open–File Report 2013-1130. +http://pubs.usgs.gov/of/2013/1130. +Stockdon, Hilary F., Kara J. Doran, David M. Thompson, Kristin L. Sopkin, Nathaniel G. Plant, +and Asbury H. Sallenger (2012). National assessment of hurricane-induced coastal erosion +hazards—Gulf of Mexico. U.S. Geological Survey Open-File Report 2012–1084. +Strauss, Anselm (1985). Work and the division of labor. The Sociological Quarterly, JAI Press, +Inc., vol. 26, no. 1, pp. 1–19. +Strauss, Anselm (1988). The Articulation of Project Work: An Organizational Process. The +Sociological Quarterly, vol. 29, no. 2, pp. 163–178.Strauss, Anselm (1993). Continual Permutations of Actions. Aldine de Gruyter, New York.Suchman, Lucy (1987). Plans and Situated Actions: The Problem of Human-Machine +Communication. Cambridge: Cambridge University Press.Teraguchi, Masayoshi, Shin Saito, Tessa Lau, Masaki Ohno, Julian A Cerruti, and Hironobu +Takagi (2012). Crowdsourcing in Crisis Informatics for Disaster Relief. In Proceedings of the +Computer-Supported Cooperative Workshop on Collaboration and Crisis Informatics. +Available in the International Reports on Socio-Informatics, vol. 9, no. 2, pp. 61–66. +http://www.iisi.de/fileadmin/IISI/upload/IRSI/IRSI_Vol9-Iss2_2012-Collaboration-and- +Crisis-Informatics.pdf#page=61. +Tierney, Kathleen J., Michael K. Lindell, and Ronald W. Perry (2001). Facing the Unexpected: +Disaster Preparedness and Response in the United States. Washington, DC: Joseph Henry +Press/National Academy Press.Trumbull, Deborah J., Rick Bonney, Derek Bascom, and Anna Cabral (2000). Thinking +scientifically during participation in a citizen-science project. Science Education, vol. 84, no. 2, +pp. 265–275.Turner, Andrew (2006). An Introduction to Neogeography. Sebastapol, CA: O’Reilly Media.Van der Windt, Peter (2012). From Crowdsourcing to Crowdseeding: The Cutting Edge of +Empowerment? Accessed 13 January 2014. +http://petervanderwindt.files.wordpress.com/2012/03/crowdseedingoup.pdf. +Vander Wal, Thomas (2004). Folksonomy. http://vanderwal.net/folksonomy.html. Accessed +15 January 2014. +Vieweg, Sarah, Amanda L. Hughes, Kate Starbird, and Leysia Palen (2010). Microblogging +during two natural hazards events: what twitter may contribute to situational awareness. In +Proceedings of the SIGCHI Conference on Human Factors in Computing Systems (CHI '10), +ACM, New York, NY, USA, pp. 1079–1088. +Vivacqua, Adriana S. and Marcos R.S. Borges (2012). Taking Advantage of Collective +Knowledge in Emergency Response Systems. Journal of Network and Computer Applications, +vol. 35, no. 1, pp. 189–198.Wachtendorf, Tricia and James M. Kendra (2005). Improvising Disaster in the City of Jazz: +Organizational Response to Hurricane Katrina. Understanding Katrina: Perspectives from the +Social Sciences. http://understandingkatrina.ssrc.org/Wachtendorf_Kendra/. Accessed 29 +February 2011. +Wald, David J., Paul S. Earle, Kuo-Wan Lin, Vincent Quitoriano, and Bruce Worden (2006). +Challenges in Rapid Ground Motion Estimation for the Prompt Assessment of Global Urban +Earthquakes. Bulletin of the Earthquake Research Institute, vol. 81, pp. 273–281.Wald, David J., Vincent Quitoriano, Bruce Worden, Margaret Hopper, and James W. Dewey +(2011). USGS “Did You Feel It?” Internet-based Macroseismic Intensity Maps. Annals of +Geophysics Special Section on Citizen Empowered Seismology, vol. 54, no. 6, pp. 688–707.Wald, David J., Vincent Quitoriano, Lori A. Dengler, and James W. Dewey. (1999a). +Utilization of the Internet for rapid community intensity maps. Seismological Research Letters +vol. 70, no. 6, pp. 680–697.Wald, David J., Vincent Quitoriano, Thomas H. Heaton, Hiroo Kanamori, Craig W. Scrivner, +and C. Bruce Worden (1999b). TriNet “ShakeMaps” – Rapid generation of peak groundmotion +and intensity maps for earthquakes in southern California. Earthquake Spectra, vol. 15, no. 3, +pp. 537–555.Warren, Jeffrey Yoo (2010). Grassroots mapping: Tools for participatory and activist +cartography. PhD dissertation. Massachusetts Institute of Technology. +Yates, Dave and Scott Paquette (2011). Emergency Knowledge Management and Social Media +Technologies: A Case Study of the 2010 Haitian Earthquake. International Journal of +Information Management, vol. 31, no. 1, pp. 6–13.Young, Jason C., David J. Wald, Paul S. Earle, and Lea A. Shanley (2013). Transforming +Earthquake Detection and Science Through Citizen Seismology. Washington, D.C.: Woodrow +Wilson International Center for Scholars.Ziemke, Jen (2012). Crisis Mapping: The Construction of a New Interdisciplinary Field? +Journal of Map & Geography Libraries, vol. 8, no. 2, pp. 101–117Zook, Matthew, Mark Graham, Taylor Shelton, and Sean Gorman (2010). Volunteered +Geographic Information and Crowdsourcing Disaster Relief: A Case Study of the Haitian +Earthquake. World Medical & Health Policy, vol. 2, no. 2, pp. 7–33.Download references diff --git a/research/outline.md b/research/outline.md new file mode 100644 index 0000000..b1e4ca5 --- /dev/null +++ b/research/outline.md @@ -0,0 +1,245 @@ +# Paper outline — preprint first, reviewed venue second + +## Plan + +**1. SocArXiv preprint.** Free, no endorsement system (unlike arXiv), no +institutional affiliation required — an OSF account and a working email is the +whole gate. Moderation is a five-point check that the work is scholarly and +correctly categorised; it is explicitly not peer review. Disciplinary fit is +good: this paper cites disaster sociology and crisis informatics, which is where +SocArXiv lives. Gives a citable, timestamped, permanent record with a DOI. + +*Note: the **generalist** OSF Preprints server was suspended indefinitely in +October 2025. Community servers including SocArXiv are unaffected and open. +Submit to SocArXiv specifically, not to "OSF Preprints".* + +**2. A reviewed venue afterwards.** A preprint is not peer review and does not +give us the thing we actually want. JORS states outright that preprinting is not +previous publication, and conference venues generally agree — so posting first +costs nothing. Candidates, in order: ISCRAM WiP (pending the attendance and +cost question), a CHI/CSCW/ICT4D workshop, JORS with an APC waiver requested in +the cover letter. + +**All six sections and the abstract are now drafted.** The remaining gate is the four `[ABSTRACT]` citation debts in §2 — Liu, Auferbauer, Kankanamge, Zhou. Zhou is readable in a browser (Bronze OA). The other three need an email or an interlibrary loan. **Do not post until they are cleared or their sentences weakened.** + +**Original rule, still standing:** The entire point of the +literature review was to avoid claiming novelty that is not there. Posting +publicly with that claim unverified is the specific failure we have been working +to prevent, and a preprint is permanent. + +## Status + +| Section | State | +| --- | --- | +| 1. Introduction | **drafted and sourced** — Harvey paragraph written from Smith et al. (2018) | +| 2. Background and related work | **drafted** — Fritz & Mathewson debt cleared; 4 `[ABSTRACT]` debts remain, listed in the draft | +| 3. Design | drafted; scheduler overstatement fixed | +| 4. What building it taught us | drafted | +| 5. Limitations | drafted | +| 6. Future work | drafted | +| Abstract | **drafted** — plus title and keywords | + +--- + +## Target venue notes — ISCRAM Work in Progress track + +Target: **ISCRAM 2027, WiP track.** The 2026 deadlines were 9 Jan (CoRe) and +23 Feb (WiP/PiP); the 2027 call is not published yet, so assume +**January–February 2027** and confirm when it appears. Length and template are +set by the CfP — do not guess them, and do not start formatting until it is out. + +WiP is the right track precisely because it does not require evaluation. Do not +submit to CoRe. We would be desk-rejected on the evaluation section and would +deserve it. + +**This file is an outline, not a draft.** Sections marked `[NO EVIDENCE]` are +things we would currently have to make up. They stay empty or get cut. + +--- + +## The claim, in the form it has to survive review + +Not *"nobody tracks the people who go in."* That is false and a reviewer will +know it. + +> Convergence of unaffiliated helpers is well theorised (Fritz & Mathewson 1957; +> Kendra & Wachtendorf 2003). The established mechanism for managing them is +> **credentialing by an authority**, which presupposes that an authority has +> arrived. In the interval before it does — and in events where it never +> meaningfully does — there is no accountability mechanism at all, and the +> literature proposes none. We report the design of a system that attempts +> accountability without a coordinator, using **silence rather than a +> supervisor** as the escalation trigger, and we report what that design costs. + +Contribution type: **design and rationale**, plus the failure modes we found +building it. Not a validated result. + +--- + +## Title candidates + +1. *Accounting for the Unaffiliated: Silence-Triggered Escalation for Volunteers + Who Self-Deploy* +2. *Nobody Is Coming to Check: Designing Volunteer Accountability Without a + Coordinator* +3. *Legible Without a Gatekeeper: A Self-Service Accountability Tool for + Converging Helpers* + +(1) is the most ISCRAM-ish. (2) is better writing and risks sounding like a blog +post. Decide late. + +--- + +## Abstract — skeleton, ~150 words + +Problem (convergence is old, credentialing presupposes an authority) → gap (the +interval before command exists) → what we built (one sentence) → mechanism +(silence, not supervision) → what we are *not* claiming (no deployment, no +users) → what the paper offers (design rationale and enumerated limits). + +Write this last. + +--- + +## 1. Introduction + +Open on the Weick/Perrow tension as Kendra & Wachtendorf state it — that +decentralisation presupposes prior socialisation, and that converging volunteers +are *"virtually by definition, strangers to the response milieu."* That is the +problem statement, already written by the field, and it earns us the right to +be in the conversation. + +Then the interval argument: credentialing is the answer, credentialing needs a +credentialer, and the first hours have neither. + +Motivating case: Hurricane Harvey, private boat owners self-deploying. **Verify +every factual claim about Harvey before it goes in.** Do not use a number we +have not sourced. + +State plainly, in the introduction and not buried: no deployment, no users, no +evaluation. + +## 2. Background and related work + +- **Convergence.** Fritz & Mathewson (1957) — five personal converger types, + external vs. internal convergence, personal/informational/materiel. Our users + are *helpers*, converging externally then internally. +- **Legitimacy.** Kendra & Wachtendorf — access is negotiated, not granted. The + key finding for us: the volunteers who got through were those who *"were able + to work with minimal supervision."* The scarce resource is emergency-manager + attention. +- **Digital volunteers.** Starbird & Palen (2011) — self-organising follows + resource → activity → task → domain. Note explicitly that their population is + remote by definition and therefore never needs accounting for. This is the + hinge of our argument; say it in one clear sentence, not three. +- **Doctrine.** FEMA spontaneous-volunteer guidance, ASPR TRACIE, Volunteer + Reception Centres. Practitioner sources belong here — citing doctrine + alongside literature is what makes a systems paper credible to this audience. +- **Taxonomy.** Liu (2014), crisis crowdsourcing framework. `[UNREAD]` — read + before writing this section and find out which box we are already in. If we + fit a box cleanly, say so and argue the design is the contribution, not the + idea. +- `[UNREAD]` Starbird dissertation (2012), convergence chapters. +- `[UNREAD]` Prior-art check on the two personnel-accountability patents. + +## 3. Design + +The system: Flask, SQLite, server-rendered, no account approval, no dispatcher. +33 routes, 6 tables. State the stack in two sentences and move on — the stack is +not the contribution. + +**The mechanism.** A responder joining a report gives an ETA (bounded 5–240 +minutes, warned above 120). Check-in interval defaults to 30 minutes. Silence +past the threshold marks them overdue; `SILENT_ESCALATE_MINUTES = 15` past that +files a report *about them*. No human decides this. + +**The design decisions worth a paragraph each** — each of these is a real +trade-off we made and can defend: + +1. **Silence as the trigger.** A coordinator noticing is the thing we cannot + assume. Absence of a signal is available where presence of a supervisor is + not. +2. **The switch has no scheduler.** It runs on read — whenever anyone loads the + board. This is deliberate: a timer can die silently, and a check nobody runs + is worse than no check. Cost: it depends on being watched. We made that cost + *visible* on the board rather than documenting it in a file nobody reads + (`SWEEP_EVERY_SECONDS = 30`; the board shows how long since the last sweep + and turns amber past five minutes). +3. **Status and contact are different facts.** What someone last told us is not + whether they are still answering. Conflating them lets a page show "on scene" + for someone forty-five minutes silent. Both are displayed; neither is + inferred from the other. +4. **Refusing to cache claims about other people.** The offline layer keeps your + own commitments and refuses the report feed and the board. A cached feed is a + list of who needed help twenty minutes ago, and acting on it sends someone to + an address already cleared. A test fails if either is added to the service + worker shell. +5. **Not storing triage answers.** They are health observations about a person + who never consented and is probably not in a position to. + +**Classifier**: multinomial naive Bayes, severity lexicon, LOOCV with a CI floor +asserted at 0.68. Keep this *short*. It is the least interesting part of the +system and the part most likely to attract a reviewer who wants it to be +something it isn't. One paragraph. Frame it as triage ordering, not prediction. + +## 4. What building it taught us + +This is the section that makes a WiP paper worth reading, and the one we can +actually fill. Candidates, all real: + +- The offline layer taught the caching rule the hard way — the interesting + finding is that *correct-when-written* and *correct-when-read* are different + guarantees, and disaster data has a short half-life between them. +- The dead man's switch started as a scheduled job in design and became + read-triggered because we could not honestly promise the scheduler would run. +- Making a limitation visible on screen is a different claim from documenting + it. Argue this generally: emergency software should surface its own liveness. +- Contention: three pages that exist to be watched all wrote to the database on + read, and broke under exactly the load they were built for. + +## 5. Limitations + +`docs/limits.md` — 18 named limitations, already written, already honest. +This is our strongest section and most papers' weakest. Lead with the two that +hurt most: + +- **It has never been used in a real disaster.** +- **The dead man's switch depends on being run.** + +Then no identity verification, self-reported location, overdue measures contact +not safety, one cautious responder can hold a report open, lockouts live in +memory. + +Add the one Kendra & Wachtendorf forces us to confront: **the literature treats +converging volunteers as a risk to be managed; we treat them as people owed an +accounting.** That is a moral position, not a finding, and the paper has to own +it rather than assume the reader shares it. + +## 6. Future work + +Honest and small. Five structured interviews with volunteer-response +coordinators would move this from WiP toward CoRe. Say that as a plan, not an +aspiration. + +--- + +## Before submission — checklist + +- [ ] **Get Liu (2014) full text — paywalled, abstract read, framework tables unseen.** + Email `sophialiu@usgs.gov` for a copy, or interlibrary loan. This is the + last real novelty risk; §2 stays `[UNREAD]` until it is closed. +- [ ] Read Starbird dissertation convergence chapters +- [ ] Prior-art check on the two accountability patents +- [ ] Verify every Harvey factual claim against a source +- [ ] Confirm ISCRAM 2027 CfP: deadline, track, page limit, template +- [ ] Decide authorship order with Sky, in writing, before drafting +- [ ] Disclose AI assistance per venue policy — check whether ISCRAM has one; + assume disclosure is required and write it either way +- [ ] Re-check every number in the paper against the repository at submission + time. The doc tests catch numbers in our own files; they will not catch a + stale number in a PDF. + +## What would make this a CoRe paper instead + +Real users, or expert interviews, or a deployment. Nothing else. No amount of +additional literature converts a design paper into an empirical one. diff --git a/start.sh b/start.sh index fa55e0c..b0dcc09 100755 --- a/start.sh +++ b/start.sh @@ -15,12 +15,18 @@ flask --app app seed # gunicorn, not the Flask dev server. The dev server is single-threaded, says # so in a warning on every boot, and would serve one visitor at a time. # -# Two workers on 512 MB: the classifier trains at import, so each worker -# carries its own copy — small, but not free. Threads handle the board and -# feed polling, which is almost all waiting on SQLite rather than computing. +# Worker count comes from the host, not from us. The classifier trains at +# import, so every worker carries its own copy — small, but not free, and on a +# 512 MB free instance two copies is enough to matter. Render announces the +# number it sized the box for (`WEB_CONCURRENCY=1`); hardcoding --workers 2 +# silently overrode that, and a container killed four seconds after boot looks +# exactly like a health check that never passed. Take the host's number. +# +# Threads handle the board and feed polling, which is almost all waiting on +# SQLite rather than computing, so they cost far less than workers do. exec gunicorn app:app \ --bind "0.0.0.0:${PORT:-10000}" \ - --workers 2 \ + --workers "${WEB_CONCURRENCY:-2}" \ --threads 4 \ --timeout 30 \ --access-logfile - \ diff --git a/static/scripts/board.js b/static/scripts/board.js index 19082c4..c21ca06 100644 --- a/static/scripts/board.js +++ b/static/scripts/board.js @@ -39,6 +39,22 @@ function rowHtml(r) { : "") : `not assigned`; + // aria-hidden, and not by oversight. This whole list sits in an + // aria-live="polite" region and is replaced wholesale every three + // seconds. A number that changes on every repaint would queue an + // announcement faster than a screen reader can speak one, burying the + // change that actually matters -- the state badge going OVERDUE -- under + // a stream of countdowns. Sighted users get the ticking clock; screen + // reader users get the badge and "last contact N min ago", which carry + // the same information without the churn. + const due = r.due_in_seconds === null || r.due_in_seconds === undefined + ? "" + : ``; + const ago = r.minutes_since_contact === null ? `no contact yet` : `last contact ${r.minutes_since_contact} min ago`; @@ -59,7 +75,7 @@ function rowHtml(r) { ${label(r.state)}
${doing}
-
${ago}${pos}
+
${due}${ago}${pos}
`; } diff --git a/static/scripts/map.js b/static/scripts/map.js index a770a78..e2ef9fb 100644 --- a/static/scripts/map.js +++ b/static/scripts/map.js @@ -193,6 +193,63 @@ function applyFilters(){ }); } +// --- finding your way back ----------------------------------------------- +// +// The map opens wherever it opens, and one stray scroll puts you over an +// ocean with no way back except reloading. Reports are the only thing on +// here worth looking at, so both buttons are about getting you to them: +// one shows all of them, the other walks through them one at a time. + +const fitBtn = document.getElementById("fit-all"); +const nextBtn = document.getElementById("next-incident"); +let cursor = -1; + +function shown(){ + return markers.filter(m => map.hasLayer(m)); +} + +function fitAll(){ + const visible = shown(); + if(!visible.length) return; + + map.fitBounds( + L.latLngBounds(visible.map(m => m.getLatLng())), + { padding: [50, 50], maxZoom: 15 } + ); + cursor = -1; + announce(`Showing all ${visible.length} reports.`); +} + +function nextIncident(){ + const visible = shown(); + if(!visible.length) return; + + cursor = (cursor + 1) % visible.length; + const marker = visible[cursor]; + + map.setView(marker.getLatLng(), 16); + marker.openPopup(); + announce(`Report ${cursor + 1} of ${visible.length}.`); +} + +// Moving the map is invisible to somebody using a screen reader, so say +// where we went. Polite: it must not interrupt anything being read. +function announce(message){ + let region = document.getElementById("map-said"); + if(!region){ + region = document.createElement("p"); + region.id = "map-said"; + region.className = "visually-hidden"; + region.setAttribute("role", "status"); + region.setAttribute("aria-live", "polite"); + document.body.appendChild(region); + } + region.textContent = message; +} + +if(fitBtn) fitBtn.addEventListener("click", fitAll); +if(nextBtn) nextBtn.addEventListener("click", nextIncident); + document.getElementById("search") .addEventListener("input",e=>{ search = e.target.value.toLowerCase(); @@ -284,7 +341,16 @@ function responderPopup(responder) { } fetch("/api/responders") - .then(res => res.json()) + .then(res => { + // fetch only rejects on a network failure. A 500 or a redirect to the + // login page resolves normally, and .json() then throws a parse error + // on the HTML — same banner, but nothing anywhere says which of the + // three happened. Reading the status is the difference between "no + // signal" and "the server is broken", and only one of those is fixed + // by moving somewhere with bars. + if (!res.ok) throw new Error(`/api/responders returned ${res.status}`); + return res.json(); + }) .then(responders => { responders.forEach(responder => { @@ -293,12 +359,18 @@ fetch("/api/responders") const { lat, lng } = responder.last_position; + // A hollow ring, because the legend says so and because colour + // is already spoken for. Red, blue and green on a teardrop mean + // whether anyone is coming to a place; the same three on a filled + // circle meant a person, and the two were indistinguishable at a + // glance. Shape carries person-or-place, colour carries state, + // and neither has to do both. const marker = L.circleMarker([lat, lng], { - radius: 8, + radius: 9, color: getResponderColor(responder.state), fillColor: getResponderColor(responder.state), - fillOpacity: 1, - weight: 2 + fillOpacity: 0.15, + weight: 3 }).addTo(map); marker.bindPopup(responderPopup(responder)); @@ -311,11 +383,23 @@ fetch("/api/responders") // when the network is bad — which is when somebody is most likely to // be staring at this screen. Failing quietly leaves a map that looks // complete and is missing every responder on it, so say so. - .catch(() => { + .catch(err => { + console.warn("responder positions unavailable:", err); + const warning = document.createElement("div"); warning.className = "map-warning"; warning.setAttribute("role", "status"); warning.textContent = "Could not load responder positions. Reports are still shown."; - document.body.appendChild(warning); + + // Above the map, not at the end of the document. Appending to body put + // it below the statistics cards, off the bottom of a phone screen — + // the map looked complete, was missing every responder, and the notice + // saying so was somewhere you had to scroll to find. + const canvas = document.getElementById("map"); + if (canvas && canvas.parentNode) { + canvas.parentNode.insertBefore(warning, canvas); + } else { + document.body.appendChild(warning); + } }); \ No newline at end of file diff --git a/static/styles/actions.css b/static/styles/actions.css index eafb466..33654ae 100644 --- a/static/styles/actions.css +++ b/static/styles/actions.css @@ -97,7 +97,7 @@ .vote.need_more{color:#f38ba8;} .vote.adequate{color:#a6e3a1;} .vote.overstaffed{color:#fab387;} -.vote.stood_down{color:#6c7086;} +.vote.stood_down{color:#a6adc8;} /* --- resolve --- */ @@ -159,7 +159,7 @@ } .responder .vote-tag{font-size:0.78rem;color:#fab387;} -.responder .caps{font-size:0.75rem;color:#45475a;margin-left:auto;} +.responder .caps{font-size:0.75rem;color:#a6adc8;margin-left:auto;} @media (max-width:560px){ .join-row{flex-direction:column;} @@ -234,3 +234,33 @@ quietly undone. */ color:#a6adc8; } + + +/* Somebody on this report who has stopped answering. + Peach rather than red: red on this page already means HIGH priority, and + a second red would read as another way of saying the same thing. This is a + different fact — the incident's severity has not changed, our contact with + a person has. */ +.overdue-warning{ + margin:0 0 14px; + padding:10px 12px; + border-left:3px solid var(--peach, #fab387); + background:rgba(250,179,135,.10); + color:var(--peach, #fab387); + font-weight:600; + font-size:0.9rem; +} + +.responder.is-overdue{ + border-left-color:var(--peach, #fab387); +} + +.overdue-tag{ + font-size:0.7rem; + letter-spacing:0.08em; + font-weight:700; + color:var(--peach, #fab387); + border:1px solid var(--peach, #fab387); + border-radius:4px; + padding:2px 6px; +} diff --git a/static/styles/board.css b/static/styles/board.css index 51714b7..7b883cf 100644 --- a/static/styles/board.css +++ b/static/styles/board.css @@ -208,14 +208,25 @@ body{ font-size:0.75rem;color:var(--peach); } -.idle{color:var(--overlay);font-size:0.85rem;} +.idle{color:var(--subtext);font-size:0.85rem;} .contact{text-align:right;font-size:0.8rem;color:var(--subtext);} .contact .ago{display:block;} -.contact .pos{display:block;margin-top:3px;font-family:ui-monospace,monospace;font-size:0.72rem;color:var(--overlay);} +.contact .pos{display:block;margin-top:3px;font-family:ui-monospace,monospace;font-size:0.72rem;color:var(--subtext);} .row.overdue .contact .ago{color:var(--red);font-weight:600;} +/* Time until this responder is expected to answer. The row above it states + the past — how long since we heard from them — and this one states the + future. Elapsed time has to be reasoned about; a number falling toward zero + does not. Tabular figures so it counts down in place instead of jittering. */ +.contact .due{ + display:block;margin-bottom:3px; + font-variant-numeric:tabular-nums; + color:var(--green);font-weight:600; +} +.contact .due.late{color:var(--red);} + .empty{color:var(--subtext);text-align:center;padding:40px 0;} @media (max-width:760px){ diff --git a/static/styles/disclaimer.css b/static/styles/disclaimer.css index b1b64f7..57aa1c9 100644 --- a/static/styles/disclaimer.css +++ b/static/styles/disclaimer.css @@ -93,7 +93,7 @@ em{color:#f9e2af;font-style:normal;} padding-top:20px; border-top:1px solid #313244; font-size:0.83rem; - color:#6c7086; + color:#a6adc8; } a{color:#89b4fa;} @@ -120,10 +120,10 @@ a{color:#89b4fa;} margin-top:26px; text-align:center; font-size:0.78rem; - color:#6c7086; + color:#a6adc8; } -.legal-link a{color:#6c7086;} +.legal-link a{color:#a6adc8;} .legal-link a:hover{color:#a6adc8;} /* The classifier's suggestion under the description box. Quiet — it is a diff --git a/static/styles/homepage.css b/static/styles/homepage.css index f9c02d1..911aa4c 100644 --- a/static/styles/homepage.css +++ b/static/styles/homepage.css @@ -154,6 +154,8 @@ gap:30px; } +.create-btn-mobile{ display:none; } + .create-btn{ background:var(--blue); @@ -252,6 +254,16 @@ gap:10px; @media(max-width:768px){ + /* Show the in-page button and hide the drawer's, so only one exists at + a time — display:none takes it out of the accessibility tree too. */ + .create-btn-mobile{ + display:block; + margin:0 16px 16px; + } + + aside .create-btn{ display:none; } + + .container{ grid-template-columns:1fr; @@ -387,13 +399,13 @@ gap:10px; font-size:.78rem; - color:#6c7086; + color:#a6adc8; } .legal-link a{ - color:#6c7086; + color:#a6adc8; } diff --git a/static/styles/login.css b/static/styles/login.css index 5818a25..1681f60 100644 --- a/static/styles/login.css +++ b/static/styles/login.css @@ -302,13 +302,13 @@ body{ font-size:.78rem; - color:#6c7086; + color:#a6adc8; } .legal-link a{ - color:#6c7086; + color:#a6adc8; } diff --git a/static/styles/map.css b/static/styles/map.css index 7d44066..f0fd443 100644 --- a/static/styles/map.css +++ b/static/styles/map.css @@ -172,17 +172,9 @@ border-left:6px solid var(--green); border-radius:50%; -} - -.legend-marker.report{ - - background:var(--blue); - -} - -.legend-marker.responder{ - - background:var(--red); + /* Four items that wrap. Without this the swatches squash before the + labels do, and a legend of ovals explains nothing. */ + flex:none; } @@ -335,10 +327,43 @@ border-left:6px solid var(--green); 100% { box-shadow:0 2px 6px rgba(0,0,0,.5), 0 0 0 0 rgba(243,139,168,0); } } +/* The legend has to carry the same distinction the map does, and colour + cannot carry it. A responder's dot is coloured by *their* status, out of + the same red / blue / green the report pins use — an overdue responder is + red and so is a report nobody is going to. Two swatches that were both + --red made "Nobody going" and "Responder" indistinguishable, which is not a + palette mistake so much as the legend admitting the colour axis is already + full. + So the legend says it in shape, as the map already does: reports are + teardrops, responders are circles. Colour then means one thing per shape — + on a teardrop, whether anybody is going; on a circle, what that person is + doing. */ + +.legend-marker.nobody, +.legend-marker.coming, +.legend-marker.there{ + + /* Same geometry as .pin, at legend size. */ + border-radius:50% 50% 50% 0; + transform:rotate(-45deg); + +} + .legend-marker.nobody { background:var(--red, #f38ba8); } .legend-marker.coming { background:var(--blue, #89b4fa); } .legend-marker.there { background:var(--green, #a6e3a1); } +/* The neutral "available" grey getResponderColor() uses, deliberately not one + of the three above: no single swatch is honest about a marker whose colour + is read off the person. The ring is what makes it a circle at 12px, where + a bare dot and a rotated teardrop are hard to tell apart. */ +.legend-marker.responder{ + + background:transparent; + border:3px solid #a6adc8; + +} + .gaps-toggle{ /* 48px tall: this gets pressed on a phone, in the rain. */ min-height:48px; @@ -376,3 +401,27 @@ border-left:6px solid var(--green); @media (prefers-reduced-motion: reduce){ .pin-nobody{ animation:none; } } + + +/* Getting back to the reports. + Sized to the 44px touch target the rest of the app holds to, because the + person most likely to be lost on this map is on a phone. */ +.map-nav{ + min-height:44px; + padding:0 14px; + border:1px solid var(--overlay, #45475a); + border-radius:8px; + background:var(--surface, #313244); + color:var(--text, #cdd6f4); + font-size:0.85rem; + font-weight:600; + cursor:pointer; + white-space:nowrap; +} + +.map-nav:hover{ border-color:var(--blue, #89b4fa); } + +.map-nav:focus-visible{ + outline:3px solid var(--blue, #89b4fa); + outline-offset:2px; +} diff --git a/static/styles/offline.css b/static/styles/offline.css index b8e6d95..9692246 100644 --- a/static/styles/offline.css +++ b/static/styles/offline.css @@ -107,7 +107,7 @@ h2 { .asof { font-variant-numeric: tabular-nums; - color: var(--overlay); + color:var(--subtext); } .notcached { @@ -143,7 +143,7 @@ h2 { .foot { margin: 32px 0 0; font-size: 0.75rem; - color: var(--overlay); + color:var(--subtext); } .foot a { color: var(--subtext); } diff --git a/static/styles/signup.css b/static/styles/signup.css index 8f5dddf..abb983c 100644 --- a/static/styles/signup.css +++ b/static/styles/signup.css @@ -332,13 +332,13 @@ body{ font-size:.78rem; - color:#6c7086; + color:#a6adc8; } .legal-link a{ - color:#6c7086; + color:#a6adc8; } diff --git a/static/styles/triage.css b/static/styles/triage.css index 7690a91..025626a 100644 --- a/static/styles/triage.css +++ b/static/styles/triage.css @@ -138,7 +138,7 @@ input[type=number]{ .use-btn:hover{background:var(--overlay);} .footnote{ - color:var(--overlay); + color:var(--subtext); font-size:0.78rem; line-height:1.5; margin-top:28px; diff --git a/templates/board.html b/templates/board.html index 9794c27..e2d96de 100644 --- a/templates/board.html +++ b/templates/board.html @@ -28,6 +28,11 @@ londo / diresq. Nothing here is real, and everything resets when the server sleeps — please don't type a real address into it. + {% if demo_speed > 1 %}
+ The clock is running {{ demo_speed }}× real time, so + check-in deadlines and the fifteen-minute silence escalation play out in + seconds. The mechanism is the production one; only the rate is scaled. + {% endif %}

{% endif %} @@ -133,6 +138,16 @@

{{ r.username }}

+ {% if r.due_in_seconds is not none %} + + {% endif %} {% if r.minutes_since_contact is not none %} last contact {{ r.minutes_since_contact }} min ago {% else %} diff --git a/templates/homepage.html b/templates/homepage.html index c89273d..568eb0d 100644 --- a/templates/homepage.html +++ b/templates/homepage.html @@ -29,6 +29,11 @@ londo / diresq. Nothing here is real, and everything resets when the server sleeps — please don't type a real address into it. + {% if demo_speed > 1 %}
+ The clock is running {{ demo_speed }}× real time, so + check-in deadlines and the fifteen-minute silence escalation play out in + seconds. The mechanism is the production one; only the rate is scaled. + {% endif %}

{% endif %} @@ -196,6 +201,15 @@

+ + + + Create Report + +