Discovery-phase research harness - design¶
Date: 2026-06-13 Status: approved (brainstorm) - ready for plan Repos touched: tatara-claude-code-wrapper, tatara-cli, tatara-operator Spec owner repo: tatara (docs index)
Problem¶
The tatara autonomous loop is live and dogfooding. Its discovery phase (turn an idea into a well-formed, human-approvable issue) is thin: the brainstorm task kind opens an idea-labelled issue from a single prompt with no deep cross-platform research procedure, and the issueLifecycle Conversation state has no procedure for an agent to actually deepen a research issue into a converged design before a human approves. We want two agent skills that encode those procedures, driven entirely through the tatara MCP server, that:
- From scratch, do deep cross-platform research and open ONE high-leverage discovery issue (kind
brainstorm). - Follow up on an existing discovery issue: answer maintainer questions, refine into a concrete design in-thread, push toward approval, idle when there is nothing to add (kind
issueLifecycle, Triage/Conversation).
Hard requirement: research issues stay in discovery - never self-implemented - until a human approves.
Constraints (from platform CLAUDE.md hard rules + research)¶
- Agent comms only through the
tataraMCP server. No gh/git SCM tooling exists in the agent surface and none is added. - Skills are baked
SKILL.mdtrees, copied verbatim into/workspace/.claude/skillsat boot (installSkills,internal/bootstrap/skills.go). Format: dir undertemplates/skills/<name>/withSKILL.mdcarrying YAML frontmatter (name,description) + markdown body, helper files by relative path. No Go templating of skill content. - The wrapper is mode-agnostic. "Modes" (
brainstorm,issueLifecycle,review) are operatorTaskSpec.Kindvalues whose prompt text the operator POSTs as the turntext. A baked skill is only reliably used if the turn prompt names it (we do this) and/or its description matches strongly. - The agent pod has ONE repo checked out on disk. Cross-repo context comes only from the tatara-memory graph (
code_cross_repo,query,describe, thecode_*family). - Issue creation egress is
propose_issueonly ->POST /projects/{p}/issues-> Task CRD -> controllerCreateIssueunderszymonrychu-bot. It opens idea-labelled withApprovalRequired=falseand completes the Task. NotriggerLabel=> not force-implemented. - Discovery hold: the self-approve guard (
finishTriageimplement arm) downgrades a<!-- tatara-authored -->issue with no human comment to discuss/idea + Conversation. R1: brainstorm output is never self-approved. - Generic free-form commenting does NOT exist today: commenting is only a side-effect of
issue_outcome(discuss|close)/review_verdict, both bound to a Task kind. The follow-up skill needs to post substantive design comments separately from the terminal state-transition, so we add a thin task-scopedcommenttool. - KISS; no tech debt; conventional commits; JSON slog; table-driven Go tests; newest stable Go pinned; charts cluster-agnostic (no chart change needed here).
Architecture¶
Three layers, one per repo. Skills carry the workflow; MCP tools carry the capability; operator prompt carries the invocation.
brainstorm turn ----> wrapper skill tatara-deep-research
(operator prompt names it) |
| researches via tatara-memory MCP (graph)
| + on-disk repo files
v
propose_issue (MCP) --> operator --> bot opens
idea-labelled discovery issue
issueLifecycle Triage/Conversation turn ----> wrapper skill tatara-research-followup
(operator prompt names it) |
| task_get + read thread
| research the gap (graph + on-disk)
v
comment (NEW MCP) --> operator --> bot posts
| design comments to the issue
v
issue_outcome(discuss) (terminal: hold Conversation,
never self-approve)
Component A - tatara-claude-code-wrapper (skills)¶
Two new dirs under templates/skills/. Baked into the image by the existing COPY templates/ /templates/; installed by installSkills. No Go, chart, or Dockerfile change for the skills themselves (the Dockerfile cli-pin bump in Component B is the only wrapper code change).
tatara-deep-research/SKILL.md¶
Frontmatter: - name: tatara-deep-research - description: Use on an autonomous platform-research (brainstorm) turn to discover one high-leverage improvement and open a discovery-phase issue via propose_issue, after deep cross-platform research over the tatara-memory graph and the on-disk repo.
Body workflow (numbered, with a checklist the agent turns into todos): 1. Orient on goals. Read on-disk ROADMAP.md, MEMORY.md, CLAUDE.md (platform goal, repo charter, the 14 hard rules). Use memory query (global/hybrid) for platform goal and open roadmap themes; describe for the repo. 2. Map current state. code_stats, code_important (high-PageRank entities), code_communities (subsystems), code_bridges (coupling risk), code_cross_repo (cross-repo edges). Then READ the on-disk code for the strongest candidate area (graph points, files confirm). 3. Score leverage. Priority order: live-loop reliability/observability > un-built planned loop features > Phase-9 SOTA backlog > deploy debt. Respect gates (e.g. the memory retrieval-quality eval harness gates any memory ranking/reranker proposal - do not propose downstream memory-ranking work before that gate exists). 4. Dedup. task_list + the repo's open issue list (via task/project reads); skip if a similar idea is already open (avoid colliding with the operator's own brainstorm proposals and the MaxOpenProposals cap). 5. Compose ONE proposal: imperative title; body = problem, evidence (file:line + concrete graph findings), KISS approach that respects the hard rules, explicit scope boundary, open questions for the maintainer. Embed the literal <!-- tatara-authored --> marker so the self-approve guard holds it in discovery. 6. Emit via propose_issue (kind improvement or bug; repo / repositoryRef; project from env). Never set triggerLabel. Exactly one issue per run; then stop (the brainstorm Task completes).
Rules block: comms only via MCP; never open issues via gh/git; one issue per run; stay in discovery; respect all 14 hard rules in the proposal so the loop that implements it will accept it.
tatara-research-followup/SKILL.md¶
Frontmatter: - name: tatara-research-followup - description: Use when continuing an existing discovery/research issue conversation (issueLifecycle Triage/Conversation turn) - read the thread, answer maintainer questions, deepen the proposal into a concrete design, push toward approval, idle when nothing to add. Never self-approve.
Body workflow: 1. Load context. task_get (issue thread, lifecycle state, status); read issue body + all comments. Extract open questions, maintainer asks, unresolved design points. Identify whether a human has engaged. 2. Research the gap. Use the memory graph + on-disk code (cross-repo via code_cross_repo) to answer the specific questions or to deepen a thin proposal. 3. Respond in-thread with the comment tool: answer each question with evidence; refine the proposal into a concrete design (architecture, components, data flow, error handling, testing) plus an implementation outline; surface remaining decisions. Multiple comments allowed; keep each focused. 4. Drive to approval. When the design is converged AND a human has engaged, post a summary of the agreed design and explicitly request the human approval signal (a maintainer comment / the approval label). NEVER self-approve (R1 + self-approve guard). 5. Idle discipline. If there is no human input and nothing genuinely new to add, post nothing and let Conversation idle (~1h). Do not spam. 6. End the turn with issue_outcome(discuss) to hold/return to Conversation; use issue_outcome(close) only if the idea is clearly dead and a human concurred. Never issue_outcome(implement) on a tatara-authored research issue lacking human approval.
Rules block: comms only via MCP; never self-approve; one focused turn; silence over noise.
Tests (wrapper)¶
- A Go test (or extend the existing skill-copy test) asserting both new skill dirs exist under
templates/skills/and eachSKILL.mdparses with non-emptyname+descriptionfrontmatter and a body. - Existing helm-unittest in
charts/.../tests/is unaffected (no chart change).
Component B - tatara-cli (comment MCP tool)¶
New MCP tool in internal/mcp/tools.go: - name: comment - target: operator - args: task (string, defaults from TATARA_TASK via argOrEnv), body (string, required), target (enum issue|mr, default issue). - maps to POST /tasks/{task}/comment with {body, target}.
Boy-scout (adjacent, in scope): fix the stale propose_issue description at tools.go:390 ("created behind the awaiting-approval label") to match reality (opens an idea-labelled issue, no parking).
Tests: table-driven test for tool registration + arg mapping + the REST path/payload (mirroring the existing issue_outcome/propose_issue tool tests).
Release: tag a new cli version after merge. The wrapper Dockerfile pins TATARA_CLI_VERSION and a build-time guard test asserts the operator tools exist - add comment to that guard list and bump the pin to the new tag (this is the only wrapper Go-side change).
Component C - tatara-operator (handler + prompt nudges)¶
- REST handler
POST /tasks/{task}/commentininternal/restapi(alongsideissue-outcome/review/pr-outcomehandlers): validate the Task exists and is non-terminal; resolve the linked issue/MR (issue number from the Task's source metadata, or the linked MR fortarget=mr); postbodyvia the existingscm.Writer.PostCommentprimitive used bytriagePostComment, under the bot token. Return 200 with the posted comment ref. Reuse existing auth/identity; do not add a new SCM code path. - Controller wiring as needed so the handler reaches the writer (follow the
triagePostCommentcall path; no new lifecycle state). - Prompt nudges:
- brainstorm prompt builder (the text behind the
brainstormKind,createProposalpath): add an instruction to invoke thetatara-deep-researchskill. lifecycleTriageText(internal/controller/turnloop.go:58): add an instruction to invoke thetatara-research-followupskill on Triage/Conversation turns.
Tests: REST handler test (POST /tasks/{t}/comment -> writer PostComment invoked with the right issue/MR + body; non-terminal/terminal Task guard); a unit assertion that the two prompt builders contain the skill-invocation text. envtest only where the existing handler tests use it.
Cross-repo contract & ordering¶
- Operator prompt strings reference the exact skill names (
tatara-deep-research,tatara-research-followup) shipped by the wrapper. Single change-set keeps them consistent. - The cli
commenttool callsPOST /tasks/{task}/comment, which the operator must implement. cli tool is unit-testable independently (mock REST); runtime needs the operator handler. - Build-time dependency: the wrapper Dockerfile cli-pin bump + guard update must wait until the cli
commenttool is merged and tagged.
Implementation order (parallel where possible): - Parallel lane 1: tatara-operator (handler + controller + prompt nudges + tests). - Parallel lane 2: tatara-cli (comment tool + stale-desc fix + tests). - Parallel lane 3: tatara-claude-code-wrapper skills (the two SKILL.md trees + skill-presence test). - Serial tail: after cli merges + is tagged, bump the wrapper Dockerfile TATARA_CLI_VERSION pin + guard list, then merge wrapper.
Done definition¶
Per repo: TDD -> requesting-code-review -> fix critical/high -> pre-commit run --all-files -> merge to that repo's main (triggers CI image build) -> nurse the main pipeline until green (re-run, do not misread a uniform ~18min "operation was canceled" control-plane-node eviction as a test failure; watch for ARC stale-listener). Deploy stays gated (infra helmfile) and is OUT OF SCOPE here.
Decisions (locked)¶
- Comment tool is task-scoped (
/tasks/{task}/comment), not arbitrary-issue: reuses existing identity/linkage; skill 2 always runs inside a Task. KISS. - Skill names:
tatara-deep-research,tatara-research-followup. - One issue per from-scratch run (matches the brainstorm Kind, which completes after one proposal; backpressure-friendly vs MaxOpenProposals).
- Research breadth: cross-platform (graph + on-disk).
- Follow-up: full design conversation to approval, with idle discipline.
Out of scope¶
- Deploying any of the three components (infra helmfile, gated).
- The phase-label-dedup migration (separate worktree/agent).
- A new operator Task Kind (skills slot onto existing
brainstorm/issueLifecyclekinds). - Arbitrary-issue commenting outside a Task.