Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@ REFERRAL_EMAIL_BATCH_SIZE=50
# World ID UI
NEXT_PUBLIC_WORLD_ID_ENABLED=true

# Optional Microsoft Clarity project ID.
# Session replay runs only on explicit public-safe pages.
NEXT_PUBLIC_MICROSOFT_CLARITY_PROJECT_ID=

# World ID proof-of-personhood
# Create these in the World Developer Portal / IDKit setup:
# Portal: https://developer.world.org/
Expand Down
26 changes: 23 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -651,8 +651,28 @@ jobs:
user_name: github-actions[bot]
user_email: github-actions[bot]@users.noreply.github.com

- name: Post Visual review commit status
- name: Wait for visual review page
id: wait_visual_review_pages
if: ${{ !cancelled() && steps.visual_review_pages.outcome == 'success' }}
shell: bash
run: |
target_url="https://mikepsinn.github.io/optimitron/pr-${{ github.event.pull_request.number }}/${{ steps.prepare_pages.outputs.short_sha }}/latest.html"
echo "target_url=$target_url" >> "$GITHUB_OUTPUT"
echo "Waiting for $target_url"
for attempt in $(seq 1 90); do
status="$(curl -L -sS --connect-timeout 5 --max-time 15 -o /tmp/visual-review-latest.html -w "%{http_code}" "$target_url" || true)"
if [ "$status" = "200" ] && [ -s /tmp/visual-review-latest.html ]; then
echo "Visual review page is live after attempt $attempt."
exit 0
fi
echo "Attempt $attempt/90 returned HTTP $status; retrying in 10s."
sleep 10
done
echo "::error::Visual review page did not become available: $target_url"
exit 1

- name: Post Visual review commit status
if: ${{ !cancelled() && steps.wait_visual_review_pages.outcome == 'success' }}
uses: actions/github-script@v8
with:
script: |
Expand All @@ -672,7 +692,7 @@ jobs:
});

- name: Create Visual review deployment
if: ${{ !cancelled() && steps.visual_review_pages.outcome == 'success' }}
if: ${{ !cancelled() && steps.wait_visual_review_pages.outcome == 'success' }}
uses: actions/github-script@v8
with:
script: |
Expand Down Expand Up @@ -707,7 +727,7 @@ jobs:
});

- name: Update PR review packet with visual review
if: ${{ !cancelled() && steps.visual_review_pages.outcome == 'success' && steps.pr_preview_url.outputs.result != '' }}
if: ${{ !cancelled() && steps.wait_visual_review_pages.outcome == 'success' && steps.pr_preview_url.outputs.result != '' }}
uses: actions/github-script@v8
env:
PREVIEW_URL: ${{ steps.pr_preview_url.outputs.result }}
Expand Down
2 changes: 1 addition & 1 deletion .husky/pre-commit
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
set -e

pnpm exec lint-staged
pnpm --filter @optimitron/web run copy:gate
#pnpm --filter @optimitron/web run copy:gate

# === Copy preview markdown reminder (not auto-run) ===
# Previously this block auto-ran `pnpm copy:preview` on every commit
Expand Down
1 change: 1 addition & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
## Mission Focus

- Until the 1% Treaty passes, optimize for the International Campaign to End War and Disease at `warondisease.org`.
- Legal nonprofit: Accelerated Medicine Foundation. Registered DBAs include Institute for Accelerated Medicine and International Campaign to End War and Disease.
- The default product question is: does this help a human vote, recruit two more humans, get an organization to join, register a plaintiff, pressure a leader, or trust the quantified case enough to act?
- Treat `optimitron.com` as the operating system and proof engine behind the campaign: task coordination, referrals, communications, OPG/OBG/Wishocracy, politician grading, impact math, and AI-agent workflows. Do not let the broader platform compete with the campaign for attention during this phase.
- Park generic platform features, clever demos, cosmetic cleanup, and non-campaign variant work unless they directly reduce campaign friction or protect an already-shipping path.
Expand Down
166 changes: 166 additions & 0 deletions docs/joke-handout-draft.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
# Joke Handout Draft

Draft source for the printable paper that goes with the shirt joke. Perfect this
copy here before wiring it back into `/joke`.

## Copy Brief

Audience: a zero-context human who found writing on their shirt and this paper
near it.

Desired action: understand the 1% Treaty, vote yes, and help spread the facts.

Motivation: their disease risk, their family, their money, and the fact that
the current allocation is insane once seen clearly.

Strategic job: make the shirt-writing feel less like random vandalism and more
like an annoying but rational attempt to put the decisive facts into everyone's
head.

Source anchors: 150,000 disease deaths/day; 604x weapons vs government clinical
trials; 6,650 diseases without FDA-approved treatment; 15 first treatments/year;
12.3x clinical-trial capacity; 36 years instead of 443; 10.7 billion deaths and
1.93 quadrillion suffering hours avoided; 206 trillion to 3.5 quadrillion extra
laughs.

Voice anchors from `docs/h2ewd.md`: "murder money to medicine money"; "testing
which medicines work"; "diseases don't have oil"; "Give 1% fewer papers to
people who build murder machines"; "If cancer had oil reserves, you would have
cured it by 2003"; "the spreadsheet stops killing people"; "the math is crazy
and I would like you to not die."

## Handout Text

### Side 1

PLEASE READ BEFORE YELLING AT ME.

# WHY SOMEONE WROTE ON YOUR SHIRT

I wrote on your shirt because I do not want you to suffer and die of horrible
diseases.

The point is to get one proposal into every human brain at once: every nation
should redirect 1% of military spending from murder money to medicine money.

That is the 1% Treaty.

The medicine money funds pragmatic clinical trials: testing which treatments
actually work in real humans.

Every country redirects the same 1%, so every country keeps 99% of its military
budget, everyone has 1% fewer missiles pointed at them, and humanity gets 12.3
times as much clinical-trial capacity.

## The math that made me write on your shirt

Disease kills 150,000 humans/day, about 50 September 11s every day. Nobody
invades anyone about it because diseases do not have oil.

Your chance of dying of disease: nearly 100%.

Your chance of dying of terrorism: 1 in 30,000,000.

Your governments spend 604 times more on the thing that will almost certainly
not kill you than the thing that almost certainly will.

If cancer had oil reserves, we would have cured it by 2003.

Before World War II, US military spending was 96.7% lower. After winning, the US
cut it 87.6% in two years.

About 6,650 diseases have no FDA-approved treatment. At 15 first treatments per
year, finding treatments for all of them takes 443 years.

The 1% Treaty increases clinical-trial capacity 12.3 times: about 185 first
treatments per year instead of 15. That is projected to find treatments for all
diseases in 36 years instead of 443.

The average human becomes about 4x richer and much less diseased and dead.

The spreadsheet stops killing people.

I did not write on your shirt because I am crazy. I wrote on it because the math
is crazy and I would like you to not die.

I love you. I am not sorry. Turn over.

### Side 2

THE YELLING PART

# THIS IS A CHAIN LETTER. THE FIRST ONE THAT IS NOT A LIE.

Chain letters worked when they were fake. This one has citations.

The threat is real: every day you wait, 150,000 people die in a line that did
not need to exist.

The reward is real: 10.7 billion people do not die, 1.93 quadrillion hours of
suffering do not happen, and the average human gets much richer because healthy
people can do things besides suffer.

## Answers for the person currently yelling at you

## But national security.

National security improves. Everyone cuts 1% at the same time, so everyone has
1% fewer missiles pointed at them and keeps 99%. Humanity still has about 121
spare apocalypses, in case we need to re-destroy the rubble a few extra times
to feel safe.

## We cannot afford it.

Disease already burns $5.00 trillion/year in lost work and drags off 13.0% of
global GDP. The current arrangement is what nobody can afford.

## Who would block this?

Nobody rational. Defense contractors keep 99%, lose one unusable apocalypse,
and get an economy about 4x larger where their children are alive to spend the
money.

Blocking this to protect the last 1% is not self-interest. It is arithmetic
failure with a lobbyist.

## Then why has nobody done it?

Because the facts are scattered. Put them in eight billion brains at once and
the insanity becomes visible: change the spreadsheet, keep the deterrent, fund
the trials, stop dying.

## Why this is the funniest joke in the universe.

A normal joke produces one laugh and dies.

This joke tries to turn a shirt into a chain reaction: shirt, conversation,
vote, treaty, clinical trials, treatments, humans still alive to hear another
joke.

The treaty knocks about 407 years off the treatment line. Those avoided
centuries of untreated disease prevent 10.7 billion deaths and 1.93 quadrillion
hours of suffering.

At one laugh per healthy day recovered, that is 206 trillion extra laughs.

The less insulting laugh model, where humans laugh more than once per day
because they are not rocks, counts 3.5 quadrillion.

That is why I wrote on your shirt.

Not because writing on shirts is clever.

Because the smallest dumb-looking action available to you might make humanity
notice it has been keeping 121 spare apocalypses while dying in a 443-year
treatment wait.

## Your instructions

1. Vote at warondisease.org. Drag the slider to say how much of the murder
budget you want redirected to not dying.

2. Pick the humans whose funerals would rather not attend. Their closets are next. Include this paper. OK.

3. Do not break the chain or you will have eternal bad luck as you and everyone you love will suffer and die of horrible diseases.


90 changes: 90 additions & 0 deletions docs/plans/mcp-tasks-improvements-2026-05-24.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
# optimitron-tasks MCP — API improvements plan

**Branch:** `feature/dating-safety-layer` (PR #87)
**Owner:** Mike P. Sinn
**Date:** 2026-05-24
**Source:** Punch list surfaced by a Codex/Claude agent that hit MCP server limitations while restructuring a task hierarchy.

## Problem

The optimitron-tasks MCP server is missing capabilities that another agent needed mid-conversation. Of the 12 items below, the agent estimated the top 3 alone would have saved ~30 minutes and made the task hierarchy correct on the first pass.

## Top 3 (must ship in this PR)

### 1. `updateTask` accepts `parentTaskId`

Currently `parentTaskId` is settable at creation but cannot be changed afterward. If an agent creates a task and later realizes it belongs under a different parent, it is stuck.

**Required semantics:**

- Accept `parentTaskId: string | null` in the `updateTask` Zod schema (`null` = move to top-level / unparent).
- Cycle detection: a task cannot become its own ancestor. If proposed parent is the task itself OR any descendant of the task, reject with a clear 400 error naming the cycle.
- Permission check: same authorization rules as creating a task under that parent.
- Idempotent: re-setting the same `parentTaskId` is a no-op success.

### 2. `updateTask` accepts `isPublic` / `visibility`

Currently all API-created tasks default to `PRIVATE` with no way to flip them public via the API. Mike wants anyone to be able to see and claim seeded tasks.

**Required semantics:**

- Accept `isPublic: boolean` in `updateTask` Zod schema. If `Task.visibility` enum exists separately, accept both `isPublic` and `visibility` and reconcile them (probably: `isPublic = visibility === "PUBLIC"`, so accept either form for API convenience).
- Permission check: only task creator, assignee, or org admin can flip visibility. Public-to-private flip might need additional confirmation if there are existing public-claim records (TBD in design).

### 3. `bulkCreateTasks`

Currently agents make N API calls to create N tasks. For typical workflows (creating 10 grant-request tasks for 10 foundations) this is 10 calls plus another 10 to set dependencies.

**Required semantics:**

- Accept an array of task definitions. Each definition has the same shape as `createTask` input PLUS optional `clientRef: string` (caller-supplied stable handle for cross-references within the batch).
- Parent-child relationships specified inline using `clientRef` for forward references (a child can reference a parent that appears later in the array; resolve in topological order).
- Dependency relationships (`blockerTaskIds`, `blockedTaskIds`) specified inline, also via `clientRef` if pointing to a task in the same batch.
- Atomic transaction semantics: ALL-OR-NOTHING. If task #47 fails validation, the whole batch rolls back. No partial creation.
- Returns the array of created tasks (in same order as input), each with the resolved `taskId`.
- Reasonable batch size cap (e.g. 100 tasks per call) with a clear error if exceeded.

## Nice-to-have (defer or include based on autoplan judgment)

4. **`moveTask` / `reparentTask` dedicated tool** — sugar for `updateTask({ parentTaskId })`. Could defer if (1) lands cleanly.
5. **`bulkUpdateTasks`** — array of `{ taskId, patch }`. Useful for "set all 10 tasks public at once."
6. **`getTaskTree`** — given parent ID, return full descendant tree with dependency relationships. Saves N searches for hierarchy understanding.
7. **`cloneTask`** — duplicate task with new assignee. Useful for templating (10 demand letters for 10 contractors).
8. **`createTask` accepts `blockerTaskIds` at creation time** — currently requires create-then-update. Two calls → one.
9. **`searchTasks` filters by `parentTaskId`** — find all children of a parent without text search.
10. **`updateTask` approval flow clarification** — the "no approval received" error was unclear to the calling agent. Either auto-approve for the task creator, or make the approval mechanism explicit in the error message.
11. **Task templates** — define a template once ("demand letter for defense contractor"), instantiate with variables (company name, CEO name, amount). Probably its own design effort.
12. **Webhooks / notifications on status change** — when a claimed task is completed, notify dependent-task owners + auto-unblock. Substantial new infra; almost certainly its own PR.

## Implementation notes (rough)

- MCP server source location: needs survey (probably `packages/web/src/lib/mcp/` or `packages/web/src/app/api/mcp/`).
- Current `updateTask` / `createTask` / `searchTasks` Zod schemas and handlers: need survey to map current shapes.
- `Task` model is in `packages/db/prisma/schema.prisma` — relevant fields include `parentTaskId`, `isPublic`, `visibility`, `claims`, etc.
- Cycle detection algorithm: BFS/DFS from candidate parent upward (toward root) checking if the task itself appears. Depth-cap at a reasonable number (e.g. 100) with cycle-detection guard. The existing `getTaskAncestors` helper in `packages/web/src/lib/tasks/impact.ts` is the natural starting point.
- Transaction semantics for `bulkCreateTasks`: wrap in `prisma.$transaction(async (tx) => ...)` with serializable isolation if cross-row consistency matters; otherwise the default isolation is fine.

## Target branch + commit semantics

- All work lands on `feature/dating-safety-layer` (PR #87) per the one-PR-at-a-time rule. PR #87 is currently dating-safety + joke-page work; this adds an MCP-improvements category to it.
- Top 3 ship as one focused commit, snapshot if any MCP descriptor docs need updating.

## Test requirements

- For each of the top 3: unit test the happy path + error paths (cycle attempt, permission denial, batch with one invalid task → full rollback).
- Cycle detection test: explicitly try to make a task its own grandparent.
- Idempotency test: call `updateTask({ parentTaskId: X })` twice; second call is a no-op success.
- `bulkCreateTasks` with `clientRef` forward references: child task in position 3 referencing parent in position 7 should resolve correctly.

## Quality gates

1. `NODE_OPTIONS=--max-old-space-size=8192 pnpm --filter @optimitron/web exec tsc --noEmit`
2. `pnpm --filter @optimitron/web test -- mcp` (or whichever pattern catches the MCP server tests)
3. `pnpm --filter @optimitron/db prisma:validate` (if any schema impact)

## Open questions for autoplan to surface

- Should the 9 nice-to-haves ship in this PR (boil the lake) or defer to follow-ups (boil-the-lake-locally)?
- Is the `visibility` enum a thing on `Task`, or just `isPublic` boolean? Affects API surface.
- Should `bulkCreateTasks` use `clientRef` for forward references, or require client to pre-sort topologically?
- For cycle detection on reparenting: does the existing `getTaskAncestors` helper exist and work, or does this need a new BFS?
Loading
Loading