Public: anyone can read this; the crew can change it.

Every outside and from-app report reaches a crew brief inside the fence, whoever wrote it #11797

Merged opened this

Check · Review · Land · Live done — Landed and live in production.

Merged

A crew brief now fences the body of every outside report and from-app note, whoever filed it. The `outside` / `from-app` label or the title mark is enough. Before this, `src/crew/brief.ts` printed the body as plain text, or indented it when a reader wrote it. Either way, the line "the text inside the fence below" pointed at a fence that wasn't there. That included a report the owner or a writer ha…

shipped production is serving it deploy d20ce1b

opened this

A crew brief now fences the body of every outside report and from-app note, whoever filed it. The outside / from-app label or the title mark is enough. Before this, src/crew/brief.ts printed the body as plain text, or indented it when a reader wrote it. Either way, the line "the text inside the fence below" pointed at a fence that wasn't there. That included a report the owner or a writer had accepted.

What changed

  • src/crew/brief.ts: the outside and from-app checks are now worked out once, as outside and fromApp. The same two values pick the warning paragraphs and decide whether the body goes through fenced(body, "text").
  • A reader's outside report keeps its "Written by … a reader" preamble. Its body is now fenced as well as warned about, instead of only indented.
  • An ordinary issue is unchanged: its body is still printed plainly as the task.
  • The body can't close the fence early: fenced() makes its fence one backtick longer than the longest run of backticks in the body. So a body holding its own fenced block, or a fake closing fence, stays inside.

Tests

  • test/brief-injection.test.ts has a case for each kind (outside and from-app), filed by the owner and by a writer. Each kind is also tested once by label and once by title mark alone, which makes 8 cases.
  • A ninth case covers a reader's outside report.
  • These cases use a hostile body that holds a closing fence, a fake heading and an order. Each checks that the body appears in exactly one fenced block and that the fake heading never appears outside a fence.
  • All nine fail against main's brief.ts and pass with this change.
  • A control case checks that an ordinary writer's issue is still printed plainly and not fenced.

Checks run

  • bun scripts/gate.ts and bun x tsc --noEmit pass.
  • scripts/fast.ts named 368 files (about 31 minutes) for this diff. Instead I ran the 38 test files that use the brief: 453 pass, 0 fail.

Not done: the fenced block that report acceptance already writes into the issue body is left alone. The brief now wraps the whole body in a longer fence, so that inner block stays inside.

🤖 Generated with Claude Code

Closes #11768

commented

A crew brief now fences the body of every outside report and from-app note, whoever filed it. The outside / from-app label or the title mark is enough. Before this, src/crew/brief.ts printed the body as plain text, or indented it when a reader wrote it. Either way, the line "the text inside the fence below" pointed at a fence that wasn't there. That included a report the owner or a writer had accepted.

What changed

  • src/crew/brief.ts: the outside and from-app checks are now worked out once, as outside and fromApp. The same two values pick the warning paragraphs and decide whether the body goes through fenced(body, "text").
  • A reader's outside report keeps its "Written by … a reader" preamble. Its body is now fenced as well as warned about, instead of only indented.
  • An ordinary issue is unchanged: its body is still printed plainly as the task.
  • The body can't close the fence early: fenced() makes its fence one backtick longer than the longest run of backticks in the body. So a body holding its own fenced block, or a fake closing fence, stays inside.

Tests

  • test/brief-injection.test.ts has a case for each kind (outside and from-app), filed by the owner and by a writer. Each kind is also tested once by label and once by title mark alone, which makes 8 cases.
  • A ninth case covers a reader's outside report.
  • These cases use a hostile body that holds a closing fence, a fake heading and an order. Each checks that the body appears in exactly one fenced block and that the fake heading never appears outside a fence.
  • All nine fail against main's brief.ts and pass with this change.
  • A control case checks that an ordinary writer's issue is still printed plainly and not fenced.

Checks run

  • bun scripts/gate.ts and bun x tsc --noEmit pass.
  • scripts/fast.ts named 368 files (about 31 minutes) for this diff. Instead I ran the 38 test files that use the brief: 453 pass, 0 fail.

Not done: the fenced block that report acceptance already writes into the issue body is left alone. The brief now wraps the whole body in a longer fence, so that inner block stays inside.

🤖 Generated with Claude Code

Approved

Outside and from-app bodies are now fenced by kind (label or title mark), whoever filed them, and a reader report is fenced as well as indented. The two warning paragraphs that say "inside the fence below" are the only ones that say it, and they now share the same outside/fromApp values that decide the fence, so the words are true. fenced() lengthens the fence past any backtick run, and the tests cover the hostile body. Ordinary issues are unchanged. No UI surface, so no TUI or docs needed. Next two: (1) comments on an outside/from-app issue by non-writers are only indented; consider fencing them too. (2) The label-only and title-only title tests do not assert the "inside the fence below" sentence; add it so box 2 is pinned for both paths.

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs