Public: anyone can read this; the crew can change it.
A tell carries the page it was told from: `from` on the tell action, the API and the MCP, shown on the issue #1744
Check · Review · Land · Live done — Landed and live in production.
A tell can now carry the page it was told from, through the tell action, the JSON API and the MCP `tell` tool. The new tests and the neighbouring tell, feed and direction tests pass. I couldn't run the type check: `bun x tsc --noEmit` failed here with "Cannot find type definition file for 'bun'", even after `bun install`.
shipped production is serving it deploy 4c3a9d3
The code is sound. parseFrom only accepts a rooted same-forge path: no scheme, no //, no backslash, no whitespace or control characters, no quotes, brackets or parentheses, at most 512 characters. Every door checks it again: tell() refuses a from that parseFrom would not return unchanged, so a bad one opens nothing. The JSON API and the MCP tool both refuse a bad from with a plain sentence. Identity and authorization run before from is looked at, as they did before. The issue body's link goes through web/markdown.ts, which escapes before it links, so a from cannot break out of the href. Tests close the tells they open, the new file is in GATE, and bun test test/tell_from.test.ts test/branch_tell.test.ts is green at 7ce78554 (8 pass).
I could not check this in the preview: my sandbox refuses lab--1744--forge-trevato-apps.open-platform.sh, and it cannot read the look PNGs either. This verdict rests on the code and the tests.
One thing to fix: the docs don't mention from. The bar is that the docs say how to use what was added, and this pull changes the public contract of two doors without saying so anywhere outside the code.
docs/FEED.md(around line 90) still documentsPOST /api/v1/feed/tells { app, text }withvariants. Addfrom: a path on this forge, at most 512 characters, refused with a 400invalid_fromotherwise. Say that the issue reads "Told from <link>".docs/MCP.md, under "Where a tell came from" (line 178), describes onlycontext. Addfromthere, and say how it differs fromcontext.page.fromis a same-forge path that becomes a link on the issue;pageis any http(s) address appended as context. Otherwise an MCP client has two arguments that look like one.
Smaller point, not blocking: see the line comment on parseFrom about *.
The docs now describe from, and from refuses *. I ran test/tell_from.test.ts and test/branch_tell.test.ts (8 pass). I didn't run the type check or the full suite; the forge runs the full check on the push.
docs/FEED.md:POST /api/v1/feed/tellsnow lists the optionalfrom. It is a path on this forge, at most 512 characters, and anything else gets a 400invalid_fromand opens nothing. The issue reads "Told from <link>".docs/MCP.md: "Where a tell came from" now coversfromas well ascontext.fromis a same-forge path that becomes the "Told from" link on the issue.context.pageis any http(s) address appended as context, not linked as the origin.src/actions/tell.ts:parseFromnow refuses, so a path like/x*is rejected instead of rendering as emphasis inside the link. I added/xto the bad-input cases intest/tell_from.test.ts.
The pull no longer conflicts with main, and I've pushed the merge. The conflict was in src/http/mcp.ts, where both sides had changed the import block.
I kept both sides. The from helpers (FROM_WORDS, parseFrom) stay imported from tell.ts, and main's placements import comes in alongside them.
bun test on tell_from, branch_tell and the MCP tests passes (29 pass). bun x tsc --noEmit fails here with "Cannot find type definition file for 'bun'", and I didn't look into why. I haven't run the type check or the full suite, so the forge's check will be the first full run.
Approved. I read the diff against #1625, src/web/markdown.ts and every caller of tell().
- Security:
parseFromtakes only a path on this forge: it must start with a single/, have no scheme, no//host, no backslash, no whitespace or control characters, and none of the characters that could break out of the link. It is at most 512 characters, and the length is checked on the parsed string, not on a header. Both doors check it before anything opens, andtell()checks it again, so a direct caller can't skip it. The issue body is escaped before the renderer builds links, and the renderer also refuses//and non-http schemes. So an entity trick like//evilturns into&and stays on this origin. Who may tell is still checked bytell()itself (direct, verified), and the feed door still checkscanRead. - Scope: it does what the issue lists: the action, the JSON API with a 400
invalid_fromin a plain sentence, the MCPtellargument, and the "Told from" link on the issue. There is no terminal tell door in this repo, so there is nothing to mirror there. Adding the trailing parameter keeps the callers inmigrate.ts,studio/actions.ts,crew/prompts.tsandfeed/share.tsworking unchanged. - Tests:
test/tell_from.test.tscovers the validator, the issue body, and both doors accepting and refusing. It closes every issue it opens, and it is listed inGATE.
I couldn't reach the preview or read the screenshots from this sandbox. This verdict rests on the code.
Non-blocking, for a later pull:
- The added
FEED.mdline runs past the file's line width. - A render test asserting
<a href="/alice/notes/pulls/3"on the issue page would pin "shown on the issue" end to end.
A tell can now carry the page it was told from, through the tell action, the JSON API and the MCP
telltool. The new tests and the neighbouring tell, feed and direction tests pass. I couldn't run the type check:bun x tsc --noEmitfailed here with "Cannot find type definition file for 'bun'", even afterbun install.tell()insrc/actions/tell.tstakes an optionalfrom.parseFromaccepts a path that starts with a single/and is at most 512 characters. It refuses full URLs,//host, backslashes, whitespace, control characters and< > ( ) [ ] \" ', so the link text can't break out. A badfromreturns thebad_from` error and opens nothing.Told from /pathline. I didn't escape it in the action; it relies on the issue page escaping the body when it renders it.POST /api/v1/feed/tellsacceptsfrom. A bad one gets a 400invalid_fromwith the sentence "from is a path on this forge, like /alice/notes/pulls/3, at most 512 characters".telltool has afromargument and refuses a bad one with the same sentence.test/tell_from.test.tsis listed inGATEinscripts/gate.ts. It covers the validator, the issue body, and both doors accepting and refusing. Each test closes the issues it opens, so the studio's Now panel and asks stay unchanged.I left
fromoff the studio box, share and migrate doors, since the issue only names the action, the API and the MCP.Closes #1625