Skip to content

Mindmap main - #569

Merged
nhyiramante1 merged 157 commits into
mainfrom
mindmap-main
Jul 29, 2026
Merged

Mindmap main#569
nhyiramante1 merged 157 commits into
mainfrom
mindmap-main

Conversation

@nhyiramante1

Copy link
Copy Markdown
Contributor

Summary

Adds the mindmap prototype to the Writing Tools repository as a standalone, client-side writing environment.

The prototype helps writers externalize ideas into an editable map while keeping AI contributions visible, reviewable, and subordinate to the writer’s decisions. This PR establishes the application itself; authenticated launch from Writing Tools is added separately in the stacked integration PR.

What this adds

  • An editable mindmap and draft workspace under prototype-mindmap/.
  • Structured AI questions, reflections, and proposed map changes.
  • Explicit confirmation before AI-proposed changes affect the map.
  • Provenance and assistance-level controls.
  • Reader translation view.
  • Local session persistence and migration support.
  • A local IndexedDB event ledger for debugging and research inspection.
  • Unit, integration, evaluation, and browser smoke coverage.
  • Checked-in interface translations.

Telemetry decision

Server-side telemetry was considered, but its current value does not justify the added privacy, consent, and backend complexity. For now, the audit ledger remains local in IndexedDB. Server telemetry can be designed later as a separate feature if a concrete research need emerges.

Scope boundaries

This PR does not:

  • Expose the mindmap from the Writing Tools launcher.
  • Add production hosting or deployment configuration.
  • Synchronize edits back to Word or Google Docs.
  • Add device-flow authentication or token refresh.
  • Send the local event ledger to the backend.

Verification

  • Mindmap TypeScript check.
  • Full Vitest suite.
  • Evaluation TypeScript check.
  • Production build.
  • Playwright browser smoke.

Stack

This is PR 1 of 2.

The follow-up PR targets mindmap-main and adds the authenticated Writing Tools launcher integration.

MaryChen68 and others added 30 commits June 22, 2026 12:29
Standalone prototype app under prototype-uist/ with React UI,
API client, and Vite build config.
- handleSend: protect the suggest box from being overwritten by a new
  placement prime when it holds user-typed text or an active suggestion;
  allow newest auto-prime to replace a prior auto-prime (lastPrimedTextRef).
- Preserve both guardrail and placement notices on the same turn.
- Document the iterative LLM-assisted evaluation in docs/evaluation-log.md
  (test catalog, open items J1/K3, UIST framing).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Pin the word bank; scroll only the region below it (pending, placement,
  rejected) in one bank-scroll-area. Resolves K3 card clipping without
  scrolling the whole pane.
- Add a chat banner when a placement suggestion is awaiting review.
- Make the "Suggest placement from the bank" header sticky within the
  scroll area.
- Condense the topbar to give the working panes more room.
- Emphasize status-bar notices (flash on change + active styling).
- Update evaluation log: J1 and K3 now PASS; record post-Phase-A UX backlog.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Phase B (expand-before-place + box authoring):
- Abandon signal (placementIntent) clears placement state on a stop/pivot.
- Expand-before-place: coach can ask to expand a thin snippet (chat + box-side
  hint); approving the re-said item auto-primes it (scoped to placement flow).
- Box is an authoring surface: box-typed text becomes a user-origin approved
  bank item, then inserts through the unchanged exact-match guardrail.
- Keep/remove placed reference (tri-state: keep/remove/ask) with persistence.
- Placement insertion now follows the coach's focus region; suggestion card
  shows the resolved anchor.

Insertion routing fix (document.ts findParagraphRangeForAnchor):
- Previously only recognized blank-line ("\n\n") paragraph separators, and a
  single global separator broke mixed drafts (single-newline body + a blank
  line before Works Cited), causing inserts to append before Works Cited and
  duplicate. Now uses the next single "\n" boundary. Covered by 2 regression
  tests. Exact-match insertion guardrail unchanged.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ve dead radios

- document.ts: match the separator at the insertion boundary instead of a global
  guess (fixes blank-line accumulation; avoids the mixed-draft L5 failure)
- types/document/App: new into_paragraph insert mode ("Insert seamless") placing
  exact bank text continuing the anchored paragraph; reuses the exact-match
  guardrail, joining space kept outside the verbatim span (AI authors nothing)
- App.tsx: remove the dead editor-mode radios + unused targetKind/placeholderTarget
- document.test.ts: spacing + seamless regression tests (22 passing)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
A writing-thinking tool where the user authors every idea and the AI only
questions, mirrors the user's own words, and captures confirmed structure.
Enforcement in code, calibration in config.

- Headless loop: capture -> segment -> deterministic signal detection ->
  readiness gate -> mirror validation -> per-chunk user confirmation.
- Question mode with deepen/organize intent + settle/narrow/challenge stance.
- Draft panel with question anchoring; concept-map canvas (xyflow) with
  nesting-as-embedding, user-drawn connections, delete/undo.
- Think<->Map slider biases mirror pacing only; grounding gates never move.
- carryForwardIntent: AI-detected commitment lets a single grounded idea
  mirror sooner, fenced by validation + confirmation (idea-only, this-turn,
  source-spanned). suppressionReason diagnostics surfaced in Debug.

74 tests passing; tsc + build clean.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…or dedup

- Phase 2/3 map commands: nest_card/connect_cards with exact + near-match
  reference resolution ("did you mean X?"), declarative/referential blocklist.
- Connection UX: optional relationship wording, side/corner handles preserved,
  draggable endpoints, deletable connections, label on/off toggle.
- Mirror dedup: drop claims already placed on the map (normalized-exact);
  downgrade to a question with an `already_on_map` suppression reason when all
  claims are already settled structure, preventing duplicate cards.
- Nest-intent prompt nudge so first-person "I want X under Y" routes to a
  command, not a mirror.
- DESIGN.md + airtightness-report.md updated to match.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
gpt-5.4 occasionally returns invalid JSON (unescaped double quotes inside a
string value when it quotes the user's wording), which hard-broke the
confirm-continuation flow with a red parse error. chatJSON now retries once
with a strict reminder before failing, the continuation-focus and output-format
prompts steer the model away from raw double quotes (use #ref/paraphrase), and
api.test.ts pins the retry with the exact failure shape.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
A complete direct command with no uncertainty now returns "Done. What would
you like to do next?" regardless of the LLM's chosen mode, instead of a
reflective probe or (via a lastAiText self-match) the mirror-suppressed repeat
question. Consolidated the two command-precedence branches, stopped pre-setting
lastAiText before finish(), and exempted command hand-backs from the anti-repeat
guard so back-to-back commands stay clean. Regression test added.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Auto-clean now lays each connected component out top-down with dagre (clean
rank flow, minimal crossings) and packs components left-to-right with row
wrapping, so unconnected cards spread across the canvas instead of stacking in
one column. Card placement is now a shared, rectangle-overlap-aware
nextRootPosition used by every add path (blank card, reflection, command), so a
new card never overlaps an existing one; the + New card button zooms out to
reveal the free slot when the canvas is cluttered. Adds @dagrejs/dagre
(prototype-mindmap only) and a non-overlap placement test.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Cards the current coach turn names by #ref are now highlighted on the canvas
(amber ring, applied like the drop-target class). The draft anchor highlight
persists until the user clicks inside the draft to dismiss it — clicks elsewhere
never clear it — and a new anchored coach turn re-shows the highlight and opens
the draft if it was minimized.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The organize-focus note was interpolated twice in the system prompt; keep one.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
nhyiramante1 and others added 22 commits July 27, 2026 15:58
`uist` named the conference deadline the prototype was built for, not what it
is. The README calls it the "User-Owned Words Writing Coach": the AI coaches and
extracts candidate wording from the user's own messages, and the word bank's
guardrail is what stops novel AI prose reaching the draft.

Updates the package name, the sibling reference in prototype-mindmap's README,
and the quickstart path. The evaluation log keeps the original directory name
alongside the new one — it is a dated research record, so the name it was
written under is provenance rather than staleness.

Also stops tracking the prototype's build output. Three `dist/` artifacts had
been committed with the original prototype; prototype-mindmap tracks none, and
vendoring is the last moment to drop them before they are baked into main's
history. Adds a `.gitignore` mirroring prototype-mindmap's, minus its
mindmap-specific `eval/runs/`.

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

Item 7 slice 2 plus the root error boundary (item 9).

The launcher integration made the persistence split necessary rather than
merely tidy: PlatformBootstrap has to ask "is there real saved work?" before
mounting App, which meant the boot layer imported storage helpers from the
4,600-line component it renders. session-persistence.ts now owns the persisted
shape, the storage key, and load/write/summarize/clear. The migrations that
transform loaded data into live stores stay in App.tsx — they operate on the
running stores, not on storage.

AppErrorBoundary sits above the ready branch in PlatformBootstrap. Map.tsx
guards the canvas; nothing sat above App, so any render throw blanked the page.
It deliberately does not clear storage: a render crash must leave the saved
mindmap as intact as a token expiry does. Its fallback uses plain strings
because the locale provider lives inside the boundary.

Behaviour-neutral. 355 Vitest (3 new), typecheck, eval typecheck, build green.

Co-Authored-By: Claude <noreply@anthropic.com>
…one 401s

Three prod-readiness fixes to the launcher gate, all fail-closed:

- `VITE_REQUIRE_LAUNCH=false` is now ignored when PROD. The override exists for
  dev servers and Playwright; honouring it in a production build let one stray
  deploy env var ship an ungated bundle with no runtime signal.
- `VITE_BACKEND_URL` is required under PROD and throws at module load. The old
  localhost fallback would have pointed every user browser at their own machine.
- `providerRuntime` is now supplied even when `session` is null, so standalone
  401s reach a blocking screen instead of leaking a raw "Backend 401" chat
  banner. Standalone maps to `launch_required`, not `token_expired` — nothing
  expired, there was never a token.

The backend-URL guard is duplicated in `api.ts` rather than imported from
`platform-session.ts` to keep provider code environment-neutral for the Node
eval runner.

Co-Authored-By: Claude <noreply@anthropic.com>
A failed turn left its optimistic user message in `msgs`. That is not cosmetic:
`msgs` is persisted, and `buildConversationHistory` rebuilds the provider
transcript from it, so every later request replayed a dangling user turn the
coach had never answered — for the life of the saved mindmap. Retrying stacked
a second copy beside the first.

Drop the bubble and restore the text to the composer instead. Not auto-resent:
after a 401 the relaunch can be minutes later, by which point the message is
often stale, and resending spends a real call the user never re-confirmed.

The coach-only turn's catch is unchanged — it has no user message to roll back.

Co-Authored-By: Claude <noreply@anthropic.com>
The choice screen is the first thing a returning user sees, and it was two
undifferentiated bordered boxes.

- Pins the timestamp to the bottom of both cards with a two-row grid, so a
  document name that wraps no longer leaves the pair looking ragged.
- Adds a focus-visible ring. The old rule styled `:hover` only, so keyboard
  users got the UA default outline against a tinted background.
- Gives "continue" a quiet accent. Starting new silently discards the saved
  mindmap, so the accent marks the recoverable path rather than shouting about
  the destructive one — an explicit warning would need a new i18n string.
- Tabular figures so the two times align, plus hover/active depth that
  `prefers-reduced-motion` opts out of.

No string changes: every visible label is an i18n key, so rewording would leave
`zh` untranslated until a paid regeneration.

Co-Authored-By: Claude <noreply@anthropic.com>
Replace the Tools registry assertion with a behavioral one. The old test
restated the registry literal (tier === 'lab', enabled === undefined); the
replacement goes through pagesByTier, the same selector the navbar uses, so
it asserts that Tools is reachable from the Labs menu without a flag rather
than that two fields hold two values. Verified non-vacuous: adding an
enabled predicate that returns false fails it.

Document why reserveBrowserLaunch opens the popup synchronously instead of
using an <a href>: the URL carries a grant id that does not exist until an
async round trip completes, the synchronous open is what detects a blocked
popup before the document is read and transmitted, and pre-minting a grant
to fill an href starts its ~2 minute TTL before the writer clicks.

Co-Authored-By: Claude <noreply@anthropic.com>
kcarnold and others added 4 commits July 29, 2026 11:46
`tsconfig.tsbuildinfo` is incremental-compile state, not source. It is
already listed in `prototype-word-bank/.gitignore`, but the file was
committed before the ignore rule could take effect, and .gitignore does
not apply to already-tracked paths.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@nhyiramante1
nhyiramante1 merged commit 43baf2a into main Jul 29, 2026
12 checks passed
@nhyiramante1
nhyiramante1 deleted the mindmap-main branch July 29, 2026 16:06
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.

3 participants