Run Debrief Ledger from your own code
Both metered lanes are available over HTTP and each returns one JSON object. The division of labour: the page parses the editions, files every entry through the signal gate, takes names out of the record, groups the entries into themes counted by edition, routes each theme, re-ranks the three menus and proposes the audit - all free, in ledgerkit.js. The run writes the trend read or the learning log; the page then holds the reply to its own board (ledgerreply.js). The log format, the occurrence bar and the menus are the source skill's own construction, not established organizer practice; every threshold is self-set.
Base URL and the response shape
Every endpoint lives under https://api.skillsafe.ai/v1/app-api, and every response has one shape:
{ "ok": true, "data": { ... } }
{ "ok": false, "error": { "code": "...", "message": "..." } }
The token is minted for this app (the guest call takes {"slug":"debrief-ledger"}), so no slug header is needed afterwards. Send it as Authorization: Bearer YOUR_TOKEN. The run body is the input object, sent bare.
| Status | Code | Meaning |
|---|---|---|
| 400 | validation_error | The body is not a JSON object, or a required key (task, event, logs, facts) is missing. |
| 401 | unauthorized | No token, or a stale one. Mint a guest token or sign in again. |
| 402 | insufficient_credits | The balance is under min_credits. Price with /estimate first. |
| 403 | forbidden | A guest token tried to run: both lanes are metered and need a personal sign-in. |
| 404 | not_found | Unknown job id. |
| 429 | rate_limited | Back off and retry. |
| 5xx | server_error | Transient. Retry with the same Idempotency-Key so a retry never double-bills. |
The task field comes first
Two lanes, chosen by task:
trends- before next edition's plan is written: the verdict, every recurring theme with its count, label, evidence and route, one deliberate change per theme in three parts (at most three, only where the page opened a slot), the hand-offs that are not this skill's, the three menu picks with the answer behind each, a 2-3 KPI shortlist and the closure line. The page offers it once two editions of records exist.log- the persisted learning log for a successor who was not in the room: every theme with its first-seen edition, count, label, status and Keep/Update/Consolidate/Replace/Delete call, an owner that is a role, what was filed but not counted, the changes carried, the opener and the moment they open it, the audit cadence and the zero-unclassified threshold, and a handover note. It works from one edition.
A missing or unknown task is answered as trends. Both lanes send the same four fields; for the log, the event field also lists the changes to carry, which the page fills from a trend read.
The input
| Field | Required | What |
|---|---|---|
task | yes | trends or log. If it is missing or neither, do trends and set "task": "trends". |
event | yes | the interview: editions run and with records, the record form, turnover and any handover this cycle, the entry form, comparable numbers, past deliberate changes, when planning starts, the mandate, the effort ceiling, where the log lives and who opens it, last cycle's changes with their outcomes, the KPIs as entered, and for the log the changes to carry. |
logs | yes | the debrief notes, one heading per edition and one line per entry with its id, already de-personalised by the page; a long paste has entries cut from the middle of an edition, and every cut is marked. |
facts | yes | the page's verdict, the honesty line, the editions, the signal gate, every theme with its count, label, route, status, disposition, owner and evidence, the vendors, the hand-offs, the change slots, the three menus with their picks, moves, deletions and notes, the KPI shortlist, the closure pass, the audit proposal and every finding tagged [fix], [check] or [info]. |
retry_note | no | optional; if present, your previous reply was unusable - follow it. |
The rules the model applies
- Say what is sourced and what is not. Published organizer practice reaches only this far: MLH's keeping-records guide covers the first handover (a running document, a reflection meeting, one handover to next year's team); DevOpsDays' organizing.md proves a shared, collectively edited document survives turnover but is no template for a trend log; Fraser and Mancl's 2023 report names the post-event retrospective as a practice for a conference series. The log format, the occurrence bar, the menus and every template are this skill's own construction, never established organizer practice. Every threshold is self-set. The filing gate is borrowed from printing-press-retro and the Keep/Update/Consolidate/Replace/Delete classification from ce-compound-refresh; say so where they appear.
- One edition is not a trend. With one edition of records the trend work stops: file this edition, start the log, come back next year. Take each debrief log as given; never re-run a single edition's analysis or reconstruct an entry that is too thin.
- The signal gate: an entry becomes a candidate only when it is current, reproducible in this event's own conditions, and generalizing. A one-time failure that was handled and cost nothing is expected work - filed with a one-line reason, never counted. A condition the event has left is closed with its reason, never deleted.
- De-personalise before anything persists: describe a condition, never a person. "One person forgot" happens once by definition; "no owner and no backup for this step" recurs and can be counted. Never carry a name into the record.
- Group before you count: cluster entries by what would have to change to prevent them, keep theme names stable, and count a theme's occurrences as the number of editions it appears in, never the number of entries. Two editions make a candidate; three make a pattern. Say which every time, and always state the denominator. A safety, code-of-conduct or legal exposure drops the bar.
- One deliberate change at a time per theme, in three parts: what changes, why the evidence justifies it, and how next edition will show whether it worked - observable, with a number where the quantity is measurable. Act on a candidate only when the fix is cheap, reversible and worth doing even if the pattern is noise.
- Route each change to its owner and never decide for it: operational to event-planning-timeline as a task; anything shaped like demand (return rate, sellout, sales pace, sponsor renewal) to event-market-fit as an observation, never an operational fix; anything naming a size ceiling to event-growth-strategy as evidence, never a recommendation; structural, recurring team load to event-team-structure with its count; a named supplier's recurring performance to event-vendor-sourcing on that vendor's own record. A cost line creeping across editions stays here; it is never event-budget's to re-model.
- The log is read before planning by one named person, at a named moment. "The team" produces a log nobody re-reads. The persisted log is itself a bus-factor mitigation; for a successor who was not in the room it carries the theme list, every live entry, the change records with outcomes, and what was tried and did not work.
- KPIs: 2 or 3, each with an owner and an action that moves it - a KPI missing either is dropped, not parked. Declare each threshold before reading it (self-set). A demand-shaped KPI still routes to event-market-fit. Keep an outcome log, appended after each event and re-opened at the kickoff pass.
- The one pass threshold: zero unclassified entries after an audit pass (self-set, binary). Every entry carries Keep, Update, Consolidate, Replace or Delete.
House rules
- Use only the input and the rules above. Copy the page's theme names, counts, labels, routes, statuses, dispositions, picks and verdict exactly. Every number in a sentence must appear in the input.
- Label anything that is not one of the rules above, and is not in the input, as your own design. Never present the log format, the occurrence bar or a threshold as established organizer practice.
- Never invent an entry, an edition, a person, a vendor or a number. Never name a person in the record: the logs are de-personalised and stay so; write about conditions and roles, refer to people as they, and never infer anyone's gender. The one named person allowed is the log's opener exactly as the input gives it.
- Never use backticks, never refer to this input's fields by their key names in a sentence, and never copy this prompt's narrative wording into a reply.
- Reply with ONLY one JSON object - no prose before or after, no code fences.
The replies
trends
summary- one sentence, at most 40 words: the verdict, the strongest recurring theme with its count and denominator, and the one change to make next.honesty- one sentence: which parts are published practice (name the sources) and which are this skill's own construction; thresholds are self-set.verdict- the page's verdict, exactly:pattern found,candidates only - hold one more editionorone edition - start the log.themes- one object per recurring theme in the page's order:theme(the page's name exactly),editions(the page's count, a number),label(candidateorpattern, the page's),evidence(short, one clause per edition from the logs, de-personalised),route(the page's route exactly).changes- at most 3 objects, one per theme, only for themes the page opened a change slot for:theme(exactly as named),change(what changes),why(why the evidence justifies it - say candidate or pattern),check(how next edition will show whether it worked, observable). Where last cycle's change on that theme did not improve it, the new change must differ.not_ours- one object per page hand-off:theme(the page's hand-off name exactly),route(the page's route exactly),why(one sentence: the evidence handed over, never the recipient's decision).menus-persistence,depth,audit, eachpick(the page's pick, exactly as named) andreason(one sentence naming the interview answer that moved it, or that nothing did).kpis- 2 or 3 objects:name,owner,action,threshold. Keep every KPI the page kept, as entered; when the page kept fewer than 2, add from the reported candidates with owner "to be named". Every threshold ends with "(self-set)".closure- one sentence on last cycle's deliberate changes: how many shipped, were checked and improved, or that there is nothing to close.caveats- at most 6 short strings: the[fix]findings first in the page's order, then the most important[check]findings.[]when there are none.
{
"task": "trends",
"summary": "one sentence",
"honesty": "one sentence",
"verdict": "pattern found",
"themes": [ { "theme": "the page's theme", "editions": 3, "label": "pattern", "evidence": "short", "route": "the page's route" } ],
"changes": [ { "theme": "the page's theme", "change": "one sentence", "why": "one sentence", "check": "one sentence" } ],
"not_ours": [ { "theme": "the page's hand-off", "route": "the page's route", "why": "one sentence" } ],
"menus": { "persistence": { "pick": "the page's pick", "reason": "one sentence" }, "depth": { "pick": "the page's pick", "reason": "one sentence" }, "audit": { "pick": "the page's pick", "reason": "one sentence" } },
"kpis": [ { "name": "a KPI", "owner": "a role or the named owner", "action": "what moves it", "threshold": "a threshold (self-set)" } ],
"closure": "one sentence",
"caveats": [ "a caveat" ]
}
The page holds it to its own board: the verdict, every recurring theme in order with its edition count, label and route, at most one change per theme and at most three, only on themes with a slot, each in three parts, every hand-off with its route, the three picks (never a deleted rung), the KPIs the page kept and none it dropped with self-set thresholds, and no number, name or gender the input does not hold.
log
title- a short title naming the event and the editions it covers.honesty- one sentence: published practice versus this skill's own construction; thresholds are self-set.entries- one object per page theme, in the page's order:theme,first_seen,occurrences,label,statusanddisposition(each the page's exactly; where the page left a theme unclassified, choose one of Keep, Update, Consolidate, Replace or Delete),owner(a role, never a person's name),next_check(short: what to look at, and when).not_counted- one object per entry the page filed as expected work, closed or too thin:entry(short, de-personalised),reason(the page's one-line reason).changes- one object per change to carry and per last-cycle change in the input, carried in that order:theme,change,check,outcome(for a carried change, "to be filled at the closure pass"; for last cycle's, the outcome the input gives).opener-person(the input's named opener exactly, or "to be named"),moment(the page's moment exactly).audit-cadence(the page's audit pick, exactly as named),threshold(one sentence: zero unclassified entries after an audit pass, self-set).outcome_log- one sentence: what to append after each event, and that it is re-opened at the kickoff pass.handover_note- two or three sentences for the successor: what the log is for, what to open first, and what was tried and did not work (when the input has any).
{
"task": "log",
"title": "Learning log - an event",
"honesty": "one sentence",
"entries": [ { "theme": "the page's theme", "first_seen": "the page's edition", "occurrences": "the page's count", "label": "pattern", "status": "the page's status", "disposition": "Consolidate", "owner": "a role", "next_check": "short" } ],
"not_counted": [ { "entry": "short", "reason": "the page's reason" } ],
"changes": [ { "theme": "a theme", "change": "one sentence", "check": "one sentence", "outcome": "short" } ],
"opener": { "person": "the named opener", "moment": "the page's moment" },
"audit": { "cadence": "the page's pick", "threshold": "one sentence" },
"outcome_log": "one sentence",
"handover_note": "two or three sentences"
}
The page requires every theme in order with its first-seen edition, occurrence count, label, status and disposition (a free choice of the five only where the page left one unclassified), an owner that is a role, the not-counted entries with their reasons, one change record per carried and last-cycle change, the opener exactly as given (or "to be named"), the page's moment and audit cadence, the zero-unclassified threshold, and - when a change failed - a handover note that says what was tried and did not work.
Worked examples - every lane, every sample
These are the page's three free samples (fictional events, vendors and people). Each input is exactly what the page sends - names already taken out; each reply is the saved reply the sample replays, shipped unedited; the last line is the page's own check.
Larchmere Code Fair (400 people, four editions) - trends
Verdict: pattern found; 4 editions of records; 8 themes, 4 recurring; 4 fix-level findings.
Input:
{
"task": "trends",
"event": "Event: Larchmere Code Fair; editions run 4, with written records 4 (Q1); the paste holds 4 editions with entries\nRecords today (Q2): one document per edition\nTurnover since the earliest record (Q3): some; a handover to different people this cycle: yes\nEntries (Q4): in the debrief's three-part form with owner and date: no; comparable numbers across editions: no; a past edition deliberately changed something because of a logged finding: yes\nPlanning (Q5): next edition's planning starts in a few months - kickoff 2027-01-15\nMandate (Q6): compounding, about 5 more editions\nEffort ceiling (Q7): 12 hours between editions; someone owns a between-edition job: no\nThe log (Q8): lives in the shared drive, Code Fair/learning-log.md; opened before planning by Odile Fenwarrow\nPeer network of independent chapters: no\nLast cycle's deliberate changes, as entered (1): 1. Printed the attendee list the morning of the event - shipped, did not improve - the 2025 queue was still 35 minutes\nKPIs, as entered (4): Peak check-in queue (minutes) | registration lead | open a second desk when it passes the threshold | under 15 minutes | no scope; Afternoon session overrun (minutes) | programme lead | hold a visible timer in every room | under 5 minutes | no scope; Social followers | the team | no action | no threshold | no scope; New vs returning attendee ratio | Odile Fenwarrow | pass the trend to the market-fit read | at least 1 in 3 returning | no scope",
"logs": "## Larchmere Code Fair 2023 debrief (E1, edition 1 of 4)\n- [E1.1] Quillfern Catering ran out of vegetarian lunches by 12:40; the queue for the rest stretched into the second session.\n- [E1.2] Venue wifi dropped twice during the morning keynote and the livestream froze both times.\n- [E1.3] Speaker's laptop wouldn't output to the projector; swapped to the backup machine, lost four minutes. Handled.\n- [E1.4] Loading dock at the old venue closed at 17:00, teardown ran past it and we paid an overtime fee.\n- [E1.5] Sponsor booths went well.\n- [E1.6] Swag.\n\n## Edition 2 (2024) (E2, edition 2 of 4)\n- [E2.1] Registration desk overwhelmed at 9am - the badge printer jammed and the line went out the door.\n- [E2.2] Talks ran 15 minutes late after lunch; nobody held the timer.\n- [E2.3] One organizer did everything for sponsors alone again and was exhausted by Saturday.\n- [E2.4] Fire alarm test at 11:00 was announced; no impact.\n\n## 2025 retro (E3, edition 3 of 4)\n- [E3.1] Badge pickup was a disaster for the third year in a row: one desk, 400 people, a 35-minute wait.\n- [E3.2] Quillfern Catering delivered lunch 50 minutes late and the afternoon started hungry.\n- [E3.3] Fewer returning attendees than last year - only 90 of 380 came back.\n- [E3.4] One organizer forgot to book the captioner, so the keynote had no captions.\n- [E3.5] Q&A overran in every afternoon slot.\n\n## 2026 (E4, edition 4 of 4)\n- [E4.1] Lanyards were sorted alphabetically but the opening queue still took 30 minutes - a single desk cannot clear more than 300 people before the first talk.\n- [E4.2] The volunteer rota had one point of contact and the single contact was unreachable on the day.\n- [E4.3] Sessions ran late again in the afternoon track.\n- [E4.4] The handover from the previous chair was a chat thread; two organizers burned out by the end.\n- [E4.5] Venue mics were fine all day.",
"facts": "Verdict: pattern found (4 editions of records; 2 pattern, 2 candidate, 4 one-off themes)\nHonesty line: Published organizer practice here is MLH's keeping-records guide, DevOpsDays' organizing.md and Fraser and Mancl's 2023 report; the log format, the occurrence bar, the menus and the templates are this skill's own construction, and every threshold is self-set.\nEditions (by year): E1 Larchmere Code Fair 2023 debrief [2023] - 6 entries; E2 Edition 2 (2024) [2024] - 4 entries; E3 2025 retro [2025] - 5 entries; E4 2026 [2026] - 5 entries\nLogs sent: 20 entries, de-personalised (2 names or handles replaced by \"one organizer\"); nothing cut\nSignal gate: 14 candidate, 2 expected, 1 closed, 1 thin, 2 positive, 0 duplicate\n- E1.3 expected: handled at no cost - expected work, kept with its reason, never counted - \"Speaker's laptop wouldn't output to the projector; swapped to the backup machine, lost...\"\n- E1.4 closed: not current - the condition is gone; closed with its reason so nobody re-files it - \"Loading dock at the old venue closed at 17:00, teardown ran past it and we paid an...\"\n- E1.5 positive: went well - not a failure finding - \"Sponsor booths went well.\"\n- E1.6 thin: too thin to file - the gap is noted, the edition is never reconstructed - \"Swag.\"\n- E2.4 expected: handled at no cost - expected work, kept with its reason, never counted - \"Fire alarm test at 11:00 was announced; no impact.\"\n- E4.5 positive: went well - not a failure finding - \"Venue mics were fine all day.\"\n- E2.3 de-personalised (Replace): \"One organizer did everything for sponsors alone again and was exhausted by Saturday.\" - condition: the workload sat with one person, with no backup and no sizing\n- E3.4 de-personalised (Replace): \"One organizer forgot to book the captioner, so the keynote had no captions.\" - condition: no owner, checklist or backup for this step - it rested on one person\n- E4.2 de-personalised (Replace): \"The volunteer rota had one point of contact and the single contact was unreachable on the day.\" - condition: a single point of contact with no documented fallback\nThemes (8, most editions first; recurrence counted by edition, never by entry):\n1. check-in and registration - 3 of 4 editions (2024, 2025, 2026) - pattern - route: event-planning-timeline - first seen 2024 - status: change shipped - did not improve - disposition: Consolidate (3 entries worded differently, merged; earliest first-seen kept, counted by edition) - owner: registration lead - evidence: 2024: Registration desk overwhelmed at 9am - the badge printer jammed and the line went out the door. | 2025: Badge pickup was a disaster for the third year in a row: one desk, 400 people, a 35-minute wait. | 2026: Lanyards were sorted alphabetically but the opening queue still took 30 minutes - a single desk cannot...\n2. schedule and timekeeping - 3 of 4 editions (2024, 2025, 2026) - pattern - route: event-planning-timeline - first seen 2024 - status: live - disposition: Consolidate (3 entries worded differently, merged; earliest first-seen kept, counted by edition) - owner: programme lead - evidence: 2024: Talks ran 15 minutes late after lunch; nobody held the timer. | 2025: Q&A overran in every afternoon slot. | 2026: Sessions ran late again in the afternoon track.\n3. catering and food - 2 of 4 editions (2023, 2025) - candidate - route: event-planning-timeline - first seen 2023 - status: not seen in the latest edition - disposition: Update (not seen in the latest edition - rewrite the condition, or close it with the reason) - owner: catering lead - evidence: 2023: Quillfern Catering ran out of vegetarian lunches by 12:40; the queue for the rest stretched into the second... | 2025: Quillfern Catering delivered lunch 50 minutes late and the afternoon started hungry.\n4. team load and handover - 2 of 4 editions (2024, 2026) - candidate - route: event-team-structure - first seen 2024 - status: routed to event-team-structure - disposition: Consolidate (2 entries worded differently, merged; earliest first-seen kept, counted by edition) - owner: lead organizer - evidence: 2024: One organizer did everything for sponsors alone again and was exhausted by Saturday. | 2026: The handover from the previous chair was a chat thread; two organizers burned out by the end.\n5. wifi and power - 1 of 4 editions (2023) - one-off - route: event-planning-timeline - first seen 2023 - status: not seen in the latest edition - disposition: Update (not seen in the latest edition - rewrite the condition, or close it with the reason) - owner: venue tech lead - evidence: 2023: Venue wifi dropped twice during the morning keynote and the livestream froze both times.\n6. attendance and return (demand) - 1 of 4 editions (2025) - one-off - route: event-market-fit - first seen 2025 - status: routed to event-market-fit - disposition: Update (not seen in the latest edition - rewrite the condition, or close it with the reason) - owner: whoever reads demand - evidence: 2025: Fewer returning attendees than last year - only 90 of 380 came back.\n7. accessibility - 1 of 4 editions (2025) - one-off - route: event-planning-timeline - first seen 2025 - status: not seen in the latest edition - disposition: Update (not seen in the latest edition - rewrite the condition, or close it with the reason) - owner: accessibility lead - evidence: 2025: One organizer forgot to book the captioner, so the keynote had no captions.\n8. volunteers and staffing - 1 of 4 editions (2026) - one-off - route: event-planning-timeline - first seen 2026 - status: live - disposition: Keep (still true, still live, count unchanged) - owner: volunteer coordinator - evidence: 2026: The volunteer rota had one point of contact and the single contact was unreachable on the day.\nRecurring themes for the trend read (4): check-in and registration; schedule and timekeeping; catering and food; team load and handover\nVendors named: Quillfern Catering - 2 of 4 editions (2023, 2025)\nHand-offs, not ours (4): check-in and registration (size evidence) -> event-growth-strategy (an entry names a ceiling (E4.1) - the ceiling and the evidence, never a recommendation about size); team load and handover -> event-team-structure (a structural finding that recurs (2 of 4 editions (2024, 2026)) - the count a single debrief could not produce; the persisted log is itself one bus-factor mitigation); attendance and return (demand) -> event-market-fit (demand-shaped, not operational - an observation for their read with its count (1 of 4 editions (2025)), never a causal claim); vendor: Quillfern Catering -> event-vendor-sourcing (named in 2 of 4 editions (2023, 2025) - a rebook-or-not verdict, filed on that vendor's own record where next edition's buyer will look)\nChange slots (one deliberate change per theme, at most 3): 1. check-in and registration - pattern - last cycle tried \"Printed the attendee list the morning of the event\" and it did not improve; 2. schedule and timekeeping - pattern; 3. catering and food - candidate - only if the fix is cheap and reversible\nMenu 1 - Log persistence posture (pick: Structured entry record): 1. Structured entry record [made the default by Q1: 4 editions of records (four or more); promoted by Q6: a compounding mandate with several editions left]; 2. Appended document; 3. Numeric series; 4. Carry-forward only. Notes: Q5, when planning starts, barely moves this menu - reshaping the record is not on the critical path, and a rushed schema is worse than an appended heading. Q8, who re-reads the log, does not move this menu - a better-structured record does not make anyone read it.\nMenu 2 - Trend-detection depth (pick: Theme grouping): 1. Theme grouping; 2. Written trend review [promoted by Q6 with Q7: a compounding mandate and room between editions]; 3. Recurrence count. Deleted, not demoted: Paired numeric read (Q4: no comparable numbers across editions)\nMenu 3 - Log-audit cadence (pick: Kickoff pass): 1. Kickoff pass; 2. Kickoff pass plus closure pass; 3. Standing audit owner [promoted by Q3: a handover to different people this cycle - the log's trustworthiness is due at handover, not at kickoff]; 4. Audit on read. Notes: Q8 does not move this menu - a better-structured record does not make anyone read it.\nKPI shortlist (2-3, each with a named owner and an action; thresholds self-set): kept Peak check-in queue (minutes) | registration lead | open a second desk when it passes the threshold | under 15 minutes; Afternoon session overrun (minutes) | programme lead | hold a visible timer in every room | under 5 minutes; New vs returning attendee ratio | Odile Fenwarrow | pass the trend to the market-fit read | at least 1 in 3 returning; dropped Social followers\nClosure pass: 1 deliberate change last cycle: 1 shipped, 1 checked, 0 improved (closure rate, self-set signal). 1. Printed the attendee list the morning of the event - shipped, did not improve - the 2025 queue was still 35 minutes\nAudit proposal: 1 Keep, 4 Update, 3 Consolidate, 0 Replace, 0 Delete, 0 unclassified. Pass threshold: Zero unclassified entries after an audit pass (self-set, binary) - holds.\nThe log opener: Odile Fenwarrow; the moment: before planning opens (kickoff 2027-01-15); audit cadence pick: Kickoff pass\nFindings (17):\n[fix] person_E2.3 (people): E2.3 names 1 person - the page files it as a condition: \"One organizer did everything for sponsors alone again and was exhausted by Saturday.\" (the workload sat with one person, with no backup and no sizing). A name never enters the log.\n[fix] person_E3.4 (people): E3.4 names 1 person - the page files it as a condition: \"One organizer forgot to book the captioner, so the keynote had no captions.\" (no owner, checklist or backup for this step - it rested on one person). A name never enters the log.\n[fix] person_E4.2 (people): E4.2 blames a role holder - the page files it as a condition: \"The volunteer rota had one point of contact and the single contact was unreachable on the day.\" (a single point of contact with no documented fallback). A name never enters the log.\n[fix] kpi_many (kpis): 4 KPIs listed - tracking many moves nothing. Keep 2-3.\n[check] thin_E1.6 (gate): E1.6 (2023) \"Swag.\" is too thin to file - note the gap; never reconstruct the edition it came from.\n[check] demand_demand (routing): \"attendance and return (demand)\" (1 of 4 editions (2025)) is demand-shaped, not operational - hand the observation to event-market-fit; an operational fix for a demand problem runs a beautiful event for an audience that stopped coming.\n[check] vendor_vendor-quillfern-catering (routing): Quillfern Catering recurs: named in 2 of 4 editions (2023, 2025) - a rebook-or-not verdict, filed on that vendor's own record where next edition's buyer will look.\n[check] kpi_drop_social-followers (kpis): \"Social followers\" has no named owner and no action - dropped, not parked.\n[check] tried_checkin (changes): Last cycle's change on \"check-in and registration\" did not improve it - the next change has to differ from \"Printed the attendee list the morning of the event\".\n[info] expected_E1.3 (gate): E1.3 filed as expected work (handled at no cost) - kept with its reason, never counted toward a recurrence.\n[info] closed_E1.4 (gate): E1.4 closed, not deleted - not current, so the next audit does not resurrect it.\n[info] expected_E2.4 (gate): E2.4 filed as expected work (handled at no cost) - kept with its reason, never counted toward a recurrence.\n[info] kpi_dem_new-vs-returning-attendee-ratio (kpis): \"New vs returning attendee ratio\" is demand-shaped - read it across editions here, hand the trend to event-market-fit.\n[info] candidates (themes): 2 candidate themes (\"catering and food\" and \"team load and handover\") - say \"candidate\" every time and hold it one more edition unless the fix is cheap, reversible and worth doing even if it is noise.\n[info] rotation (log): A handover to different people this cycle (Q3): write for the successor who is not in the room - carry the theme list, every live entry, the change records with outcomes, and what was tried and did not work.\n[info] loose (logs): Entries are looser than the debrief's three-part form (Q4) - the page files what is there and notes the gaps; it never reconstructs an edition.\n[info] honesty (honesty): Published organizer practice here is MLH's keeping-records guide, DevOpsDays' organizing.md and Fraser and Mancl's 2023 report; the log format, the occurrence bar, the menus and the templates are this skill's own construction, and every threshold is self-set."
}
Reply:
{
"task": "trends",
"summary": "Pattern found: check-in and registration failed in 3 of 4 editions and last cycle's printed attendee list did not fix it - next edition, add a second check-in desk rather than another list.",
"honesty": "Only MLH's keeping-records guide, DevOpsDays' organizing.md and Fraser and Mancl's 2023 report are published organizer practice; the occurrence bar, the log format, these menus and every threshold here are this skill's own construction and self-set.",
"verdict": "pattern found",
"themes": [
{
"theme": "check-in and registration",
"editions": 3,
"label": "pattern",
"evidence": "2024: the desk was overwhelmed, the badge printer jammed and the line went out the door; 2025: one desk for 400 people, a 35-minute wait; 2026: the opening queue still took 30 minutes at a single desk",
"route": "event-planning-timeline"
},
{
"theme": "schedule and timekeeping",
"editions": 3,
"label": "pattern",
"evidence": "2024: talks ran 15 minutes late and nobody held the timer; 2025: Q&A overran in every afternoon slot; 2026: sessions ran late again in the afternoon track",
"route": "event-planning-timeline"
},
{
"theme": "catering and food",
"editions": 2,
"label": "candidate",
"evidence": "2023: vegetarian lunches ran out by 12:40; 2025: lunch arrived 50 minutes late",
"route": "event-planning-timeline"
},
{
"theme": "team load and handover",
"editions": 2,
"label": "candidate",
"evidence": "2024: one organizer carried the sponsor work alone and was exhausted; 2026: the handover was a chat thread and two organizers burned out",
"route": "event-team-structure"
}
],
"changes": [
{
"theme": "check-in and registration",
"change": "Run a second check-in desk with its own scanner, and split badge pickup by surname between the two desks.",
"why": "A pattern in 3 of 4 editions, and last cycle's printed attendee list did not shorten the queue, so the condition is desk capacity, not the list.",
"check": "Peak queue length at the doors, observed at opening next edition, against the self-set threshold of under 15 minutes."
},
{
"theme": "schedule and timekeeping",
"change": "Give every afternoon room a visible timer and a timekeeper role, and close Q&A at the scheduled end of the slot.",
"why": "A pattern in 3 of 4 editions, always in the afternoon, and one entry says nobody held the timer.",
"check": "Overrun per afternoon session, logged by the timekeepers next edition, against the self-set threshold of under 5 minutes."
},
{
"theme": "catering and food",
"change": "Write the vegetarian share and a delivery time 30 minutes before lunch into the catering brief.",
"why": "Only a candidate, 2 of 4 editions, so it ships only because the fix is cheap, reversible and worth doing even if the pattern turns out to be noise.",
"check": "Whether any lunch option runs out, or lunch arrives after its scheduled start, observed at the serving line next edition."
}
],
"not_ours": [
{
"theme": "check-in and registration (size evidence)",
"route": "event-growth-strategy",
"why": "The 2026 entry says a single desk cannot clear more than 300 people before the first talk - the ceiling and its evidence, not a recommendation about size."
},
{
"theme": "team load and handover",
"route": "event-team-structure",
"why": "The same structural load recurs in 2 of 4 editions, a count no single debrief could show; the persisted log is itself one of the bus-factor mitigations."
},
{
"theme": "attendance and return (demand)",
"route": "event-market-fit",
"why": "Fewer returning attendees in 2025, 90 of 380, is a demand observation for their read, not something an operational fix answers."
},
{
"theme": "vendor: Quillfern Catering",
"route": "event-vendor-sourcing",
"why": "Named in 2 of 4 editions, for running out and for a late delivery - evidence for a rebook-or-not verdict on that vendor's own record."
}
],
"menus": {
"persistence": {
"pick": "Structured entry record",
"reason": "Four editions of records make it the default (Q1), and a compounding mandate with about 5 more editions promotes it further (Q6)."
},
"depth": {
"pick": "Theme grouping",
"reason": "The default holds; the written trend review moves up because the event compounds with 12 hours between editions (Q6 with Q7), and the paired numeric read is deleted for lack of comparable numbers (Q4)."
},
"audit": {
"pick": "Kickoff pass",
"reason": "The default holds; this cycle's handover to different people (Q3) promotes the standing audit owner one place, not to the top."
}
},
"kpis": [
{
"name": "Peak check-in queue (minutes)",
"owner": "registration lead",
"action": "open a second desk when it passes the threshold",
"threshold": "under 15 minutes (self-set)"
},
{
"name": "Afternoon session overrun (minutes)",
"owner": "programme lead",
"action": "hold a visible timer in every room",
"threshold": "under 5 minutes (self-set)"
},
{
"name": "New vs returning attendee ratio",
"owner": "Odile Fenwarrow",
"action": "pass the trend to the market-fit read",
"threshold": "at least 1 in 3 returning (self-set)"
}
],
"closure": "One deliberate change last cycle, the printed attendee list, shipped and was checked, and it did not improve the queue, which was still 35 minutes in 2025.",
"caveats": [
"Three entries named or blamed a person; the page files each as a condition, and no name enters the log.",
"4 KPIs were listed - keep 2-3; social followers is dropped for having no named owner and no action.",
"Swag in 2023 is too thin to file; the gap is noted, never reconstructed.",
"Returning attendees is a demand signal for event-market-fit, not an operational fix.",
"Quillfern Catering recurs in 2 of 4 editions - file the verdict on that vendor's own record.",
"The next check-in change has to differ from last cycle's printed attendee list."
]
}
The page's check: kept - nothing to flag
Larchmere Code Fair (400 people, four editions) - log
Verdict: pattern found; 4 editions of records; 8 themes, 4 recurring; 4 fix-level findings.
Input:
{
"task": "log",
"event": "Event: Larchmere Code Fair; editions run 4, with written records 4 (Q1); the paste holds 4 editions with entries\nRecords today (Q2): one document per edition\nTurnover since the earliest record (Q3): some; a handover to different people this cycle: yes\nEntries (Q4): in the debrief's three-part form with owner and date: no; comparable numbers across editions: no; a past edition deliberately changed something because of a logged finding: yes\nPlanning (Q5): next edition's planning starts in a few months - kickoff 2027-01-15\nMandate (Q6): compounding, about 5 more editions\nEffort ceiling (Q7): 12 hours between editions; someone owns a between-edition job: no\nThe log (Q8): lives in the shared drive, Code Fair/learning-log.md; opened before planning by Odile Fenwarrow\nPeer network of independent chapters: no\nLast cycle's deliberate changes, as entered (1): 1. Printed the attendee list the morning of the event - shipped, did not improve - the 2025 queue was still 35 minutes\nKPIs, as entered (4): Peak check-in queue (minutes) | registration lead | open a second desk when it passes the threshold | under 15 minutes | no scope; Afternoon session overrun (minutes) | programme lead | hold a visible timer in every room | under 5 minutes | no scope; Social followers | the team | no action | no threshold | no scope; New vs returning attendee ratio | Odile Fenwarrow | pass the trend to the market-fit read | at least 1 in 3 returning | no scope\nChanges to carry into the log (3): 1. check-in and registration | Run a second check-in desk with its own scanner, and split badge pickup by surname between the two desks. | Peak queue length at the doors, observed at opening next edition, against the self-set threshold of under 15 minutes.; 2. schedule and timekeeping | Give every afternoon room a visible timer and a timekeeper role, and close Q&A at the scheduled end of the slot. | Overrun per afternoon session, logged by the timekeepers next edition, against the self-set threshold of under 5 minutes.; 3. catering and food | Write the vegetarian share and a delivery time 30 minutes before lunch into the catering brief. | Whether any lunch option runs out, or lunch arrives after its scheduled start, observed at the serving line next edition.",
"logs": "## Larchmere Code Fair 2023 debrief (E1, edition 1 of 4)\n- [E1.1] Quillfern Catering ran out of vegetarian lunches by 12:40; the queue for the rest stretched into the second session.\n- [E1.2] Venue wifi dropped twice during the morning keynote and the livestream froze both times.\n- [E1.3] Speaker's laptop wouldn't output to the projector; swapped to the backup machine, lost four minutes. Handled.\n- [E1.4] Loading dock at the old venue closed at 17:00, teardown ran past it and we paid an overtime fee.\n- [E1.5] Sponsor booths went well.\n- [E1.6] Swag.\n\n## Edition 2 (2024) (E2, edition 2 of 4)\n- [E2.1] Registration desk overwhelmed at 9am - the badge printer jammed and the line went out the door.\n- [E2.2] Talks ran 15 minutes late after lunch; nobody held the timer.\n- [E2.3] One organizer did everything for sponsors alone again and was exhausted by Saturday.\n- [E2.4] Fire alarm test at 11:00 was announced; no impact.\n\n## 2025 retro (E3, edition 3 of 4)\n- [E3.1] Badge pickup was a disaster for the third year in a row: one desk, 400 people, a 35-minute wait.\n- [E3.2] Quillfern Catering delivered lunch 50 minutes late and the afternoon started hungry.\n- [E3.3] Fewer returning attendees than last year - only 90 of 380 came back.\n- [E3.4] One organizer forgot to book the captioner, so the keynote had no captions.\n- [E3.5] Q&A overran in every afternoon slot.\n\n## 2026 (E4, edition 4 of 4)\n- [E4.1] Lanyards were sorted alphabetically but the opening queue still took 30 minutes - a single desk cannot clear more than 300 people before the first talk.\n- [E4.2] The volunteer rota had one point of contact and the single contact was unreachable on the day.\n- [E4.3] Sessions ran late again in the afternoon track.\n- [E4.4] The handover from the previous chair was a chat thread; two organizers burned out by the end.\n- [E4.5] Venue mics were fine all day.",
"facts": "Verdict: pattern found (4 editions of records; 2 pattern, 2 candidate, 4 one-off themes)\nHonesty line: Published organizer practice here is MLH's keeping-records guide, DevOpsDays' organizing.md and Fraser and Mancl's 2023 report; the log format, the occurrence bar, the menus and the templates are this skill's own construction, and every threshold is self-set.\nEditions (by year): E1 Larchmere Code Fair 2023 debrief [2023] - 6 entries; E2 Edition 2 (2024) [2024] - 4 entries; E3 2025 retro [2025] - 5 entries; E4 2026 [2026] - 5 entries\nLogs sent: 20 entries, de-personalised (2 names or handles replaced by \"one organizer\"); nothing cut\nSignal gate: 14 candidate, 2 expected, 1 closed, 1 thin, 2 positive, 0 duplicate\n- E1.3 expected: handled at no cost - expected work, kept with its reason, never counted - \"Speaker's laptop wouldn't output to the projector; swapped to the backup machine, lost...\"\n- E1.4 closed: not current - the condition is gone; closed with its reason so nobody re-files it - \"Loading dock at the old venue closed at 17:00, teardown ran past it and we paid an...\"\n- E1.5 positive: went well - not a failure finding - \"Sponsor booths went well.\"\n- E1.6 thin: too thin to file - the gap is noted, the edition is never reconstructed - \"Swag.\"\n- E2.4 expected: handled at no cost - expected work, kept with its reason, never counted - \"Fire alarm test at 11:00 was announced; no impact.\"\n- E4.5 positive: went well - not a failure finding - \"Venue mics were fine all day.\"\n- E2.3 de-personalised (Replace): \"One organizer did everything for sponsors alone again and was exhausted by Saturday.\" - condition: the workload sat with one person, with no backup and no sizing\n- E3.4 de-personalised (Replace): \"One organizer forgot to book the captioner, so the keynote had no captions.\" - condition: no owner, checklist or backup for this step - it rested on one person\n- E4.2 de-personalised (Replace): \"The volunteer rota had one point of contact and the single contact was unreachable on the day.\" - condition: a single point of contact with no documented fallback\nThemes (8, most editions first; recurrence counted by edition, never by entry):\n1. check-in and registration - 3 of 4 editions (2024, 2025, 2026) - pattern - route: event-planning-timeline - first seen 2024 - status: change shipped - did not improve - disposition: Consolidate (3 entries worded differently, merged; earliest first-seen kept, counted by edition) - owner: registration lead - evidence: 2024: Registration desk overwhelmed at 9am - the badge printer jammed and the line went out the door. | 2025: Badge pickup was a disaster for the third year in a row: one desk, 400 people, a 35-minute wait. | 2026: Lanyards were sorted alphabetically but the opening queue still took 30 minutes - a single desk cannot...\n2. schedule and timekeeping - 3 of 4 editions (2024, 2025, 2026) - pattern - route: event-planning-timeline - first seen 2024 - status: live - disposition: Consolidate (3 entries worded differently, merged; earliest first-seen kept, counted by edition) - owner: programme lead - evidence: 2024: Talks ran 15 minutes late after lunch; nobody held the timer. | 2025: Q&A overran in every afternoon slot. | 2026: Sessions ran late again in the afternoon track.\n3. catering and food - 2 of 4 editions (2023, 2025) - candidate - route: event-planning-timeline - first seen 2023 - status: not seen in the latest edition - disposition: Update (not seen in the latest edition - rewrite the condition, or close it with the reason) - owner: catering lead - evidence: 2023: Quillfern Catering ran out of vegetarian lunches by 12:40; the queue for the rest stretched into the second... | 2025: Quillfern Catering delivered lunch 50 minutes late and the afternoon started hungry.\n4. team load and handover - 2 of 4 editions (2024, 2026) - candidate - route: event-team-structure - first seen 2024 - status: routed to event-team-structure - disposition: Consolidate (2 entries worded differently, merged; earliest first-seen kept, counted by edition) - owner: lead organizer - evidence: 2024: One organizer did everything for sponsors alone again and was exhausted by Saturday. | 2026: The handover from the previous chair was a chat thread; two organizers burned out by the end.\n5. wifi and power - 1 of 4 editions (2023) - one-off - route: event-planning-timeline - first seen 2023 - status: not seen in the latest edition - disposition: Update (not seen in the latest edition - rewrite the condition, or close it with the reason) - owner: venue tech lead - evidence: 2023: Venue wifi dropped twice during the morning keynote and the livestream froze both times.\n6. attendance and return (demand) - 1 of 4 editions (2025) - one-off - route: event-market-fit - first seen 2025 - status: routed to event-market-fit - disposition: Update (not seen in the latest edition - rewrite the condition, or close it with the reason) - owner: whoever reads demand - evidence: 2025: Fewer returning attendees than last year - only 90 of 380 came back.\n7. accessibility - 1 of 4 editions (2025) - one-off - route: event-planning-timeline - first seen 2025 - status: not seen in the latest edition - disposition: Update (not seen in the latest edition - rewrite the condition, or close it with the reason) - owner: accessibility lead - evidence: 2025: One organizer forgot to book the captioner, so the keynote had no captions.\n8. volunteers and staffing - 1 of 4 editions (2026) - one-off - route: event-planning-timeline - first seen 2026 - status: live - disposition: Keep (still true, still live, count unchanged) - owner: volunteer coordinator - evidence: 2026: The volunteer rota had one point of contact and the single contact was unreachable on the day.\nRecurring themes for the trend read (4): check-in and registration; schedule and timekeeping; catering and food; team load and handover\nVendors named: Quillfern Catering - 2 of 4 editions (2023, 2025)\nHand-offs, not ours (4): check-in and registration (size evidence) -> event-growth-strategy (an entry names a ceiling (E4.1) - the ceiling and the evidence, never a recommendation about size); team load and handover -> event-team-structure (a structural finding that recurs (2 of 4 editions (2024, 2026)) - the count a single debrief could not produce; the persisted log is itself one bus-factor mitigation); attendance and return (demand) -> event-market-fit (demand-shaped, not operational - an observation for their read with its count (1 of 4 editions (2025)), never a causal claim); vendor: Quillfern Catering -> event-vendor-sourcing (named in 2 of 4 editions (2023, 2025) - a rebook-or-not verdict, filed on that vendor's own record where next edition's buyer will look)\nChange slots (one deliberate change per theme, at most 3): 1. check-in and registration - pattern - last cycle tried \"Printed the attendee list the morning of the event\" and it did not improve; 2. schedule and timekeeping - pattern; 3. catering and food - candidate - only if the fix is cheap and reversible\nMenu 1 - Log persistence posture (pick: Structured entry record): 1. Structured entry record [made the default by Q1: 4 editions of records (four or more); promoted by Q6: a compounding mandate with several editions left]; 2. Appended document; 3. Numeric series; 4. Carry-forward only. Notes: Q5, when planning starts, barely moves this menu - reshaping the record is not on the critical path, and a rushed schema is worse than an appended heading. Q8, who re-reads the log, does not move this menu - a better-structured record does not make anyone read it.\nMenu 2 - Trend-detection depth (pick: Theme grouping): 1. Theme grouping; 2. Written trend review [promoted by Q6 with Q7: a compounding mandate and room between editions]; 3. Recurrence count. Deleted, not demoted: Paired numeric read (Q4: no comparable numbers across editions)\nMenu 3 - Log-audit cadence (pick: Kickoff pass): 1. Kickoff pass; 2. Kickoff pass plus closure pass; 3. Standing audit owner [promoted by Q3: a handover to different people this cycle - the log's trustworthiness is due at handover, not at kickoff]; 4. Audit on read. Notes: Q8 does not move this menu - a better-structured record does not make anyone read it.\nKPI shortlist (2-3, each with a named owner and an action; thresholds self-set): kept Peak check-in queue (minutes) | registration lead | open a second desk when it passes the threshold | under 15 minutes; Afternoon session overrun (minutes) | programme lead | hold a visible timer in every room | under 5 minutes; New vs returning attendee ratio | Odile Fenwarrow | pass the trend to the market-fit read | at least 1 in 3 returning; dropped Social followers\nClosure pass: 1 deliberate change last cycle: 1 shipped, 1 checked, 0 improved (closure rate, self-set signal). 1. Printed the attendee list the morning of the event - shipped, did not improve - the 2025 queue was still 35 minutes\nAudit proposal: 1 Keep, 4 Update, 3 Consolidate, 0 Replace, 0 Delete, 0 unclassified. Pass threshold: Zero unclassified entries after an audit pass (self-set, binary) - holds.\nThe log opener: Odile Fenwarrow; the moment: before planning opens (kickoff 2027-01-15); audit cadence pick: Kickoff pass\nFindings (17):\n[fix] person_E2.3 (people): E2.3 names 1 person - the page files it as a condition: \"One organizer did everything for sponsors alone again and was exhausted by Saturday.\" (the workload sat with one person, with no backup and no sizing). A name never enters the log.\n[fix] person_E3.4 (people): E3.4 names 1 person - the page files it as a condition: \"One organizer forgot to book the captioner, so the keynote had no captions.\" (no owner, checklist or backup for this step - it rested on one person). A name never enters the log.\n[fix] person_E4.2 (people): E4.2 blames a role holder - the page files it as a condition: \"The volunteer rota had one point of contact and the single contact was unreachable on the day.\" (a single point of contact with no documented fallback). A name never enters the log.\n[fix] kpi_many (kpis): 4 KPIs listed - tracking many moves nothing. Keep 2-3.\n[check] thin_E1.6 (gate): E1.6 (2023) \"Swag.\" is too thin to file - note the gap; never reconstruct the edition it came from.\n[check] demand_demand (routing): \"attendance and return (demand)\" (1 of 4 editions (2025)) is demand-shaped, not operational - hand the observation to event-market-fit; an operational fix for a demand problem runs a beautiful event for an audience that stopped coming.\n[check] vendor_vendor-quillfern-catering (routing): Quillfern Catering recurs: named in 2 of 4 editions (2023, 2025) - a rebook-or-not verdict, filed on that vendor's own record where next edition's buyer will look.\n[check] kpi_drop_social-followers (kpis): \"Social followers\" has no named owner and no action - dropped, not parked.\n[check] tried_checkin (changes): Last cycle's change on \"check-in and registration\" did not improve it - the next change has to differ from \"Printed the attendee list the morning of the event\".\n[info] expected_E1.3 (gate): E1.3 filed as expected work (handled at no cost) - kept with its reason, never counted toward a recurrence.\n[info] closed_E1.4 (gate): E1.4 closed, not deleted - not current, so the next audit does not resurrect it.\n[info] expected_E2.4 (gate): E2.4 filed as expected work (handled at no cost) - kept with its reason, never counted toward a recurrence.\n[info] kpi_dem_new-vs-returning-attendee-ratio (kpis): \"New vs returning attendee ratio\" is demand-shaped - read it across editions here, hand the trend to event-market-fit.\n[info] candidates (themes): 2 candidate themes (\"catering and food\" and \"team load and handover\") - say \"candidate\" every time and hold it one more edition unless the fix is cheap, reversible and worth doing even if it is noise.\n[info] rotation (log): A handover to different people this cycle (Q3): write for the successor who is not in the room - carry the theme list, every live entry, the change records with outcomes, and what was tried and did not work.\n[info] loose (logs): Entries are looser than the debrief's three-part form (Q4) - the page files what is there and notes the gaps; it never reconstructs an edition.\n[info] honesty (honesty): Published organizer practice here is MLH's keeping-records guide, DevOpsDays' organizing.md and Fraser and Mancl's 2023 report; the log format, the occurrence bar, the menus and the templates are this skill's own construction, and every threshold is self-set."
}
Reply:
{
"task": "log",
"title": "Larchmere Code Fair learning log - editions 2023 to 2026",
"honesty": "MLH's keeping-records guide, DevOpsDays' organizing.md and Fraser and Mancl's 2023 report are the only published practice behind this log; its format, the occurrence bar and the audit classification are this skill's own construction, and every threshold is self-set.",
"entries": [
{
"theme": "check-in and registration",
"first_seen": "2024",
"occurrences": "3 of 4 editions (2024, 2025, 2026)",
"label": "pattern",
"status": "change shipped - did not improve",
"disposition": "Consolidate",
"owner": "registration lead",
"next_check": "Peak queue at the doors at next edition's opening, under 15 minutes (self-set)."
},
{
"theme": "schedule and timekeeping",
"first_seen": "2024",
"occurrences": "3 of 4 editions (2024, 2025, 2026)",
"label": "pattern",
"status": "live",
"disposition": "Consolidate",
"owner": "programme lead",
"next_check": "Afternoon overrun per session next edition, under 5 minutes (self-set)."
},
{
"theme": "catering and food",
"first_seen": "2023",
"occurrences": "2 of 4 editions (2023, 2025)",
"label": "candidate",
"status": "not seen in the latest edition",
"disposition": "Update",
"owner": "catering lead",
"next_check": "Whether lunch runs out or arrives late next edition; rewrite the condition at the kickoff pass."
},
{
"theme": "team load and handover",
"first_seen": "2024",
"occurrences": "2 of 4 editions (2024, 2026)",
"label": "candidate",
"status": "routed to event-team-structure",
"disposition": "Consolidate",
"owner": "lead organizer",
"next_check": "Whether the sponsor work and the handover still rest on one person, at the closure pass after next edition."
},
{
"theme": "wifi and power",
"first_seen": "2023",
"occurrences": "1 of 4 editions (2023)",
"label": "one-off",
"status": "not seen in the latest edition",
"disposition": "Update",
"owner": "venue tech lead",
"next_check": "Close it with its reason at the kickoff pass unless the livestream drops again."
},
{
"theme": "attendance and return (demand)",
"first_seen": "2025",
"occurrences": "1 of 4 editions (2025)",
"label": "one-off",
"status": "routed to event-market-fit",
"disposition": "Update",
"owner": "whoever reads demand",
"next_check": "The returning share at next edition's registration, read by event-market-fit."
},
{
"theme": "accessibility",
"first_seen": "2025",
"occurrences": "1 of 4 editions (2025)",
"label": "one-off",
"status": "not seen in the latest edition",
"disposition": "Update",
"owner": "accessibility lead",
"next_check": "Whether captioning is booked with an owner and a backup before the programme is published."
},
{
"theme": "volunteers and staffing",
"first_seen": "2026",
"occurrences": "1 of 4 editions (2026)",
"label": "one-off",
"status": "live",
"disposition": "Keep",
"owner": "volunteer coordinator",
"next_check": "Whether the volunteer rota names a fallback contact before the event."
}
],
"not_counted": [
{
"entry": "2023: a speaker's laptop would not output to the projector; the backup machine took over",
"reason": "handled at no cost - expected work, kept with its reason, never counted"
},
{
"entry": "2023: the loading dock at the old venue closed before teardown ended",
"reason": "not current - the condition is gone; closed with its reason so nobody re-files it"
},
{
"entry": "2023: Swag.",
"reason": "too thin to file - the gap is noted, the edition is never reconstructed"
},
{
"entry": "2024: an announced fire alarm test",
"reason": "handled at no cost - expected work, kept with its reason, never counted"
}
],
"changes": [
{
"theme": "check-in and registration",
"change": "Run a second check-in desk with its own scanner, and split badge pickup by surname between the two desks.",
"check": "Peak queue length at the doors, observed at opening next edition, against the self-set threshold of under 15 minutes.",
"outcome": "to be filled at the closure pass"
},
{
"theme": "schedule and timekeeping",
"change": "Give every afternoon room a visible timer and a timekeeper role, and close Q&A at the scheduled end of the slot.",
"check": "Overrun per afternoon session, logged by the timekeepers next edition, against the self-set threshold of under 5 minutes.",
"outcome": "to be filled at the closure pass"
},
{
"theme": "catering and food",
"change": "Write the vegetarian share and a delivery time 30 minutes before lunch into the catering brief.",
"check": "Whether any lunch option runs out, or lunch arrives after its scheduled start, observed at the serving line next edition.",
"outcome": "to be filled at the closure pass"
},
{
"theme": "check-in and registration",
"change": "Printed the attendee list the morning of the event.",
"check": "The queue at the doors.",
"outcome": "shipped, did not improve - the 2025 queue was still 35 minutes"
}
],
"opener": {
"person": "Odile Fenwarrow",
"moment": "before planning opens (kickoff 2027-01-15)"
},
"audit": {
"cadence": "Kickoff pass",
"threshold": "Zero unclassified entries after an audit pass (self-set): every entry carries Keep, Update, Consolidate, Replace or Delete before planning opens."
},
"outcome_log": "After each edition, append the projects, collaborations, companies and jobs that came out of it, and re-open the list at the kickoff pass, since outcomes surface months later.",
"handover_note": "This log is what the team learned across four editions, written for whoever was not in the room; open the two patterns first, check-in and timekeeping. A printed attendee list was tried for check-in and did not work - the queue was still 35 minutes - so the next change adds desk capacity instead."
}
The page's check: kept - nothing to flag
Marrowby Data Day (120 people, two editions) - trends
Verdict: candidates only - hold one more edition; 2 editions of records; 4 themes, 2 recurring; 1 fix-level findings.
Input:
{
"task": "trends",
"event": "Event: Marrowby Data Day; editions run 2, with written records 2 (Q1); the paste holds 2 editions with entries\nRecords today (Q2): a chat thread\nTurnover since the earliest record (Q3): nobody; a handover to different people this cycle: no\nEntries (Q4): in the debrief's three-part form with owner and date: no; comparable numbers across editions: no; a past edition deliberately changed something because of a logged finding: no\nPlanning (Q5): next edition's planning starts within weeks\nMandate (Q6): compounding\nEffort ceiling (Q7): 6 hours between editions; someone owns a between-edition job: no\nThe log (Q8): lives in a place not named; opened before planning by nobody named yet\nPeer network of independent chapters: no\nLast cycle's deliberate changes, as entered (0): none\nKPIs, as entered (0): none",
"logs": "## Edition 1 (E1, edition 1 of 2)\n- [E1.1] The main room projector had no HDMI adapter for two speakers; we borrowed one from the venue after ten minutes.\n- [E1.2] Lunch queue took 25 minutes because there was one serving line for 120 people.\n- [E1.3] The CFP closed a week late and two talks were announced only five days before the event.\n- [E1.4] Coffee was great.\n\n## Edition 2 (E2, edition 2 of 2)\n- [E2.1] Again no USB-C adapter at the lectern - one speaker presented from a borrowed laptop.\n- [E2.2] One serving line at lunch again, a 20-minute wait.\n- [E2.3] Room signage pointed to the wrong floor for the workshop track all morning.\n- [E2.4] A volunteer stayed late to cover the cloakroom; handled, no impact.",
"facts": "Verdict: candidates only - hold one more edition (2 editions of records; 0 pattern, 2 candidate, 2 one-off themes)\nHonesty line: Published organizer practice here is MLH's keeping-records guide, DevOpsDays' organizing.md and Fraser and Mancl's 2023 report; the log format, the occurrence bar, the menus and the templates are this skill's own construction, and every threshold is self-set.\nEditions (by edition number): E1 Edition 1 [ed. 1] - 4 entries; E2 Edition 2 [ed. 2] - 4 entries\nLogs sent: 8 entries, de-personalised; nothing cut\nSignal gate: 6 candidate, 1 expected, 0 closed, 0 thin, 1 positive, 0 duplicate\n- E1.4 positive: went well - not a failure finding - \"Coffee was great.\"\n- E2.4 expected: handled at no cost - expected work, kept with its reason, never counted - \"A volunteer stayed late to cover the cloakroom; handled, no impact.\"\nThemes (4, most editions first; recurrence counted by edition, never by entry):\n1. catering and food - 2 of 2 editions (ed. 1, ed. 2) - candidate - route: event-planning-timeline - first seen ed. 1 - status: live - disposition: Consolidate (2 entries worded differently, merged; earliest first-seen kept, counted by edition) - owner: catering lead - evidence: ed. 1: Lunch queue took 25 minutes because there was one serving line for 120 people. | ed. 2: One serving line at lunch again, a 20-minute wait.\n2. AV and recording - 2 of 2 editions (ed. 1, ed. 2) - candidate - route: event-planning-timeline - first seen ed. 1 - status: live - disposition: Consolidate (2 entries worded differently, merged; earliest first-seen kept, counted by edition) - owner: AV lead - evidence: ed. 1: The main room projector had no HDMI adapter for two speakers; we borrowed one from the venue after ten... | ed. 2: Again no USB-C adapter at the lectern - one speaker presented from a borrowed laptop.\n3. speakers and programme - 1 of 2 editions (ed. 1) - one-off - route: event-planning-timeline - first seen ed. 1 - status: not seen in the latest edition - disposition: Update (not seen in the latest edition - rewrite the condition, or close it with the reason) - owner: programme lead - evidence: ed. 1: The CFP closed a week late and two talks were announced only five days before the event.\n4. venue, rooms and signage - 1 of 2 editions (ed. 2) - one-off - route: event-planning-timeline - first seen ed. 2 - status: live - disposition: Keep (still true, still live, count unchanged) - owner: venue lead - evidence: ed. 2: Room signage pointed to the wrong floor for the workshop track all morning.\nRecurring themes for the trend read (2): catering and food; AV and recording\nVendors named: none\nHand-offs, not ours (0): none\nChange slots (one deliberate change per theme, at most 3): 1. catering and food - candidate - only if the fix is cheap and reversible; 2. AV and recording - candidate - only if the fix is cheap and reversible\nMenu 1 - Log persistence posture (pick: Appended document): 1. Appended document [held as the default by Q7: 6 hours between editions (a low ceiling, at most 10, self-set)]; 2. Structured entry record [promoted by Q6: a compounding mandate with several editions left]; 3. Numeric series; 4. Carry-forward only. Notes: Q5, when planning starts, barely moves this menu - reshaping the record is not on the critical path, and a rushed schema is worse than an appended heading. Q7 forbids the retrofit: past editions stay as they were written; any richer record starts with the next edition. Q8, who re-reads the log, does not move this menu - a better-structured record does not make anyone read it.\nMenu 2 - Trend-detection depth (pick: Theme grouping): 1. Theme grouping; 2. Recurrence count. Deleted, not demoted: Written trend review (Q1: 2 editions of records - two editions delete the written trend review and cap every claim at candidate); Paired numeric read (Q4: no comparable numbers across editions). Notes: Q3: one team runs every edition - it has no theme-grouping problem yet, and a worse turnover one. Q5 leaves theme grouping as the default. Q7 leaves the default untouched - it costs one clustering pass.\nMenu 3 - Log-audit cadence (pick: Kickoff pass): 1. Kickoff pass [made the default by Q5: planning starts within weeks - run it now rather than scheduling it]; 2. Audit on read; 3. Standing audit owner. Deleted, not demoted: Kickoff pass plus closure pass (Q4: no past edition shipped a deliberate change - nothing to close yet). Notes: Q8 does not move this menu - a better-structured record does not make anyone read it.\nKPI shortlist (2-3, each with a named owner and an action; thresholds self-set): kept none; dropped none\nClosure pass: Nothing to close: no past edition deliberately changed something because of a logged finding (Q4).\nAudit proposal: 1 Keep, 1 Update, 2 Consolidate, 0 Replace, 0 Delete, 0 unclassified. Pass threshold: Zero unclassified entries after an audit pass (self-set, binary) - holds.\nThe log opener: to be named; the moment: before planning opens (within weeks); audit cadence pick: Kickoff pass (run it now)\nFindings (9):\n[fix] opener (log): \"the team\" is not a person - name the one person who opens the log before planning starts; \"the team\" is the answer that produces a log nobody re-reads.\n[info] expected_E2.4 (gate): E2.4 filed as expected work (handled at no cost) - kept with its reason, never counted toward a recurrence.\n[info] kpi_none (kpis): No KPIs entered - pick 2-3 from the reported candidates, each with an owner and an action; declare each threshold before reading it (self-set).\n[info] candidates (themes): 2 candidate themes (\"catering and food\" and \"AV and recording\") - say \"candidate\" every time and hold it one more edition unless the fix is cheap, reversible and worth doing even if it is noise.\n[info] two_editions (trends): Two editions of records - every claim is capped at candidate; two points draw a line through anything.\n[info] no_record (log): The records live in a chat thread (Q2) - the draft log below is the first persisted record; name it to the team as the bus-factor mitigation it is.\n[info] continuous (log): The same team every edition (Q3): memory partly substitutes for the log, which is the trap - it stays thin until the year someone leaves.\n[info] loose (logs): Entries are looser than the debrief's three-part form (Q4) - the page files what is there and notes the gaps; it never reconstructs an edition.\n[info] honesty (honesty): Published organizer practice here is MLH's keeping-records guide, DevOpsDays' organizing.md and Fraser and Mancl's 2023 report; the log format, the occurrence bar, the menus and the templates are this skill's own construction, and every threshold is self-set."
}
Reply:
{
"task": "trends",
"summary": "Candidates only - hold one more edition: catering and food and AV and recording each recur in 2 of 2 editions, so only cheap, reversible fixes ship, starting with a second lunch serving line.",
"honesty": "Published practice here is limited to MLH's keeping-records guide, DevOpsDays' organizing.md and Fraser and Mancl's 2023 report; the candidate-or-pattern bar, the log format and these menus are this skill's own construction, and every threshold is self-set.",
"verdict": "candidates only - hold one more edition",
"themes": [
{
"theme": "catering and food",
"editions": 2,
"label": "candidate",
"evidence": "ed. 1: one serving line for 120 people, a 25-minute lunch queue; ed. 2: one serving line again, a 20-minute wait",
"route": "event-planning-timeline"
},
{
"theme": "AV and recording",
"editions": 2,
"label": "candidate",
"evidence": "ed. 1: no HDMI adapter at the main room projector for two speakers; ed. 2: again no USB-C adapter at the lectern",
"route": "event-planning-timeline"
}
],
"changes": [
{
"theme": "catering and food",
"change": "Ask the venue for a second serving line at lunch.",
"why": "Still a candidate at 2 of 2 editions, but a second line is cheap, reversible and worth doing even if the queue was coincidence.",
"check": "The longest lunch wait next edition, timed at the serving line, against a self-set ceiling of under 20 minutes."
},
{
"theme": "AV and recording",
"change": "Keep a labelled adapter kit at every lectern, with both HDMI and USB-C, checked the morning of the event.",
"why": "A candidate at 2 of 2 editions; the kit costs little and can be dropped if the pattern turns out to be noise.",
"check": "Whether any speaker cannot connect at the lectern next edition, noted by the room host."
}
],
"not_ours": [],
"menus": {
"persistence": {
"pick": "Appended document",
"reason": "6 hours between editions is a low ceiling (Q7), which holds the default and forbids retrofitting the chat thread into a record."
},
"depth": {
"pick": "Theme grouping",
"reason": "Two editions of records delete the written trend review and cap every claim at candidate (Q1), and there are no comparable numbers for a paired read (Q4)."
},
"audit": {
"pick": "Kickoff pass",
"reason": "Planning starts within weeks (Q5), so the kickoff pass runs now; the closure pass is deleted because no past edition shipped a deliberate change (Q4)."
}
},
"kpis": [
{
"name": "Longest lunch wait (minutes)",
"owner": "to be named",
"action": "open a second serving line when it passes the threshold",
"threshold": "under 20 minutes (self-set)"
},
{
"name": "Satisfaction from a survey sent automatically after the event",
"owner": "to be named",
"action": "read it at the kickoff pass and act on the lowest-rated part",
"threshold": "declared before reading (self-set)"
}
],
"closure": "Nothing to close: no past edition deliberately changed something because of a logged finding.",
"caveats": [
"Name the one person who opens the log before planning starts - the team is not a person.",
"Both recurring themes are candidates on two editions; say candidate every time and confirm them at the next edition."
]
}
The page's check: kept - nothing to flag
Marrowby Data Day (120 people, two editions) - log
Verdict: candidates only - hold one more edition; 2 editions of records; 4 themes, 2 recurring; 1 fix-level findings.
Input:
{
"task": "log",
"event": "Event: Marrowby Data Day; editions run 2, with written records 2 (Q1); the paste holds 2 editions with entries\nRecords today (Q2): a chat thread\nTurnover since the earliest record (Q3): nobody; a handover to different people this cycle: no\nEntries (Q4): in the debrief's three-part form with owner and date: no; comparable numbers across editions: no; a past edition deliberately changed something because of a logged finding: no\nPlanning (Q5): next edition's planning starts within weeks\nMandate (Q6): compounding\nEffort ceiling (Q7): 6 hours between editions; someone owns a between-edition job: no\nThe log (Q8): lives in a place not named; opened before planning by nobody named yet\nPeer network of independent chapters: no\nLast cycle's deliberate changes, as entered (0): none\nKPIs, as entered (0): none\nChanges to carry into the log (2): 1. catering and food | Ask the venue for a second serving line at lunch. | The longest lunch wait next edition, timed at the serving line, against a self-set ceiling of under 20 minutes.; 2. AV and recording | Keep a labelled adapter kit at every lectern, with both HDMI and USB-C, checked the morning of the event. | Whether any speaker cannot connect at the lectern next edition, noted by the room host.",
"logs": "## Edition 1 (E1, edition 1 of 2)\n- [E1.1] The main room projector had no HDMI adapter for two speakers; we borrowed one from the venue after ten minutes.\n- [E1.2] Lunch queue took 25 minutes because there was one serving line for 120 people.\n- [E1.3] The CFP closed a week late and two talks were announced only five days before the event.\n- [E1.4] Coffee was great.\n\n## Edition 2 (E2, edition 2 of 2)\n- [E2.1] Again no USB-C adapter at the lectern - one speaker presented from a borrowed laptop.\n- [E2.2] One serving line at lunch again, a 20-minute wait.\n- [E2.3] Room signage pointed to the wrong floor for the workshop track all morning.\n- [E2.4] A volunteer stayed late to cover the cloakroom; handled, no impact.",
"facts": "Verdict: candidates only - hold one more edition (2 editions of records; 0 pattern, 2 candidate, 2 one-off themes)\nHonesty line: Published organizer practice here is MLH's keeping-records guide, DevOpsDays' organizing.md and Fraser and Mancl's 2023 report; the log format, the occurrence bar, the menus and the templates are this skill's own construction, and every threshold is self-set.\nEditions (by edition number): E1 Edition 1 [ed. 1] - 4 entries; E2 Edition 2 [ed. 2] - 4 entries\nLogs sent: 8 entries, de-personalised; nothing cut\nSignal gate: 6 candidate, 1 expected, 0 closed, 0 thin, 1 positive, 0 duplicate\n- E1.4 positive: went well - not a failure finding - \"Coffee was great.\"\n- E2.4 expected: handled at no cost - expected work, kept with its reason, never counted - \"A volunteer stayed late to cover the cloakroom; handled, no impact.\"\nThemes (4, most editions first; recurrence counted by edition, never by entry):\n1. catering and food - 2 of 2 editions (ed. 1, ed. 2) - candidate - route: event-planning-timeline - first seen ed. 1 - status: live - disposition: Consolidate (2 entries worded differently, merged; earliest first-seen kept, counted by edition) - owner: catering lead - evidence: ed. 1: Lunch queue took 25 minutes because there was one serving line for 120 people. | ed. 2: One serving line at lunch again, a 20-minute wait.\n2. AV and recording - 2 of 2 editions (ed. 1, ed. 2) - candidate - route: event-planning-timeline - first seen ed. 1 - status: live - disposition: Consolidate (2 entries worded differently, merged; earliest first-seen kept, counted by edition) - owner: AV lead - evidence: ed. 1: The main room projector had no HDMI adapter for two speakers; we borrowed one from the venue after ten... | ed. 2: Again no USB-C adapter at the lectern - one speaker presented from a borrowed laptop.\n3. speakers and programme - 1 of 2 editions (ed. 1) - one-off - route: event-planning-timeline - first seen ed. 1 - status: not seen in the latest edition - disposition: Update (not seen in the latest edition - rewrite the condition, or close it with the reason) - owner: programme lead - evidence: ed. 1: The CFP closed a week late and two talks were announced only five days before the event.\n4. venue, rooms and signage - 1 of 2 editions (ed. 2) - one-off - route: event-planning-timeline - first seen ed. 2 - status: live - disposition: Keep (still true, still live, count unchanged) - owner: venue lead - evidence: ed. 2: Room signage pointed to the wrong floor for the workshop track all morning.\nRecurring themes for the trend read (2): catering and food; AV and recording\nVendors named: none\nHand-offs, not ours (0): none\nChange slots (one deliberate change per theme, at most 3): 1. catering and food - candidate - only if the fix is cheap and reversible; 2. AV and recording - candidate - only if the fix is cheap and reversible\nMenu 1 - Log persistence posture (pick: Appended document): 1. Appended document [held as the default by Q7: 6 hours between editions (a low ceiling, at most 10, self-set)]; 2. Structured entry record [promoted by Q6: a compounding mandate with several editions left]; 3. Numeric series; 4. Carry-forward only. Notes: Q5, when planning starts, barely moves this menu - reshaping the record is not on the critical path, and a rushed schema is worse than an appended heading. Q7 forbids the retrofit: past editions stay as they were written; any richer record starts with the next edition. Q8, who re-reads the log, does not move this menu - a better-structured record does not make anyone read it.\nMenu 2 - Trend-detection depth (pick: Theme grouping): 1. Theme grouping; 2. Recurrence count. Deleted, not demoted: Written trend review (Q1: 2 editions of records - two editions delete the written trend review and cap every claim at candidate); Paired numeric read (Q4: no comparable numbers across editions). Notes: Q3: one team runs every edition - it has no theme-grouping problem yet, and a worse turnover one. Q5 leaves theme grouping as the default. Q7 leaves the default untouched - it costs one clustering pass.\nMenu 3 - Log-audit cadence (pick: Kickoff pass): 1. Kickoff pass [made the default by Q5: planning starts within weeks - run it now rather than scheduling it]; 2. Audit on read; 3. Standing audit owner. Deleted, not demoted: Kickoff pass plus closure pass (Q4: no past edition shipped a deliberate change - nothing to close yet). Notes: Q8 does not move this menu - a better-structured record does not make anyone read it.\nKPI shortlist (2-3, each with a named owner and an action; thresholds self-set): kept none; dropped none\nClosure pass: Nothing to close: no past edition deliberately changed something because of a logged finding (Q4).\nAudit proposal: 1 Keep, 1 Update, 2 Consolidate, 0 Replace, 0 Delete, 0 unclassified. Pass threshold: Zero unclassified entries after an audit pass (self-set, binary) - holds.\nThe log opener: to be named; the moment: before planning opens (within weeks); audit cadence pick: Kickoff pass (run it now)\nFindings (9):\n[fix] opener (log): \"the team\" is not a person - name the one person who opens the log before planning starts; \"the team\" is the answer that produces a log nobody re-reads.\n[info] expected_E2.4 (gate): E2.4 filed as expected work (handled at no cost) - kept with its reason, never counted toward a recurrence.\n[info] kpi_none (kpis): No KPIs entered - pick 2-3 from the reported candidates, each with an owner and an action; declare each threshold before reading it (self-set).\n[info] candidates (themes): 2 candidate themes (\"catering and food\" and \"AV and recording\") - say \"candidate\" every time and hold it one more edition unless the fix is cheap, reversible and worth doing even if it is noise.\n[info] two_editions (trends): Two editions of records - every claim is capped at candidate; two points draw a line through anything.\n[info] no_record (log): The records live in a chat thread (Q2) - the draft log below is the first persisted record; name it to the team as the bus-factor mitigation it is.\n[info] continuous (log): The same team every edition (Q3): memory partly substitutes for the log, which is the trap - it stays thin until the year someone leaves.\n[info] loose (logs): Entries are looser than the debrief's three-part form (Q4) - the page files what is there and notes the gaps; it never reconstructs an edition.\n[info] honesty (honesty): Published organizer practice here is MLH's keeping-records guide, DevOpsDays' organizing.md and Fraser and Mancl's 2023 report; the log format, the occurrence bar, the menus and the templates are this skill's own construction, and every threshold is self-set."
}
Reply:
{
"task": "log",
"title": "Marrowby Data Day learning log - editions 1 and 2",
"honesty": "Published practice behind this log is MLH's keeping-records guide, DevOpsDays' organizing.md and Fraser and Mancl's 2023 report; the format, the candidate-or-pattern bar and the audit classification are this skill's own construction, and every threshold is self-set.",
"entries": [
{
"theme": "catering and food",
"first_seen": "ed. 1",
"occurrences": "2 of 2 editions (ed. 1, ed. 2)",
"label": "candidate",
"status": "live",
"disposition": "Consolidate",
"owner": "catering lead",
"next_check": "The longest lunch wait at the next edition."
},
{
"theme": "AV and recording",
"first_seen": "ed. 1",
"occurrences": "2 of 2 editions (ed. 1, ed. 2)",
"label": "candidate",
"status": "live",
"disposition": "Consolidate",
"owner": "AV lead",
"next_check": "Whether every speaker connects at the lectern at the next edition."
},
{
"theme": "speakers and programme",
"first_seen": "ed. 1",
"occurrences": "1 of 2 editions (ed. 1)",
"label": "one-off",
"status": "not seen in the latest edition",
"disposition": "Update",
"owner": "programme lead",
"next_check": "Whether the call for papers closes on its published date; close the entry if it does."
},
{
"theme": "venue, rooms and signage",
"first_seen": "ed. 2",
"occurrences": "1 of 2 editions (ed. 2)",
"label": "one-off",
"status": "live",
"disposition": "Keep",
"owner": "venue lead",
"next_check": "A walk of the signage route the morning of the next edition."
}
],
"not_counted": [
{
"entry": "ed. 2: a gap at the cloakroom covered by a volunteer staying late",
"reason": "handled at no cost - expected work, kept with its reason, never counted"
}
],
"changes": [
{
"theme": "catering and food",
"change": "Ask the venue for a second serving line at lunch.",
"check": "The longest lunch wait next edition, timed at the serving line, against a self-set ceiling of under 20 minutes.",
"outcome": "to be filled at the closure pass"
},
{
"theme": "AV and recording",
"change": "Keep a labelled adapter kit at every lectern, with both HDMI and USB-C, checked the morning of the event.",
"check": "Whether any speaker cannot connect at the lectern next edition, noted by the room host.",
"outcome": "to be filled at the closure pass"
}
],
"opener": {
"person": "to be named",
"moment": "before planning opens (within weeks)"
},
"audit": {
"cadence": "Kickoff pass",
"threshold": "Zero unclassified entries after an audit pass (self-set); run the pass now, since planning starts within weeks."
},
"outcome_log": "Append what came out of each edition - projects, collaborations, jobs - and re-open it at the kickoff pass, because outcomes surface months later.",
"handover_note": "Both recurring themes are candidates on two editions, not patterns, so the changes are small and reversible. Name one person to open this log before planning; until then it is a document nobody is due to read."
}
The page's check: kept - nothing to flag
Fernwick Hack Night (one edition) - trends: not offered - one edition of records - the trend read needs two; file this edition and start the log instead.
Fernwick Hack Night (one edition) - log
Verdict: one edition - start the log; 1 editions of records; 5 themes, 0 recurring; 1 fix-level findings.
Input:
{
"task": "log",
"event": "Event: Fernwick Hack Night; editions run 1, with written records 1 (Q1); the paste holds 1 edition with entries\nRecords today (Q2): nothing written\nTurnover since the earliest record (Q3): nobody; a handover to different people this cycle: no\nEntries (Q4): in the debrief's three-part form with owner and date: no; comparable numbers across editions: no; a past edition deliberately changed something because of a logged finding: no\nPlanning (Q5): next edition's planning starts six months or more away\nMandate (Q6): compounding, about 3 more editions\nEffort ceiling (Q7): 4 hours between editions; someone owns a between-edition job: no\nThe log (Q8): lives in a pinned doc in the organizers' chat; opened before planning by Bram Quillet\nPeer network of independent chapters: no\nLast cycle's deliberate changes, as entered (0): none\nKPIs, as entered (0): none\nChanges to carry into the log (0): none",
"logs": "## Fernwick Hack Night - first edition debrief (E1, edition 1 of 1)\n- [E1.1] Power strips ran out by 19:30 and teams were sharing two sockets.\n- [E1.2] Judging ran 40 minutes over because the rubric arrived on the day.\n- [E1.3] Pizza arrived late; it was fine once it came.\n- [E1.4] Mentors were great.\n- [E1.5] Teams formed by friendship groups and three solo hackers never found a team.\n- [E1.6] Sign-in sheet got lost, so we do not know the final headcount.",
"facts": "Verdict: one edition - start the log (1 edition of records; 0 pattern, 0 candidate, 5 one-off themes)\nHonesty line: Published organizer practice here is MLH's keeping-records guide, DevOpsDays' organizing.md and Fraser and Mancl's 2023 report; the log format, the occurrence bar, the menus and the templates are this skill's own construction, and every threshold is self-set.\nEditions (paste order): E1 Fernwick Hack Night - first edition debrief [ed. 1] - 6 entries\nLogs sent: 6 entries, de-personalised; nothing cut\nSignal gate: 5 candidate, 0 expected, 0 closed, 0 thin, 1 positive, 0 duplicate\n- E1.4 positive: went well - not a failure finding - \"Mentors were great.\"\nThemes (5, most editions first; recurrence counted by edition, never by entry):\n1. check-in and registration - 1 of 1 edition (ed. 1) - one-off - route: event-planning-timeline - first seen ed. 1 - status: live - disposition: Keep (still true, still live, count unchanged) - owner: registration lead - evidence: ed. 1: Sign-in sheet got lost, so we do not know the final headcount.\n2. catering and food - 1 of 1 edition (ed. 1) - one-off - route: event-planning-timeline - first seen ed. 1 - status: live - disposition: Keep (still true, still live, count unchanged) - owner: catering lead - evidence: ed. 1: Pizza arrived late; it was fine once it came.\n3. wifi and power - 1 of 1 edition (ed. 1) - one-off - route: event-planning-timeline - first seen ed. 1 - status: live - disposition: Keep (still true, still live, count unchanged) - owner: venue tech lead - evidence: ed. 1: Power strips ran out by 19:30 and teams were sharing two sockets.\n4. schedule and timekeeping - 1 of 1 edition (ed. 1) - one-off - route: event-planning-timeline - first seen ed. 1 - status: live - disposition: Keep (still true, still live, count unchanged) - owner: programme lead - evidence: ed. 1: Judging ran 40 minutes over because the rubric arrived on the day.\n5. other: teams formed friendship - 1 of 1 edition (ed. 1) - one-off - route: event-planning-timeline - first seen ed. 1 - status: live - disposition: unclassified (an unthemed single entry - needs a human call at the kickoff pass) - owner: to be named (a role) - evidence: ed. 1: Teams formed by friendship groups and three solo hackers never found a team.\nRecurring themes for the trend read (0): none\nVendors named: none\nHand-offs, not ours (0): none\nChange slots (one deliberate change per theme, at most 3): none\nMenu 1 - Log persistence posture (pick: Appended document): 1. Appended document [held as the default by Q7: 4 hours between editions (a low ceiling, at most 10, self-set)]; 2. Carry-forward only. Deleted, not demoted: Structured entry record (Q1: 1 edition of records - one edition has no recurrence to count yet); Numeric series (Q1: 1 edition of records - a series of one is not a series). Notes: Q5, when planning starts, barely moves this menu - reshaping the record is not on the critical path, and a rushed schema is worse than an appended heading. Q7 forbids the retrofit: past editions stay as they were written; any richer record starts with the next edition. Q8, who re-reads the log, does not move this menu - a better-structured record does not make anyone read it.\nMenu 2 - Trend-detection depth (pick: Theme grouping): 1. Theme grouping. Deleted, not demoted: Recurrence count (Q1: 1 edition of records - nothing to count across yet); Written trend review (Q1: 1 edition of records - nothing to count across yet); Paired numeric read (Q1: 1 edition of records - nothing to count across yet). Notes: Q3: one team runs every edition - it has no theme-grouping problem yet, and a worse turnover one. Q7 leaves the default untouched - it costs one clustering pass.\nMenu 3 - Log-audit cadence (pick: Kickoff pass): 1. Kickoff pass; 2. Audit on read. Deleted, not demoted: Kickoff pass plus closure pass (Q1: 1 edition of records - fewer than two); Standing audit owner (Q1: 1 edition of records - fewer than two). Notes: Q8 does not move this menu - a better-structured record does not make anyone read it.\nKPI shortlist (2-3, each with a named owner and an action; thresholds self-set): kept none; dropped none\nClosure pass: Nothing to close: no past edition deliberately changed something because of a logged finding (Q4).\nAudit proposal: 4 Keep, 0 Update, 0 Consolidate, 0 Replace, 0 Delete, 1 unclassified. Pass threshold: Zero unclassified entries after an audit pass (self-set, binary) - does not hold yet.\nThe log opener: Bram Quillet; the moment: before planning opens (six months or more away); audit cadence pick: Kickoff pass\nFindings (7):\n[fix] one_edition (trends): One edition of records - the trend work stops here: file this edition, start the log, and come back next year. Pretending otherwise manufactures a pattern.\n[check] unclassified (audit): 1 theme the page cannot classify (\"other: teams formed friendship\") - the pass threshold, zero unclassified entries, does not hold until someone classifies it.\n[info] kpi_none (kpis): No KPIs entered - pick 2-3 from the reported candidates, each with an owner and an action; declare each threshold before reading it (self-set).\n[info] no_record (log): The records live in nothing written (Q2) - the draft log below is the first persisted record; name it to the team as the bus-factor mitigation it is.\n[info] continuous (log): The same team every edition (Q3): memory partly substitutes for the log, which is the trap - it stays thin until the year someone leaves.\n[info] loose (logs): Entries are looser than the debrief's three-part form (Q4) - the page files what is there and notes the gaps; it never reconstructs an edition.\n[info] honesty (honesty): Published organizer practice here is MLH's keeping-records guide, DevOpsDays' organizing.md and Fraser and Mancl's 2023 report; the log format, the occurrence bar, the menus and the templates are this skill's own construction, and every threshold is self-set."
}
Reply:
{
"task": "log",
"title": "Fernwick Hack Night learning log - the first edition",
"honesty": "Only MLH's keeping-records guide, DevOpsDays' organizing.md and Fraser and Mancl's 2023 report are published practice; this log's format, the occurrence bar and the audit classification are this skill's own construction, and every threshold is self-set.",
"entries": [
{
"theme": "check-in and registration",
"first_seen": "ed. 1",
"occurrences": "1 of 1 edition (ed. 1)",
"label": "one-off",
"status": "live",
"disposition": "Keep",
"owner": "registration lead",
"next_check": "Whether the sign-in record survives the night at the next edition."
},
{
"theme": "catering and food",
"first_seen": "ed. 1",
"occurrences": "1 of 1 edition (ed. 1)",
"label": "one-off",
"status": "live",
"disposition": "Keep",
"owner": "catering lead",
"next_check": "The food arrival time against the schedule at the next edition."
},
{
"theme": "wifi and power",
"first_seen": "ed. 1",
"occurrences": "1 of 1 edition (ed. 1)",
"label": "one-off",
"status": "live",
"disposition": "Keep",
"owner": "venue tech lead",
"next_check": "Sockets per team at the next edition's setup."
},
{
"theme": "schedule and timekeeping",
"first_seen": "ed. 1",
"occurrences": "1 of 1 edition (ed. 1)",
"label": "one-off",
"status": "live",
"disposition": "Keep",
"owner": "programme lead",
"next_check": "Whether judging ends on time with the rubric sent ahead."
},
{
"theme": "other: teams formed friendship",
"first_seen": "ed. 1",
"occurrences": "1 of 1 edition (ed. 1)",
"label": "one-off",
"status": "live",
"disposition": "Keep",
"owner": "to be named (a role)",
"next_check": "Whether solo hackers find a team at the next edition; confirm this classification at the kickoff pass."
}
],
"not_counted": [],
"changes": [],
"opener": {
"person": "Bram Quillet",
"moment": "before planning opens (six months or more away)"
},
"audit": {
"cadence": "Kickoff pass",
"threshold": "Zero unclassified entries after an audit pass (self-set) - the unthemed entry is classified here and confirmed at the kickoff pass."
},
"outcome_log": "After each edition, append the projects and teams that kept going, and re-open the list at the kickoff pass, since outcomes surface months later.",
"handover_note": "One edition is not a trend: this log starts the record, and nothing in it is a candidate or a pattern yet. Come back after the next edition and count each theme again."
}
The page's check: kept - other: teams formed friendship: the page left it unclassified; the reply classifies it Keep - confirm it at the kickoff pass.
The free draft log for the first sample
# Larchmere Code Fair - learning log
_Published organizer practice here is MLH's keeping-records guide, DevOpsDays' organizing.md and Fraser and Mancl's 2023 report; the log format, the occurrence bar, the menus and the templates are this skill's own construction, and every threshold is self-set._
- Opened before planning by: **Odile Fenwarrow** - before planning opens (kickoff 2027-01-15)
- Lives in: the shared drive, Code Fair/learning-log.md
- Persistence: Structured entry record; audit cadence: Kickoff pass
- Pass threshold: Zero unclassified entries after an audit pass (self-set, binary) - holds
- Records held: 4 editions (2023, 2024, 2025, 2026) - every count below is out of 4
## Entries
| Theme | First seen | Occurrences | Status | Condition (latest) | Disposition | Routed to | Owner |
|---|---|---|---|---|---|---|---|
| check-in and registration | 2024 | 3 of 4 editions (2024, 2025, 2026) | pattern, change shipped - did not improve | 2026: Lanyards were sorted alphabetically but the opening queue still took 30 minutes - a single desk cannot... | Consolidate | event-planning-timeline | registration lead |
| schedule and timekeeping | 2024 | 3 of 4 editions (2024, 2025, 2026) | pattern, live | 2026: Sessions ran late again in the afternoon track. | Consolidate | event-planning-timeline | programme lead |
| catering and food | 2023 | 2 of 4 editions (2023, 2025) | candidate, not seen in the latest edition | 2025: Quillfern Catering delivered lunch 50 minutes late and the afternoon started hungry. | Update | event-planning-timeline | catering lead |
| team load and handover | 2024 | 2 of 4 editions (2024, 2026) | candidate, routed to event-team-structure | 2026: The handover from the previous chair was a chat thread; two organizers burned out by the end. | Consolidate | event-team-structure | lead organizer |
| wifi and power | 2023 | 1 of 4 editions (2023) | one-off, not seen in the latest edition | 2023: Venue wifi dropped twice during the morning keynote and the livestream froze both times. | Update | event-planning-timeline | venue tech lead |
| attendance and return (demand) | 2025 | 1 of 4 editions (2025) | one-off, routed to event-market-fit | 2025: Fewer returning attendees than last year - only 90 of 380 came back. | Update | event-market-fit | whoever reads demand |
| accessibility | 2025 | 1 of 4 editions (2025) | one-off, not seen in the latest edition | 2025: One organizer forgot to book the captioner, so the keynote had no captions. | Update | event-planning-timeline | accessibility lead |
| volunteers and staffing | 2026 | 1 of 4 editions (2026) | one-off, live | 2026: The volunteer rota had one point of contact and the single contact was unreachable on the day. | Keep | event-planning-timeline | volunteer coordinator |
## Filed, not counted
- 2023: Speaker's laptop wouldn't output to the projector; swapped to the backup machine, lost four minutes. Handled. - handled at no cost - expected work, kept with its reason, never counted
- 2023: Loading dock at the old venue closed at 17:00, teardown ran past it and we paid an overtime fee. - not current - the condition is gone; closed with its reason so nobody re-files it
- 2023: Swag. - too thin to file - the gap is noted, the edition is never reconstructed
- 2024: Fire alarm test at 11:00 was announced; no impact. - handled at no cost - expected work, kept with its reason, never counted
## Deliberate changes
- CR-1 check-in and registration (pattern): change, why and check to be written - one deliberate change at a time
- CR-2 schedule and timekeeping (pattern): change, why and check to be written - one deliberate change at a time
- CR-3 catering and food (candidate - only if the fix is cheap and reversible): change, why and check to be written - one deliberate change at a time
Last cycle:
- Printed the attendee list the morning of the event - shipped, did not improve - the 2025 queue was still 35 minutes
Tried and did not work:
- Printed the attendee list the morning of the event - the 2025 queue was still 35 minutes
## Routing hand-offs
- check-in and registration (size evidence) -> event-growth-strategy: an entry names a ceiling (E4.1) - the ceiling and the evidence, never a recommendation about size
- team load and handover -> event-team-structure: a structural finding that recurs (2 of 4 editions (2024, 2026)) - the count a single debrief could not produce; the persisted log is itself one bus-factor mitigation
- attendance and return (demand) -> event-market-fit: demand-shaped, not operational - an observation for their read with its count (1 of 4 editions (2025)), never a causal claim
- vendor: Quillfern Catering -> event-vendor-sourcing: named in 2 of 4 editions (2023, 2025) - a rebook-or-not verdict, filed on that vendor's own record where next edition's buyer will look
## Outcome log
Appended after each event, re-opened at the kickoff pass - outcomes surface months later.
| Date found | Event and edition | Outcome type | What | Source | Consent to publish |
|---|---|---|---|---|---|
| | | Project / collaboration / company / job | | Self-report / organizer saw | |
Build the input yourself
Load the engine in node (global.window = global; require("./ledgerkit.js"); require("./ledgerreply.js")), then:
const K = LedgerKit, R = LedgerReply;
const f = K.form({ name: "My Meetup", editionsRun: "4", editionsRecorded: "3", turnover: "most", handover: "yes", planWhen: "months",
hours: "12", opener: "a named person", logs: fs.readFileSync("debriefs.md", "utf8") });
// f.eds (id, label, short), f.entries (id, clean, gate, reason, theme, disp), f.themes (name, count, label, occ, route, status, disp, owner)
// f.handoffs, f.vendors, f.slots, f.menus (persistence, depth, audit: options, deleted, notes, picks), f.kpis, f.closure, f.verdict, f.findings
K.logMd(f); K.themesCsv(f) // the free draft log and the themes table
const b = K.buildInput(f, "trends"); // or "log" (works from one edition)
const wire = K.toWire(b.input); // POST this to /estimate and /run
// then: const reply = R.normalize(R.parseReply(job.output.output), "trends");
// R.check(reply, b) // {status: kept or flagged, notes}
// R.carryText(reply) // the lines the log lane carries - set them as f.raw.carry
Get a token for the steps below from /tokens.html.
Step 1 — a tiny client helper
One function that sends JSON and unwraps the response. Paste a personal token from /tokens.html, or leave it empty and mint a guest token in step 2.
BASE="https://api.skillsafe.ai/v1/app-api"
TOKEN="YOUR_TOKEN" # from https://debrief-ledger.skillsafe.ai/tokens.html
api() { # api METHOD PATH [JSON-BODY]
curl -s -X "$1" "$BASE$2" -H "Content-Type: application/json" \
${TOKEN:+-H "Authorization: Bearer $TOKEN"} ${3:+--data "$3"}
}
import json, urllib.request
BASE = "https://api.skillsafe.ai/v1/app-api"
TOKEN = "YOUR_TOKEN" # from https://debrief-ledger.skillsafe.ai/tokens.html
def api(method, path, body=None, headers=None):
req = urllib.request.Request(BASE + path, method=method,
data=None if body is None else json.dumps(body).encode(),
headers={"Content-Type": "application/json", **({"Authorization": "Bearer " + TOKEN} if TOKEN else {}), **(headers or {})})
with urllib.request.urlopen(req) as r:
env = json.load(r)
if env.get("error"):
raise RuntimeError(env["error"])
return env["data"]
// debrief-ledger.mjs -- Node 18+ (global fetch)
const BASE = "https://api.skillsafe.ai/v1/app-api";
let TOKEN = "YOUR_TOKEN"; // from https://debrief-ledger.skillsafe.ai/tokens.html
async function api(method, path, body, headers = {}) {
const r = await fetch(BASE + path, { method, headers: { "Content-Type": "application/json",
...(TOKEN ? { Authorization: "Bearer " + TOKEN } : {}), ...headers },
body: body === undefined ? undefined : JSON.stringify(body) });
const env = await r.json();
if (env.error) throw new Error(env.error.code + ": " + env.error.message);
return env.data;
}
package main
import ("bytes"; "encoding/json"; "fmt"; "net/http")
const base = "https://api.skillsafe.ai/v1/app-api"
var token = "YOUR_TOKEN" // from https://debrief-ledger.skillsafe.ai/tokens.html
func api(method, path string, body any, headers map[string]string) (map[string]any, error) {
var buf bytes.Buffer
if body != nil { json.NewEncoder(&buf).Encode(body) }
req, _ := http.NewRequest(method, base+path, &buf)
req.Header.Set("Content-Type", "application/json")
if token != "" { req.Header.Set("Authorization", "Bearer "+token) }
for k, v := range headers { req.Header.Set(k, v) }
res, err := http.DefaultClient.Do(req)
if err != nil { return nil, err }
defer res.Body.Close()
var env struct { Data map[string]any; Error map[string]any }
json.NewDecoder(res.Body).Decode(&env)
if env.Error != nil { return nil, fmt.Errorf("%v", env.Error) }
return env.Data, nil
}
// DebriefLedger.java -- Java 17+, with com.fasterxml.jackson.core:jackson-databind
import com.fasterxml.jackson.databind.*;
import java.net.URI; import java.net.http.*; import java.util.*;
public class DebriefLedger {
static final String BASE = "https://api.skillsafe.ai/v1/app-api";
static String token = "YOUR_TOKEN"; // from https://debrief-ledger.skillsafe.ai/tokens.html
static final ObjectMapper M = new ObjectMapper();
static final HttpClient C = HttpClient.newHttpClient();
static JsonNode api(String method, String path, Object body, Map<String, String> headers) throws Exception {
var b = HttpRequest.newBuilder(URI.create(BASE + path)).header("Content-Type", "application/json");
if (!token.isEmpty()) b.header("Authorization", "Bearer " + token);
if (headers != null) headers.forEach(b::header);
b.method(method, body == null ? HttpRequest.BodyPublishers.noBody() : HttpRequest.BodyPublishers.ofString(M.writeValueAsString(body)));
JsonNode env = M.readTree(C.send(b.build(), HttpResponse.BodyHandlers.ofString()).body());
if (env.hasNonNull("error")) throw new RuntimeException(env.get("error").toString());
return env.get("data");
}
}
require "json"
require "net/http"
BASE = "https://api.skillsafe.ai/v1/app-api"
TOKEN = "YOUR_TOKEN" # from https://debrief-ledger.skillsafe.ai/tokens.html
def api(method, path, body = nil, headers = {})
uri = URI(BASE + path)
req = Net::HTTPGenericRequest.new(method, !body.nil?, true, uri.request_uri,
{ "Content-Type" => "application/json" }.merge(TOKEN.empty? ? {} : { "Authorization" => "Bearer #{TOKEN}" }).merge(headers))
req.body = JSON.generate(body) unless body.nil?
env = JSON.parse(Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |h| h.request(req) }.body)
raise env["error"].to_s if env["error"]
env["data"]
end
<?php
const BASE = "https://api.skillsafe.ai/v1/app-api";
$TOKEN = "YOUR_TOKEN"; // from https://debrief-ledger.skillsafe.ai/tokens.html
function api(string $method, string $path, $body = null, array $headers = []) {
global $TOKEN;
$h = ["Content-Type: application/json"];
if ($TOKEN) $h[] = "Authorization: Bearer $TOKEN";
foreach ($headers as $k => $v) $h[] = "$k: $v";
$ch = curl_init(BASE . $path);
curl_setopt_array($ch, [CURLOPT_CUSTOMREQUEST => $method, CURLOPT_HTTPHEADER => $h, CURLOPT_RETURNTRANSFER => true]);
if ($body !== null) curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($body));
$env = json_decode(curl_exec($ch), true);
if (!empty($env["error"])) throw new Exception(json_encode($env["error"]));
return $env["data"];
}
// Program.cs -- .NET 6+ console app
using System.Net.Http.Json; using System.Text.Json; using System.Text.Json.Nodes;
static class Api {
public const string Base = "https://api.skillsafe.ai/v1/app-api";
public static string Token = "YOUR_TOKEN"; // from https://debrief-ledger.skillsafe.ai/tokens.html
static readonly HttpClient C = new();
public static async Task<JsonNode?> Call(string method, string path, object? body = null, Dictionary<string, string>? headers = null) {
var req = new HttpRequestMessage(new HttpMethod(method), Base + path);
if (Token != "") req.Headers.Add("Authorization", "Bearer " + Token);
if (headers != null) foreach (var h in headers) req.Headers.Add(h.Key, h.Value);
if (body != null) req.Content = JsonContent.Create(body);
var env = JsonNode.Parse(await (await C.SendAsync(req)).Content.ReadAsStringAsync())!;
if (env["error"] is JsonNode e && e.GetValueKind() != JsonValueKind.Null) throw new Exception(e.ToJsonString());
return env["data"];
}
}
Step 2 — a token
A guest token is enough for /me and /estimate. A run is metered, so it needs a personal token: sign in on /tokens.html and copy it from there.
# a guest token (enough for /me and /estimate); a run needs your personal token from /tokens.html
TOKEN=$(curl -s -X POST "$BASE/guest" -H "Content-Type: application/json" -d '{"slug":"debrief-ledger"}' | jq -r '.data.token')
# a guest token (enough for /me and /estimate); a run needs your personal token from /tokens.html
TOKEN = ""
TOKEN = api("POST", "/guest", {"slug": "debrief-ledger"})["token"]
// a guest token (enough for /me and /estimate); a run needs your personal token from /tokens.html
TOKEN = "";
TOKEN = (await api("POST", "/guest", { slug: "debrief-ledger" })).token;
// inside main: a guest token (enough for /me and /estimate); a run needs your personal token
token = ""
g, err := api("POST", "/guest", map[string]string{"slug": "debrief-ledger"}, nil)
if err != nil { panic(err) }
token = g["token"].(string)
// inside main: a guest token (enough for /me and /estimate); a run needs your personal token
token = "";
token = api("POST", "/guest", Map.of("slug", "debrief-ledger"), null).get("token").asText();
# a guest token (enough for /me and /estimate); a run needs your personal token from /tokens.html
TOKEN.replace("")
TOKEN.replace(api("POST", "/guest", { slug: "debrief-ledger" })["token"])
// a guest token (enough for /me and /estimate); a run needs your personal token from /tokens.html
$TOKEN = "";
$TOKEN = api("POST", "/guest", ["slug" => "debrief-ledger"])["token"];
// a guest token (enough for /me and /estimate); a run needs your personal token from /tokens.html
Api.Token = "";
Api.Token = (await Api.Call("POST", "/guest", new { slug = "debrief-ledger" }))!["token"]!.GetValue<string>();
Step 3 — GET /me
Who the token is (subject_type: user or guest) and the credit balance.
api GET /me | jq '.data | {subject_type, credits}'
me = api("GET", "/me")
print(me["subject_type"], me.get("credits"))
const me = await api("GET", "/me");
console.log(me.subject_type, me.credits);
me, _ := api("GET", "/me", nil, nil)
fmt.Println(me["subject_type"], me["credits"])
JsonNode me = api("GET", "/me", null, null);
System.out.println(me.get("subject_type") + " " + me.get("credits"));
me = api("GET", "/me")
puts [me["subject_type"], me["credits"]].inspect
$me = api("GET", "/me");
echo $me["subject_type"], " ", $me["credits"] ?? "", "\n";
var me = await Api.Call("GET", "/me");
Console.WriteLine($"{me!["subject_type"]} {me["credits"]}");
Step 4 — POST /estimate
Free. The body is the run input itself, the bare object (never wrapped in {"input": ...}). hold_credits is a reservation, not the price; min_credits is what the balance must cover; model_alias reads gpt-terra.
# input.json: the run input object - {"task": "trends", "event": "Event: ...; editions run 4, with written records 4 ...", "logs": "## 2024 (E1, edition 1 of 4) ...", "facts": "Verdict: ..."}
# - see the input table
api POST /estimate "$(cat input.json)" | jq '.data | {hold_credits, min_credits, model, model_alias, markup_bps, warnings}'
inp = json.load(open("input.json")) # {"task": "trends", "event": "Event: ...; editions run 4, with written records 4 ...", "logs": "## 2024 (E1, edition 1 of 4) ...", "facts": "Verdict: ..."}
# - see the input table
est = api("POST", "/estimate", inp)
print(est["hold_credits"], est["min_credits"], est["model"], est.get("warnings"))
import { readFileSync } from "node:fs";
const input = JSON.parse(readFileSync("input.json", "utf8")); // {task: "trends" or "log", event, logs, facts} (see the input table)
const est = await api("POST", "/estimate", input);
console.log(est.hold_credits, est.min_credits, est.model, est.warnings);
raw, _ := os.ReadFile("input.json") // add "os" to the imports
var input map[string]any
json.Unmarshal(raw, &input)
est, _ := api("POST", "/estimate", input, nil)
fmt.Println(est["hold_credits"], est["min_credits"], est["model"])
Map<String, Object> input = M.readValue(new java.io.File("input.json"), Map.class);
JsonNode est = api("POST", "/estimate", input, null);
System.out.println(est.get("hold_credits") + " " + est.get("min_credits") + " " + est.get("model"));
input = JSON.parse(File.read("input.json"))
est = api("POST", "/estimate", input)
puts [est["hold_credits"], est["min_credits"], est["model"]].inspect
$input = json_decode(file_get_contents("input.json"), true);
$est = api("POST", "/estimate", $input);
echo $est["hold_credits"], " ", $est["min_credits"], " ", $est["model"], "\n";
var input = JsonNode.Parse(File.ReadAllText("input.json"))!;
var est = await Api.Call("POST", "/estimate", input);
Console.WriteLine($"{est!["hold_credits"]} {est["min_credits"]} {est["model"]}");
Step 5 — POST /run, then poll the job
Send an Idempotency-Key built from the lane and the input: a retry with the same key never bills twice. The page uses debrief-ledger:<task>:<inputHash>:a<attempt> - the lane is part of the key - and its one automatic reformat retry is a new attempt number, named in the page as one extra run. A trend read carries summary, honesty, verdict, themes, changes, not_ours, menus, kpis, closure and caveats; a learning log carries title, honesty, entries, not_counted, changes, opener, audit, outcome_log and handover_note. The code below prints the headline of either.
KEY="debrief-ledger:trends:$(shasum -a 256 input.json | cut -c1-16):a1"
JOB=$(curl -s -X POST "$BASE/run" -H "Content-Type: application/json" -H "Authorization: Bearer $TOKEN" \
-H "Idempotency-Key: $KEY" --data @input.json | jq -r '.data.job_id')
while :; do
J=$(api GET "/jobs/$JOB"); S=$(echo "$J" | jq -r '.data.status')
case "$S" in succeeded|failed|cancelled) break;; esac; sleep 2
done
echo "$J" | jq -r '.data.output.output' > reply.json # one JSON object, the reply contract
echo "$J" | jq '.data | {charged_credits, truncated}'
jq -r '.verdict // .title, .summary // .handover_note' reply.json
jq -r '(.themes // .entries)[] | .theme' reply.json # the trend read's recurring themes, or the log's entries
import hashlib, time
key = "debrief-ledger:" + inp["task"] + ":" + hashlib.sha256(json.dumps(inp).encode()).hexdigest()[:16] + ":a1"
job = api("POST", "/run", inp, {"Idempotency-Key": key})
while True:
j = api("GET", "/jobs/" + job["job_id"])
if j["status"] in ("succeeded", "failed", "cancelled"):
break
time.sleep(2)
reply = json.loads(j["output"]["output"]) # the reply as one JSON object
print(j["charged_credits"], j.get("truncated"), reply.get("verdict") or reply.get("title"))
print(reply.get("summary") or reply.get("handover_note", ""))
for t in reply.get("themes") or reply.get("entries") or []:
print("-", t["theme"])
import { createHash } from "node:crypto";
const key = `debrief-ledger:${input.task}:${createHash("sha256").update(JSON.stringify(input)).digest("hex").slice(0, 16)}:a1`;
const job = await api("POST", "/run", input, { "Idempotency-Key": key });
let j;
do { await new Promise((r) => setTimeout(r, 2000)); j = await api("GET", "/jobs/" + job.job_id); }
while (!["succeeded", "failed", "cancelled"].includes(j.status));
const reply = JSON.parse(j.output.output);
console.log(j.charged_credits, j.truncated, reply.verdict ?? reply.title);
console.log(reply.summary ?? reply.handover_note);
for (const t of reply.themes || reply.entries || []) console.log("-", t.theme);
sum := sha256.Sum256(raw) // add "crypto/sha256", "encoding/hex", "time" to the imports
key := "debrief-ledger:" + input["task"].(string) + ":" + hex.EncodeToString(sum[:8]) + ":a1"
job, _ := api("POST", "/run", input, map[string]string{"Idempotency-Key": key})
var j map[string]any
for {
time.Sleep(2 * time.Second)
j, _ = api("GET", "/jobs/"+job["job_id"].(string), nil, nil)
if s := j["status"]; s == "succeeded" || s == "failed" || s == "cancelled" { break }
}
var reply map[string]any
json.Unmarshal([]byte(j["output"].(map[string]any)["output"].(string)), &reply)
fmt.Println(j["charged_credits"], j["truncated"], reply["verdict"], reply["title"])
fmt.Println(reply["summary"], reply["handover_note"])
items, _ := reply["themes"].([]any) // the trend read's recurring themes
if items == nil { items, _ = reply["entries"].([]any) } // or the log's entries
for _, x := range items {
fmt.Println("-", x.(map[string]any)["theme"])
}
var digest = java.security.MessageDigest.getInstance("SHA-256").digest(M.writeValueAsBytes(input));
String key = "debrief-ledger:" + input.get("task") + ":" + HexFormat.of().formatHex(digest, 0, 8) + ":a1";
JsonNode job = api("POST", "/run", input, Map.of("Idempotency-Key", key)), j;
do { Thread.sleep(2000); j = api("GET", "/jobs/" + job.get("job_id").asText(), null, null); }
while (!Set.of("succeeded", "failed", "cancelled").contains(j.get("status").asText()));
JsonNode reply = M.readTree(j.get("output").get("output").asText());
System.out.println(j.get("charged_credits") + " " + reply.path("verdict").asText(reply.path("title").asText()));
System.out.println(reply.path("summary").asText(reply.path("handover_note").asText()));
for (JsonNode t : reply.has("themes") ? reply.path("themes") : reply.path("entries")) System.out.println("- " + t.path("theme").asText());
require "digest"
key = "debrief-ledger:#{input["task"]}:#{Digest::SHA256.hexdigest(JSON.generate(input))[0, 16]}:a1"
job = api("POST", "/run", input, { "Idempotency-Key" => key })
j = nil
loop do
sleep 2
j = api("GET", "/jobs/#{job["job_id"]}")
break if %w[succeeded failed cancelled].include?(j["status"])
end
reply = JSON.parse(j["output"]["output"])
puts [j["charged_credits"], j["truncated"], reply["verdict"] || reply["title"]].inspect
puts reply["summary"] || reply["handover_note"]
(reply["themes"] || reply["entries"] || []).each { |t| puts "- #{t["theme"]}" }
$key = "debrief-ledger:" . $input["task"] . ":" . substr(hash("sha256", json_encode($input)), 0, 16) . ":a1";
$job = api("POST", "/run", $input, ["Idempotency-Key" => $key]);
do { sleep(2); $j = api("GET", "/jobs/" . $job["job_id"]); }
while (!in_array($j["status"], ["succeeded", "failed", "cancelled"]));
$reply = json_decode($j["output"]["output"], true);
echo $j["charged_credits"], " ", ($reply["verdict"] ?? $reply["title"] ?? ""), "\n";
echo $reply["summary"] ?? $reply["handover_note"] ?? "", "\n";
foreach ($reply["themes"] ?? $reply["entries"] ?? [] as $t) echo "- ", $t["theme"], "\n";
var digest = System.Security.Cryptography.SHA256.HashData(System.Text.Encoding.UTF8.GetBytes(input.ToJsonString()));
var key = $"debrief-ledger:{input["task"]}:{Convert.ToHexString(digest, 0, 8).ToLowerInvariant()}:a1";
var job = await Api.Call("POST", "/run", input, new() { ["Idempotency-Key"] = key });
JsonNode j;
do { await Task.Delay(2000); j = (await Api.Call("GET", "/jobs/" + job!["job_id"]))!; }
while (!new[] { "succeeded", "failed", "cancelled" }.Contains(j["status"]!.GetValue<string>()));
var reply = JsonNode.Parse(j["output"]!["output"]!.GetValue<string>());
Console.WriteLine($"{j["charged_credits"]} {reply!["verdict"] ?? reply["title"]}");
Console.WriteLine($"{reply["summary"] ?? reply["handover_note"]}");
foreach (var t in (reply["themes"] ?? reply["entries"]) as JsonArray ?? new JsonArray()) Console.WriteLine("- " + t!["theme"]);
Step 6 — POST /run-stream
The same run as Server-Sent Events, with the same input.json. Browsers receive progress ticks rather than text deltas; the final done event carries the reply.
# Server-Sent Events: tick/delta events while the job runs, then a final event with the job
curl -N -s -X POST "$BASE/run-stream" -H "Content-Type: application/json" -H "Authorization: Bearer $TOKEN" \
-H "Idempotency-Key: debrief-ledger:trends:$(shasum -a 256 input.json | cut -c1-16):a1" --data @input.json
rev = json.load(open("input.json")) # the same run input as input.json: {"task": "trends", "event": "Event: ...; editions run 4, with written records 4 ...", "logs": "## 2024 (E1, edition 1 of 4) ...", "facts": "Verdict: ..."}
# - see the input table
req = urllib.request.Request(BASE + "/run-stream", method="POST", data=json.dumps(rev).encode(),
headers={"Content-Type": "application/json", "Authorization": "Bearer " + TOKEN,
"Idempotency-Key": "debrief-ledger:trends:" + hashlib.sha256(json.dumps(rev).encode()).hexdigest()[:16] + ":a1"})
with urllib.request.urlopen(req) as r:
for line in r:
line = line.decode().strip()
if line.startswith("data:"):
print(line[5:].strip()[:200])
const rev = JSON.parse(readFileSync("input.json", "utf8"));
const r = await fetch(BASE + "/run-stream", { method: "POST", body: JSON.stringify(rev), headers: {
"Content-Type": "application/json", Authorization: "Bearer " + TOKEN,
"Idempotency-Key": `debrief-ledger:trends:${createHash("sha256").update(JSON.stringify(rev)).digest("hex").slice(0, 16)}:a1` } });
const dec = new TextDecoder();
for await (const chunk of r.body) for (const line of dec.decode(chunk).split("\n"))
if (line.startsWith("data:")) console.log(line.slice(5).trim().slice(0, 200));
rraw, _ := os.ReadFile("input.json") // add "bufio", "strings" to the imports
rs := sha256.Sum256(rraw)
req, _ := http.NewRequest("POST", base+"/run-stream", bytes.NewReader(rraw))
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Authorization", "Bearer "+token)
req.Header.Set("Idempotency-Key", "debrief-ledger:trends:"+hex.EncodeToString(rs[:8])+":a1")
res, _ := http.DefaultClient.Do(req)
sc := bufio.NewScanner(res.Body)
for sc.Scan() { if l := sc.Text(); strings.HasPrefix(l, "data:") { fmt.Println(l[5:]) } }
String rev = java.nio.file.Files.readString(java.nio.file.Path.of("input.json"));
var rd = java.security.MessageDigest.getInstance("SHA-256").digest(rev.getBytes());
var sreq = HttpRequest.newBuilder(URI.create(BASE + "/run-stream")).header("Content-Type", "application/json")
.header("Authorization", "Bearer " + token).header("Idempotency-Key", "debrief-ledger:trends:" + HexFormat.of().formatHex(rd, 0, 8) + ":a1")
.POST(HttpRequest.BodyPublishers.ofString(rev)).build();
C.send(sreq, HttpResponse.BodyHandlers.ofLines()).body().filter(l -> l.startsWith("data:")).forEach(System.out::println);
rev = File.read("input.json")
uri = URI(BASE + "/run-stream")
req = Net::HTTP::Post.new(uri, "Content-Type" => "application/json", "Authorization" => "Bearer #{TOKEN}",
"Idempotency-Key" => "debrief-ledger:trends:#{Digest::SHA256.hexdigest(rev)[0, 16]}:a1")
req.body = rev
Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |h|
h.request(req) { |res| res.read_body { |chunk| chunk.each_line { |l| puts l if l.start_with?("data:") } } }
end
$rev = file_get_contents("input.json");
$ch = curl_init(BASE . "/run-stream");
curl_setopt_array($ch, [CURLOPT_POST => true, CURLOPT_POSTFIELDS => $rev, CURLOPT_HTTPHEADER => [
"Content-Type: application/json", "Authorization: Bearer $TOKEN",
"Idempotency-Key: debrief-ledger:trends:" . substr(hash("sha256", $rev), 0, 16) . ":a1"],
CURLOPT_WRITEFUNCTION => function ($ch, $chunk) { foreach (explode("\n", $chunk) as $l) if (str_starts_with($l, "data:")) echo $l, "\n"; return strlen($chunk); }]);
curl_exec($ch);
var rev = File.ReadAllText("input.json");
var rd = System.Security.Cryptography.SHA256.HashData(System.Text.Encoding.UTF8.GetBytes(rev));
var sreq = new HttpRequestMessage(HttpMethod.Post, Api.Base + "/run-stream") { Content = new StringContent(rev, System.Text.Encoding.UTF8, "application/json") };
sreq.Headers.Add("Authorization", "Bearer " + Api.Token);
sreq.Headers.Add("Idempotency-Key", $"debrief-ledger:trends:{Convert.ToHexString(rd, 0, 8).ToLowerInvariant()}:a1");
using var http = new HttpClient();
using var res = await http.SendAsync(sreq, HttpCompletionOption.ResponseHeadersRead);
using var rdr = new StreamReader(await res.Content.ReadAsStreamAsync());
for (string? l; (l = await rdr.ReadLineAsync()) != null;) if (l.StartsWith("data:")) Console.WriteLine(l);