diff --git a/packages/cli/src/agent/report.md b/packages/cli/src/agent/report.md index 5336274e..58387bd3 100644 --- a/packages/cli/src/agent/report.md +++ b/packages/cli/src/agent/report.md @@ -1,4 +1,4 @@ -# Topic: report (CLI v%(CLI_VERSION)s / topic v3) +# Topic: report (CLI v%(CLI_VERSION)s / topic v4) ## Goal Publish a Taskless report: an unlisted page on tskl.es that shows what @@ -79,10 +79,14 @@ later and deletes one on request. 4. **Show the result.** On success the CLI prints a short summary: the rules, what they found in the code today, what review raised over - the window, the link, and when it expires. Show it to the user - exactly as printed. Then tell them, in one line, that the report can - be deleted after they have reviewed it, and that they only need to - ask. + the window, the link, and when it expires. Relay it to the user as + ordinary chat text, NOT inside a code block or quote: a fenced block + makes the link unclickable and buries the report the whole session + led up to. Keep its content and order; do not add, drop, or reword + facts. Put the link on its own line as a plain URL or a Markdown + link, so the user can open it directly, and render the rules as a + list. The summary already says the report can be deleted on + request, so do not repeat it. If you restate any of the report's numbers in your own words, keep the kinds apart and label each: counts the CLI found **in the code diff --git a/packages/cli/test/report.test.ts b/packages/cli/test/report.test.ts index 8b11cea9..937b24d2 100644 --- a/packages/cli/test/report.test.ts +++ b/packages/cli/test/report.test.ts @@ -878,7 +878,7 @@ describe("taskless report", () => { it("counts only review comments, and asks for a candidate estimate, not pricing", async () => { const { stdout, exitCode } = await run(["agent", "report"]); expect(exitCode).toBe(0); - expect(stdout).toMatch(/^# Topic: report {5}\(CLI v.+ \/ topic v3\)/m); + expect(stdout).toMatch(/^# Topic: report {5}\(CLI v.+ \/ topic v4\)/m); const flat = stdout.replaceAll(/\s+/g, " "); const counting = flat.slice(flat.indexOf("## Counting surfaced")); expect(counting).toContain("**Only review comments count.**"); @@ -899,6 +899,25 @@ describe("taskless report", () => { expect(show).toContain("which are **your estimate**"); }); + // "Show it exactly as printed" read as verbatim, so agents fenced the + // summary and its link stopped being clickable. The summary already says it + // can be deleted, so the recipe no longer asks for that line again. + it("relays the summary as chat text, not a code block", async () => { + const { stdout, exitCode } = await run(["agent", "report"]); + expect(exitCode).toBe(0); + const flat = stdout.replaceAll(/\s+/g, " "); + const show = flat.slice( + flat.indexOf("**Show the result.**"), + flat.indexOf("**Clean up.**") + ); + expect(show).toContain( + "Relay it to the user as ordinary chat text, NOT inside a code block or quote" + ); + expect(show).toContain("Put the link on its own line"); + expect(show).not.toContain("exactly as printed"); + expect(show).toContain("so do not repeat it"); + }); + it("refuses --from and --delete together", async () => { const { stderr, exitCode } = await run([ "report",