Skip to content

enhance: proposal review depth (drift detection, deep-link, history view)#5

Merged
mroops0111 merged 7 commits into
masterfrom
enhance/proposal-review-depth
May 24, 2026
Merged

enhance: proposal review depth (drift detection, deep-link, history view)#5
mroops0111 merged 7 commits into
masterfrom
enhance/proposal-review-depth

Conversation

@mroops0111
Copy link
Copy Markdown
Owner

@mroops0111 mroops0111 commented May 24, 2026

Summary

Finishes the proposal-review surface (drift detection, deep-link, history) plus a couple of small UX wins. Closes the last code blockers for v0.1 except the upcoming skill-refactor PR.

What changed

Clarify state machine cleanup

  • PATCH /workspaces/:ws/clarify/:id now takes { status: 'applied', proposalId?, userId }; proposalId is optional so no-impact resolutions transition without producing a Proposal. Removes the last filesystem-touching hack in braid-clarify.

Drift detection rails

  • New DriftIssue schema + GraphNodeMetadata.driftIssues / acknowledgedDrifts. No facet/dimension/kind enums — taxonomy lives in skill prompts so it can evolve without migrations.
  • EvidenceValidator surfaces each entry as a ValidationIssue (code evidence.drift), severity preserved, gated by acknowledgedDrifts. Errors block Apply via the existing blockedByErrors mechanism.
  • New packages/core/skills/shared/drift-detection.md reference (distilled from ReDoc's cross-source-rules.md / facet-rules.md) used by braid-extract (Step 3 — field-level drift → DriftIssue, identity-level → ClarifyTicket) and braid-model (Step 3a cross-source drift, Step 6 stale-drift pruning).

Issue → graph deep-link

  • ValidationIssue.nodeId is now a button that switches to the Graph tab and selects the target node via a new GraphNavigationContext. useGraphSurfaceState is hoisted from GraphPage to App.tsx so selection survives tab switches.

Transcript-level cancel

  • Conversation header gets a Cancel button while a turn is streaming; same SIGTERM path as the global banner.

Proposals tab polish

  • Pending count badge on the Proposals tab label.
  • New Pending / Applied / Rejected segmented filter, mounted in the top tab row via PageActions (no extra row). Applied / rejected entries render read-only.
  • Sidebar collapse button moved to the bottom utility row in both states (Mac-native pattern, matches the Tauri target).

mroops0111 and others added 7 commits May 24, 2026 11:22
PATCH /workspaces/:ws/clarify/:id now takes
{ status: 'applied', proposalId?, userId }. proposalId is optional so
the skill can mark a no-impact ticket applied without producing a
Proposal — removing the last filesystem-touching hack in the
braid-clarify skill (manually moving from answered/ to applied/).

Domain renamed `markAppliedWithProposal(proposalId)` → `markApplied(proposalId?)`.
Service entry point renamed `linkClarifyTicketToProposal` → `markClarifyTicketApplied`.
`ClarifyAppliedEvent.proposalId` becomes optional.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…kill prompts

Builds the rails for Theme 5 drift detection so build-cycle skills can
record specific, gateable inconsistencies between two sources rather
than burying them in ClarifyTicket prose.

Schema
- New DriftIssueId + DriftIssue (id, description, severity,
  sourceReferences [≥2], raisedAt). No facet/dimension/kind enums —
  taxonomy lives in the skill prompt so it can evolve without
  migrations.
- GraphNodeMetadata gains driftIssues? + acknowledgedDrifts? (human
  suppression list). Kùzu codec round-trips automatically (metadata
  is JSON-blob, schema-validated).

Validator
- EvidenceValidator surfaces each drift entry as ValidationIssue with
  code 'evidence.drift', severity preserved. Entries whose description
  appears in acknowledgedDrifts are silenced. Errors gate Apply via
  the existing blockedByErrors mechanism.

Skills
- New shared/drift-detection.md: when to compare (intent-vs-code,
  code-vs-code, intent-vs-intent), 11-dimension checklist (existence,
  terminology, sequence, params, states, rules, permissions, limits,
  api-contract, errors, feature-coverage), what is NOT drift,
  description writing pattern, severity rules, JSON shape.
- braid-extract Step 3 splits identity-level disagreement (→
  ClarifyTicket) from field-level drift (→ DriftIssue on the node).
- braid-model adds Step 3a (cross-source drift extract can't see) and
  Step 6 stale-drift pruning (drift is a derived observation).
- artifact-formats.md documents DriftIssue + acknowledgedDrifts.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
ValidationIssue's nodeId in the proposal review pane is now a button
that switches the active tab to Graph and selects the target node.
Surfaces both pre-existing structural validators (orphan edges,
structural rules) and the new evidence.drift entries from Theme 5.

- New useGraphNavigation context (focusNode / focusEdge) provided by
  App.tsx and consumed by Proposals.tsx's IssueGroup.
- useGraphSurfaceState hoisted from GraphPage to App so selection
  survives tab switches and can be driven from outside the Graph page.
- Edge focus is a placeholder (no edge-selection state on the graph
  surface yet); call-sites are wired so adding edge selection later
  only touches the context.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
While a turn is streaming, the Conversation header shows a Cancel
button next to "New conversation". Targets the most recent runId via
api.cancelRun, same SIGTERM → SSE → button-disappears path as the
global InFlightRunBanner. Hidden during the brief submitting window
where no runId exists yet.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ollapse polish

Three small UX wins for the Proposals tab + Sidebar:

- Pending count next to the Proposals tab label (App.tsx). Hidden when
  zero so the tab strip stays quiet during normal flow. Reuses
  usePendingProposals — same source the sidebar already drives.
- Proposals tab now has a Pending / Applied / Rejected segmented
  switch. Pending wears its own count badge (Applied / Rejected lists
  grow monotonically, count there would be noise). Applied / rejected
  entries render read-only: Apply / Reject buttons hide, validation
  panel hides, status badge shows in the header instead. Invalidating
  the whole `['workspaces', ws, 'proposals']` key on apply/reject
  refreshes Pending + Applied + Rejected in one shot. New shared hook
  `useProposalsByStatus(workspaceId, status)` backs all three;
  usePendingProposals is now a thin wrapper.
- Sidebar collapse/expand button now lives in the top header in both
  states (previously: top when expanded, bottom when collapsed).
  Single icon swaps `PanelLeftClose` ↔ `PanelLeftOpen` based on state.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The Pending / Applied / Rejected segment now portals into the
top tab row's PageActionsHost instead of taking its own header row
inside the Proposals page. Same pattern GraphPage already uses for
ViewToggle / FocusToggle — no extra row, segment sits on the right of
the top tabs.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…h states

Macy native (Finder / Mail / Notes / Things) puts the sidebar
collapse toggle in the bottom-left corner, not the top. Braid ships
through a Tauri desktop shell so it makes more sense to follow the
macOS convention than the web-app one (VS Code / Linear).

- Top header is now just the logo + Braid wordmark; no chrome button
  cluttering the brand area.
- Bottom utility row carries the same Server / Theme / Collapse
  cluster in both expanded and collapsed states. Collapse swaps to
  Expand (PanelLeftClose ↔ PanelLeftOpen) based on state.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@mroops0111 mroops0111 merged commit bcfcd41 into master May 24, 2026
5 checks passed
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.

1 participant