Skip to content

Mindmap/New - #6

Merged
nhyiramante1 merged 12 commits into
mainfrom
explore/tools-first
Oct 30, 2026
Merged

nhyiramante1 merged 12 commits into
mainfrom
explore/tools-first

Conversation

@nhyiramante1

Copy link
Copy Markdown
Contributor

Mindmap: Tools-First Prototype

Summary

A fresh, separate Mindmap in next/, built to test whether we can keep the design's guarantees if the coach reasons freely and only its actions are checked at the moment it attempts them.
The current app in src/ is untouched. The two run side by side so they can be compared.

Spec: docs/tools-first-pass.md

How It Works

Tools and Validation

Four tools:

  • propose_card
  • propose_link
  • propose_nest
  • suggest_idea

Each tool's handler checks its rule when it runs: plain text matching and message order, no regexes or word lists for meaning.

The model writes card text, and the handler checks it word for word against a record of the writer's own messages.

Proposals and Writer Control

  • Every map edit by the coach is a proposal. Nothing reaches the map until the writer accepts it.
  • Tool calls show in the chat.
  • Refusals carry a truthful reason the writer can expand.

Levels

Level Allowed behavior
L0 Cards from the writer's messages
L1 Also from the draft
L2 The coach may also propose links, nesting, and its own ideas, all marked "AI suggested"

Links and nesting below L2 need the writer's own words as evidence, from one message or two adjacent ones.

Limits and Conversation State

  • Up to 3 refused attempts per turn, with the count in each refusal, then text only.
  • A cap of 8 model calls per turn. (This is arbitrary, and I could just change it)
  • Stateless calls: The full conversation is sent every time (the last 40 writer turns), plus a state block containing:
    • The map
    • Pending proposals
    • Recent decisions
    • Everything the writer has declined

Handling Typos

Pieces are quoted exactly as typed, typos included. Allowing the model to return text with typos corrected would make the checker complicated.

UI (Plain for V1)

Chat

  • One line per tool call, with Accept/Reject and the provenance label.

Map

React Flow with visual nesting:

  • Drop a card on another to nest it.
  • Drag it out or press "Out" to separate.
  • Drag to link.
  • Edit, delete, and undo.

Controls

  • Level picker
  • Draft panel
  • Copy map (Markdown)
  • Copy draft
  • Suggestion-adoption setting

Saving

Everything is saved in the browser.

Not Included in V1

  • i18n
  • A tool specifically for making sure the model restates you using only your own words.
  • The adversarial fuzz harness I used to test the current app to make sure it correctly gated unintended model behaviour.
  • L3 (a no-checks on tool calls study level)
  • Sign-in and deploy
  • Matching the current app's look

Testing

Automated Tests

cd next && npm test

63 tests across:

  • Handler rules
  • Evidence rule
  • Budget and call cap
  • History trimming
  • Undo
  • Saving
  • Nesting layout

Type Checking and Build

npx tsc --noEmit
npm run build

The build is 366 kB of JavaScript.

Browser and Live Testing

  • Browser walkthroughs with a stubbed model
  • Live conversations against the real model

Local testing guide: next/TESTING.md

Explains how you could run it locally against any recently checked-out Writing Tools backend.

Open Questions

Whether this meets our expectations and is simple enough for a study.

Attempting to do some writing with it in the meantime.

nhyiramante1 and others added 10 commits October 28, 2026 19:59
Plan for a fresh Mindmap in next/ where the coach reasons freely and its
map actions are checked inside the tool handlers when they execute:
levels, the four tools and their checks, the attempt budget, what the
model sees on each call, what the writer sees, and the v1 scope.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Core of next/ per docs/tools-first-pass.md: the writer record and matching
rule, the map with proposals and undo, the four tools (propose_card,
propose_link, propose_nest, suggest_idea) with their checks in the
handlers, the evidence rule for links and nesting below L2, the context
builder, the Responses client, and the turn loop with the 3-refusal budget
and an 8-call cap. Suggestion adoption uses shared three-word runs instead
of a common-word list; the spec is updated to match. 38 tests.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- The state block now lists everything the writer declined, for the whole
  session, so the coach doesn't propose it again (decisions alone were
  cleared after one turn). Sent as a developer message.
- Only the last 40 writer turns of history are sent; the cut falls where a
  writer message starts, so tool calls stay paired with their results, and
  the state block says how many messages are hidden.
- Card proposals record each piece's most recent match and every match
  (spec §5.1); accepted cards keep these sources.
- The attempt budget is checked per call, so calls in one batch can't
  exceed it.
- An accepted L2 nesting keeps an "AI suggested" mark, like L2 links.
- Nested cards are positioned relative to their parent; nesting, taking a
  card out and deleting a parent keep cards visibly in place.
- Accept decisions name the card a proposal became; tool descriptions say
  any pending proposal can be referenced; one shared set of provenance
  labels for the model and the UI.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Spec §8 and §9 step 1's UI parts:
- Chat with one line per tool call; Accept/Reject on pending proposals (a
  link or nesting waits for its card), the outcome once decided, and a
  collapsed "why" on refusals.
- Map on React Flow with visual nesting: a parent card is a box sized to
  hold its children. Double-click to edit, drop a card on another to nest,
  drag out or "Out" to separate, drag from a card's dot to link, select a
  link and press Delete to remove it, ✕ to delete a card (its children stay),
  Undo. Provenance badges on cards; AI-suggested links are dashed.
- Level picker (applies from the next message), draft panel, copy map
  (Markdown) and copy draft, suggestion-adoption toggle, new session.
- Browser saving that starts fresh on missing or malformed data and reports
  when storage is blocked.
- Everything is locked while a turn runs, since the turn works from a
  snapshot.

Tests for saving, the Markdown export and the nesting layout.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
In current Chrome, Element.scrollIntoView() returns a Promise. The chat's
auto-scroll effect returned it (an expression-bodied arrow), React called
it as the effect's cleanup, and the Chat crash unmounted the whole app, so
the page rendered blank. Give the effect a block body so it returns
nothing.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Pending card, suggestion, link and nesting proposals now show the same short
label the map will (From 2 messages, From your draft, AI suggestion, AI
suggested), from one shared proposalLabel in state/labels.ts, so the writer
sees where the words came from before deciding.

Also braces the three remaining effects written as braceless arrows, the
shape behind the crash fixed in 3b3a0e0. They returned undefined, so they
were safe, but now can't regress.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Undo restores proposal states with the map, so undoing an Accept makes the
  proposal pending again. Only proposals that existed at that point are
  touched (later ones stay), and the model is told the Accept was undone.
  Undo steps saved in the old format are dropped on load.
- Any error mid-turn, not just a failed model call, now shows a notice and
  the turn still reaches history; a tool call left without a result gets an
  error result so the next request stays valid. App.send also catches
  anything outside runTurn.
- A "+ Card" left empty is removed when editing ends, by undoing the add
  step, so no extra undo step is left.
- Editing a quoted card's words drops its stale sources and "From …" label;
  an AI suggestion keeps its label.
- Spec: record Nhyira's L0 decision (the prompt says suggest_idea is
  refused; the handler still refuses), and the rules above.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Text boxes use white-space: break-spaces, so a space typed at the end of
  a wrapped line takes room and the caret visibly moves (it used to hang
  past the edge, so space and backspace looked like they did nothing).
- The message box starts taller and grows with the text up to 40% of the
  screen; the chat column widens on larger screens.
- Card and suggestion proposals show their whole text in the chat; it was
  cut at 80 characters, so the writer couldn't see the full card before
  accepting.
- **bold** in coach replies renders as bold instead of literal asterisks.
  Display only; React still escapes the text.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ger word

Nhyira's call (option A): the coach quotes the writer exactly, typos
included, and the writer fixes spelling on the card afterwards.
- propose_card's description now says so, and that pieces start and end on
  whole words.
- When a card piece or a piece of link/nest evidence is in the writer's
  text only inside longer words (a typo like "lik ethe" glues "the" to a
  letter), the refusal says so and shows the stretch it sits in, instead of
  "not in your messages", so the model can retry with whole words.
- Spec §5.1 records the rule and why near-miss matching was rejected.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@nhyiramante1
nhyiramante1 requested a review from kcarnold October 29, 2026 04:13
@nhyiramante1 nhyiramante1 changed the title Simp Mindmap/New Oct 29, 2026
@kcarnold

Copy link
Copy Markdown
Contributor

What if we merge, swap next with root, and deploy? I guess we'd need to port the OAuth login logic, but that should be straightforward?

nhyiramante1 and others added 2 commits October 30, 2026 07:09
…e apps

- next/ signs in with the same Writing Tools OAuth (PKCE) flow as the
  current app: src/platform/platform-session.ts copied as is (its tests
  too), plus a lean Bootstrap with the Connect screen, the callback,
  expired-session handling (back to Connect, work kept), a not-allowed
  banner and Disconnect. Same client, redirect URI and session key, so no
  backend change and users stay signed in across a switch. Local dev still
  runs without sign-in.
- Model calls send the access token and report sign-in failures the
  backend marks with X-Writing-Tools-Error.
- next/.env.production matches the current app's.
- The Pages workflow gets an "app" choice, current (default) or next.
  Rollback is running it again with current. Pull requests build and
  verify both apps. The verifier takes an optional app folder.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…reject

Review N1 on 8493b20: aiAccessDenied was passed to the chat as `busy`, so
the chat said "The coach is thinking…" and disabled Accept/Reject, which
only change the map. It now disables sending only.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@nhyiramante1
nhyiramante1 marked this pull request as ready for review October 30, 2026 11:47
@nhyiramante1
nhyiramante1 merged commit 86970b9 into main Oct 30, 2026
2 checks passed
@kcarnold

Copy link
Copy Markdown
Contributor

Looking nice so far. It would be cool if you could click one button to load a "demo" situation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants