Repository navigation
feat(studio): show the proposal that wrote a memory fact - #2229
Merged
Merged
Conversation
peppescg
force-pushed
the
feat/studio-memory-proposal-2223
branch
from
October 9, 2026 15:33
299a1b3 to
4019116
Compare
peppescg
changed the base branch from
feat/studio-foundation-2204
to
feat/studio-shell-search-2205
October 9, 2026 15:33
peppescg
added this pull request to stack #2227
October 9, 2026 15:33
peppescg
force-pushed
the
feat/studio-memory-proposal-2223
branch
from
October 11, 2026 14:57
4019116 to
22ccd78
Compare
kantord
force-pushed
the
feat/studio-memory-proposal-2223
branch
2 times, most recently
from
October 13, 2026 10:54
242b112 to
3a96992
Compare
peppescg
force-pushed
the
feat/studio-memory-proposal-2223
branch
from
October 14, 2026 08:44
3a96992 to
53d3b42
Compare
Pin what the BFF maps from the SDK's UserModelRevision today, for the current value and its history, and the order of the fact detail's Details rows, before the Proposal row is added. Refs #2223 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The BFF now maps sourceProposalId from the SDK's UserModelRevision, and the memory revision contract carries it as a string that is empty when no proposal wrote the revision, like sourceSessionId. The fact detail page shows the prototype's Proposal row, in monospace, only when the field is set, linking to Settings > Learning (no route addresses one proposal). Closes #2223 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
kantord
force-pushed
the
feat/studio-memory-proposal-2223
branch
from
October 14, 2026 08:59
53d3b42 to
d5aa7be
Compare
kantord
approved these changes
Oct 14, 2026
Member
|
Post-merge review follow-ups for this PR. No blockers or regressions found. Items worth tracking were filed here:
Other candidate findings were checked and dropped as not worth tracking. Fully or partially written by an AI agent. |
Merged
2 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
This is the memory fact detail's Proposal row from the Studio alignment (#2210), a follow-up to #1854 (#2222). It's the top of a GitHub stack: #2225 → #2226 → #2228 → this PR. Review and merge from the bottom.
The daemon already reports which learning proposal wrote a memory revision (
UserModelRevision.source_proposal_id), but Studio's BFF dropped it. The BFF now maps it, the memory revision contract carries it, and the fact detail shows the prototype's Proposal row when it's set.What changed
apps/contracts/src/schemas/knowledge.ts):memoryRevisionSchemagainssourceProposalId: z.string(), an empty string when no proposal wrote the revision. This is the same shape assourceSessionId.openapi.jsonandtypes.gen.tsare regenerated withtask studio:generate; nothing else in the contract changes.apps/server/src/mecatl/knowledge.ts):memoryRevisionFromSdk()mapssourceProposalIdfrom the SDK'sUserModelRevision, for the current revision and for every history entry.apps/web/src/features/memory/memory-fact-detail.tsx): the prototype's Proposal row, between Source session and Updated. The label is "Proposal", the value is the proposal id in monospace, and it links to Settings → Learning (/workspace/settings/learning) with the samehover:underlinelink as Source session. The row is absent when the id is empty.Visible change
A fact written by a learning proposal gets one more row in Details, Proposal, with the proposal id. The rows below it move down by one row. A fact with no proposal looks exactly as before.
Differences from the prototype
None for the row itself: same label, position, monospace value, link styling, and link target (
/workspace/settings/learning) asstack-08'smemory-fact-detail.tsx.No regression
Pinning tests
2e9fd6256was committed first, alone, and passes on #2225's head (db98c3768) and on this branch:server/src/mecatl/knowledge.test.ts, "maps a memory revision's provenance for the current value and its history": an exacttoEqualof whatgetMemorymaps from an SDK revision, for the current value and one history entry, plus the request sent to the SDK. There was no adapter test forgetMemorybefore.web/src/features/memory/memory-fact-detail.test.tsx, "orders the Details rows key first and the update time last": the exact row labels, in order, for a fact with a source session.Modified tests
sourceProposalId("proposal-7"for the current revision,""for the history entry). The test was written to catch fields the mapping drops, and now it also checks the new field. No expectation was removed.detail()fixture gainssourceProposalId: ""on each revision, which the contract type now requires. No assertion changes.getMemoryreturnssourceProposalId: "proposal-7", which the type now requires.New tests
server/src/routes/knowledge.test.ts):GET /api/v1/user-memory/{key}servessourceProposalId, the body round-trips throughmemoryDetailResponseSchema, an empty string is accepted, and a revision without the field is rejected.proposal-7to/workspace/settings/learningin monospace, between Source session and Updated; and without a proposal there is no Proposal row.The
mecated --mockintegration test isn't extended: its memory coverage reads the list and a missing key's 404, not revision fields.Gate counts
db98c3768)task studio:browser(desktop + mobile Chromium)Screenshots
Captured with a throwaway Playwright journey (Chromium, not committed) with offline BFF routes, a fixed clock (2026-09-25 12:30 UTC),
Europe/Rome, and en-US, at desktop 1280×800 and mobile 390×844, in light and dark. Both trees get the same BFF responses, includingsourceProposalId; the before tree ignores it. Before is #2225's head (db98c3768), after is this PR's head (299a1b3). They were captured before the stack was linearised onto #2228. That rebase was conflict-free, and neither #2226 nor #2228 touches the memory fact detail. The gates were rerun on the rebased head. Each tree was captured twice and the two runs matched pixel for pixel. Every pair was pixel-compared; red boxes mark the regions that differ. Desktop composites are downscaled to 1600px wide.Fact written by a learning proposal
Intended change: a Proposal row between Source session and Updated, the proposal id in monospace, linking to Settings → Learning. Everything below it moves down one row.
Dark and mobile
Desktop, dark:
Mobile, light:
Mobile, dark:
Fact with no proposal
No change: the revision's
sourceProposalIdis empty, so there is no Proposal row. Before and after are identical pixel for pixel.Dark and mobile
Desktop, dark:
Mobile, light:
Mobile, dark:
Re-verification (2026-10-11)
Re-verified at this head: no change needed.
Closes #2223
🤖 Generated with Claude Code