Skip to content

feat(agent): serve long topics as an outline with sections on request - #693

Merged
theCodeDrift merged 4 commits into
mainfrom
feat/agent-topics-toc
Nov 12, 2026
Merged

theCodeDrift merged 4 commits into
mainfrom
feat/agent-topics-toc

Conversation

@theCodeDrift

Copy link
Copy Markdown
Member

Closes #672

What

taskless agent <topic> now prints a long topic as an outline that fits one agent tool call: the purpose, the steps, and a ## Sections on request list at the end. Reference material is printed on its own with taskless agent <topic> --section <name>. --full prints the whole recipe.

  • Mechanism (packages/cli/src/prompts/sections.ts, new):
    • Every ## heading is a section, named by its slug.
    • An author marks a section <!-- on-demand --> (on the line above its heading) to leave it out of the outline. The marker is stripped at load, and a misplaced marker throws.
    • Same-recipe cross-references are markdown links ([Quirks](#quirks)). The full text keeps them as links. The outline and section output rewrite a link to an unprinted section as "section quirks".
    • A recipe with no on-demand section prints exactly as before.
  • Command (agent.ts):
    • New --section and --full flags.
    • An unknown section exits 1 and lists the topic's sections.
    • A second positional is still refused, and the error now points at --section.
    • A section fetch captures cli_agent with a section property and never carries the feedback invite.
    • taskless onboard and taskless update serve the same outline.
  • @taskless/cli/prompts is unchanged: it still renders whole recipes, with the markers removed.
  • Recipes: the 17 that were over budget are restructured (each topic version bumped):
    • The steps stay in the outline and link to the detail.
    • Moved into sections: quirk tables, worked examples, input schemas, engine reach lists, update ledger entries, CI templates.
    • route's step 4 now tells the agent to print the ast-grep-reach, vale-reach and legacy-linters sections before deciding.
  • Skill: tells the agent to print a section a step names before acting on that step.
  • OpenSpec: cli-agent gains the outline/section requirement. The change is archived in this PR, since it is a single-PR delivery.

Budget

test/recipe-sections.test.ts holds every topic's outline, and every section printed alone, to 8 KiB (8192 bytes).

  • It measures the worst realistic case: a nightly's long invocation plus the fetch-time directive.
  • For the surveyed topics the feedback invite counts toward the budget.
  • It also checks that every ](#name) link and every agent X --section y citation resolves.

Before, at default output: create-vale-rule 68KB, update 36KB, report 25KB, create-sg-rule 24KB, route 21KB, and 12 more over 8KB. After, all are under 8KB. create-vale-rule's outline is about 5.4KB.

Open questions for review

  1. report --section facts-schema is over budget (~14KB). It is one fenced %(INPUT_SCHEMA)s, and compact JSON would still be 8.3KB. The test carries it as the only explicit exemption, and fails if the exemption goes stale. Fitting it needs the schema served in parts, which I left for a follow-up.

  2. onboard is tight. Its outline is 7.9KB with the default host-tools text. With a real hostTools list and a nightly invocation it can pass 8KB. The test measures default caller state only.

  3. route's outline is also tight, at about 8.0KB.

  4. A few redundant sentences were dropped while restructuring rather than moved, all restatements of nearby text. In onboard.md:

    • step 4's summary of what route decides
    • "This recipe reads it; it does not duplicate it."
    • a repeated "follow the ci recipe"

    In ci.md: the repeated full/diff bullets and the three outcomes. Everything else was moved, not deleted.

  5. Possible follow-up: update --json could list the ledger section names the walk covers, so an agent would not have to match versions itself.

  6. Diff size: about 3.6k insertions and 2.0k deletions. Most of it is recipe text moved between sections. A split would leave a layer whose budget test is red.

@theCodeDrift

Copy link
Copy Markdown
Member Author

@claude /review

@github-actions

github-actions Bot commented Nov 12, 2026 •

Copy link
Copy Markdown
Contributor

Claude finished @theCodeDrift's task in 3m 10s —— View job


Review complete

Review mode: incremental — read 0 prior review thread(s) before reviewing. .prior-review.json held no prior inline threads, review summaries, or comments besides the trigger itself, so this is the first review of this PR; every finding below is [New].

Summary

This is a well-executed, mechanically sound feature. The core mechanism (packages/cli/src/prompts/sections.ts) is small, pure, and does exactly what the PR description claims: lift markers at load time, split rendered text on `## ` headings (skipping fenced blocks), and rewrite same-recipe links to unprinted sections as `section \`name\. recipes.ts's new getServedRecipe/getServedRecipeText/onDemandSections are additive and don't disturb the existing getRecipe/getRawRecipe/getRenderedRecipe render paths beyond the mechanical RecipeSource type threading. agent.ts's --section/--full wiring, the unknown-section/too-many-positionals error paths, and the init.ts/onboard.ts switch to getServedRecipeText all look correct. The OpenSpec requirement addition in openspec/specs/cli-agent/spec.md accurately describes the shipped behavior. The test suite (recipe-sections.test.ts plus the updated call sites in agent-extensions, onboard, reconcile-marker, report, feedback-recipes, legacy-ladder) is thorough — it enforces the 8 KiB budget on every outline and every standalone section, validates every #name link and --section citation resolves, and exercises the actual --section/--full/unknown-section CLI paths end to end.

Spot-checked route.md, onboard.md, and update.md for section/link consistency against the new mechanism (cross-references, on-demand markers sitting directly above headings, the route step 4 instruction to print ast-grep-reach/vale-reach/legacy-linters) — all consistent with the described design.

I posted three inline findings, all minor and non-blocking:

  1. sections.ts:194 — the sectionSlug(title) === name check in renderOutline's table-of-contents formatting is dead/tautological: name is always derived from title via sectionSlug in splitSections, so the condition can never be false. The ternary's real behavior is driven only by title.includes("\")`. Not a functional bug (no current heading has a backtick), but the comment above it implies a divergence check that doesn't exist — worth simplifying.
  2. sections.ts:67 — no uniqueness check on section slugs. Two headings that slugify to the same name would silently collide: an on-demand marker on one would mark both (since onDemand is just a Set<string>), and --section <name> would always resolve to whichever section appears first in the file. No current recipe triggers this, but given how strict this module already is about failing fast on malformed markers, a one-line duplicate check seems in the spirit of the design.
  3. agent.ts:370 — passing --section and --full together silently prefers --section with no documentation of the precedence and no test for the combination.

The four "open questions for review" the author flagged in the PR body (the report --section facts-schema budget exemption, onboard/route's tight margins, and the dropped redundant sentences) are self-disclosed and already reflected faithfully in the code/tests (e.g. the OVER_BUDGET_SECTIONS exemption map in recipe-sections.test.ts that fails if it goes stale) — I didn't find anything beyond what's already called out there.

Comment thread packages/cli/src/prompts/sections.ts Resolved
Comment thread packages/cli/src/prompts/sections.ts Resolved
Comment thread packages/cli/src/commands/agent.ts Resolved
theCodeDrift added a commit that referenced this pull request Nov 12, 2026
Address review on #693: splitSections throws when two headings share a
slug, agent rejects --section combined with --full, and the outline's
table of contents drops a tautological slug check.
@theCodeDrift

Copy link
Copy Markdown
Member Author

Re: @github-actions — "Claude finished @theCodeDrift's task in 3m 10s…"
#693 (comment)

All three inline findings are addressed in 99a7785 (tautological slug check removed, duplicate section names now throw, --section with --full rejected), with tests for each.

— AI Coding Agent

taskless agent <topic> prints a long recipe's steps and a list of the
sections it serves on request; --section <name> prints one and --full
prints all of it. onboard and update serve the same outline. A test holds
every outline and every section to 8 KiB.

Refs #672
Reference material (quirk tables, engine reach lists, input schemas,
ledger entries, templates) moves into sections served on request; the
steps stay in each topic's outline and link to them. Archives the
agent-topics-toc change.

Closes #672
Address review on #693: splitSections throws when two headings share a
slug, agent rejects --section combined with --full, and the outline's
table of contents drops a tautological slug check.
Rebasing onto main brought in text from #682, #683, #686 and #691 that
pushed three outputs past 8 KiB:

- create-sg-rule outline: the `taskless ast` guidance moves to an
  on-demand Reading kinds section, step 4 points at it, and step 5 drops
  its quirk enumeration (the Quirks table lists them).
- create-sg-rule pattern-quirks: the relational entries (follows/precedes,
  has/inside, not) move to a Relational quirks section; validate-rule
  names it beside the other two.
- route outline: #686's note on recipes that limit questions moves to an
  on-demand Limits on asking section, with a one-line pointer in
  Preconditions.
@theCodeDrift

Copy link
Copy Markdown
Member Author

Rebased onto main after #682, #683, #685, #686, #687, #688, #689 and #691 landed. Conflicts and what the resolution did:

A separate commit (docs(agent): fit recipes merged from main back into the section budget) brings three outputs back under 8 KiB after the merge:

— AI Coding Agent

@theCodeDrift
theCodeDrift merged commit f3f3a6e into main Nov 12, 2026
4 checks passed
theCodeDrift added a commit that referenced this pull request Nov 12, 2026
Address review on #693: splitSections throws when two headings share a
slug, agent rejects --section combined with --full, and the outline's
table of contents drops a tautological slug check.
@theCodeDrift
theCodeDrift deleted the feat/agent-topics-toc branch November 12, 2026 05:24
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.

agent: make topics table-of-contents friendly so long recipes fit agent tool output

1 participant