Skip to content

feat(prompt): add communication guidance - #1214

Open
tautvydasLiekis wants to merge 2 commits into
masterfrom
feat/focus-mode
Open

tautvydasLiekis wants to merge 2 commits into
masterfrom
feat/focus-mode

Conversation

@tautvydasLiekis

Copy link
Copy Markdown
Contributor

Linked issue

Closes #1213

What does this PR do?

Adds a ## Communication section with answer-first, milestone-based reporting guidance to single-model and orchestrator system prompts, replacing the forced per-tool-result text rule and the single-model orientation paragraph. Subagents keep their JSON output protocol: append-mode prompt inheritance strips the section. Assumption handling softens from confirm-before-acting to investigate-with-tools, ask only when materially needed.

Context budgets raised to match (systemPrompt 2625 / total 2705 — merged canonical prompt measures 2453 est tokens, ~7% headroom, accommodating #1201's timeout rewording).

Verification: 85 affected unit tests, new TUI e2e test (system prompt carries the section and is stable across turns), and a live tmux session on glm-5.3-flash confirming answer-first responses and zero inter-tool narration.

Checklist

  • I have read CONTRIBUTING.md and agree to the CLA
  • This PR links to an open issue above
  • Tests pass locally (pnpm run test)
  • Lint passes (pnpm run check)
  • Documentation updated if behavior changed

tautvydasLiekis and others added 2 commits September 16, 2026 15:37
Add a ## Communication section (answer-first, milestone reporting,
evidence-based completion to single-model and orchestrator prompts.
Replaces the forced per-tool-result text rule and the single-model
orientation paragraph. Subagents keep their JSON protocol: append-mode
inheritance strips the section.

Budgets raised to match (systemPrompt 2050→2450, measured 2287 est
tokens, 7.1% headroom). Unit + TUI e2e coverage added; user docs in
docs/communication.md.

Co-Authored-By: Kimchi <noreply@kimchi.dev>
EOF
)
Master's timeout-guidance rewording (#1201) adds 78 chars to the
canonical prompt; combined with the communication section the
merged tree measures 2453 est tokens, 3 over the 2450 budget.
Raise systemPrompt to 2625 and total to 2705 (~7% headroom over
the measured 2453/2532).

Co-Authored-By: Kimchi <noreply@kimchi.dev>
@tautvydasLiekis tautvydasLiekis added the new feature Introduces a new feature label Sep 16, 2026
@readme-ai-writer

readme-ai-writer Bot commented Sep 16, 2026

Copy link
Copy Markdown

Documentation Changes Added

Page Section Action Summary
coding-communicationGuides🆕 CreatedAdd a new guide page documenting Kimchi's default communication guidance: answer-first responses, concise clarifications, milestone-based progress reporting, and assumption handling.

🔗 View all changes in ReadMe


Actions

  • Merge documentation branch with PR merge
  • Delete documentation branch with PR close

If neither actions are selected, on PR close/merge the docs branch in ReadMe will remain open.

@kimchi-review

kimchi-review Bot commented Sep 16, 2026

Copy link
Copy Markdown

Kimchi Code Review

Property Value
Commit 7eb77a0
Author @tautvydasLiekis
Files changed 7
Review status Completed
Comments 4 (4 info)
Duration 66s

Summary

📊 Review Score: 88/100 (overall code quality — 0 lowest, 100 highest)
⏱️ Estimated effort to review: 2/5 (1 = trivial, 5 = very complex)

🧪 Tests: yes — Coverage is strong: unit tests assert the new ## Communication section appears exactly once in single and orchestrator modes, is excluded from subagent mode, and is positioned after project context; negative assertions guard against removed wording regressing. prompts.test.ts verifies stripHumanResponseStyle removes the section from inherited worker prompts with and without activeToolNames, and a new e2e test confirms the guidance is sent unchanged on successive turns. The token budget test was updated consistently (2453 * ~1.07 ≈ 2625, and 2625 + 80 = 2705). The only gap is that the strip regex is tested only in the Communication-is-last position, not mid-prompt.

📝 Found 4 issue(s). See inline comments for details.

What to expect

Kimchi will analyze the changes in this pull request and post:

  • A summary of the overall changes
  • Inline comments on specific lines with findings categorized by issue type

The review typically completes within a few minutes. This comment will be updated once the review is ready.

Interact with Kimchi
  • @getkimchi review — re-trigger a full review on the latest commit
  • @getkimchi summary — regenerate the PR summary
  • @getkimchi ignore — skip this PR (no review will be posted)
  • Reply to any inline comment to ask follow-up questions or request clarification
Configuration

Reviews are configured by your organization admin.
Review instructions, excluded directories, and severity thresholds can be adjusted per repository in the Kimchi dashboard.


Powered by Kimchi — AI-powered code review by CAST AI

@kimchi-review kimchi-review Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📊 Review Score: 88/100 (overall code quality — 0 lowest, 100 highest)
⏱️ Estimated effort to review: 2/5 (1 = trivial, 5 = very complex)

🧪 Tests: yes — Coverage is strong: unit tests assert the new ## Communication section appears exactly once in single and orchestrator modes, is excluded from subagent mode, and is positioned after project context; negative assertions guard against removed wording regressing. prompts.test.ts verifies stripHumanResponseStyle removes the section from inherited worker prompts with and without activeToolNames, and a new e2e test confirms the guidance is sent unchanged on successive turns. The token budget test was updated consistently (2453 * ~1.07 ≈ 2625, and 2625 + 80 = 2705). The only gap is that the strip regex is tested only in the Communication-is-last position, not mid-prompt.

📝 Found 4 issue(s). See inline comments for details.

return [...new Set(toolNames)].filter(Boolean)
}

function stripHumanResponseStyle(prompt: string): string {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ℹ️🐛 Bug

The regex in stripHumanResponseStyle requires a newline immediately after the ## Communication header ([^\n]*\n). If a parent prompt ever ends exactly at the header with no trailing newline or body, the replacement silently no-ops and the bare ## Communication header leaks into the worker prompt. Prompts built by buildPrompt always include a body, so this is a latent edge case rather than an active bug.

💡 Suggestion: Make the trailing newline optional: /(^|\n)## Communication\b[^\n]*(?:\n|$)[\s\S]*?(?=\n#{1,2} |\n*$)/g, or add a comment documenting the invariant that the Communication section always has a body.

}

describe("default agents — subagent system prompt snapshot", () => {
it.each([

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ℹ️🧪 Testing

The new stripHumanResponseStyle tests only cover the case where ## Communication is the final section of the parent prompt (exercising the \n*$ lookahead branch). The mid-prompt case — where Communication is followed by another ## heading and the lookahead (?=\n#{1,2} ) must terminate the lazy match — is untested, so a future edit to the lookahead pattern could regress middle-section stripping without a failing test.

💡 Suggestion: Add a case with a parent prompt like "## Rules\n...\n## Communication\n...\n## Environment\n..." asserting that Communication content is removed while the trailing ## Environment section is preserved.

return [...new Set(toolNames)].filter(Boolean)
}

function stripHumanResponseStyle(prompt: string): string {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ℹ️🔧 Maintainability

stripHumanResponseStyle uses lookahead (?=\n#{1,2} |\n*$) while the adjacent stripAvailableToolsSection uses (?=\n#+ |\n*$). If the COMMUNICATION constant ever contains a line starting with # or ## (e.g., an embedded markdown or code example), stripping would stop early and leak the remainder of the section into worker prompts. The current constant has no such lines, so this is documentation-level risk.

💡 Suggestion: Add a brief comment on stripHumanResponseStyle noting that the COMMUNICATION section must not contain level-1/2 headings, or align the lookahead with the sibling function's #+ pattern if behavior parity is intended.

})
for (const prompt of prompts) {
expect(prompt).toContain("## Communication")
expect(prompt).toContain("Explicit output formats, including code-only or structured data, take precedence")

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ℹ️🧪 Testing

The assertion expect(prompts[1]).toBe(prompts[0]) enforces byte-identical system prompts across turns. This is a reasonable stability guard, but it will fail on any future legitimate addition of per-turn dynamic content (e.g., timestamps, turn counters, telemetry markers) to the system prompt, and the failure message won't explain the intent.

💡 Suggestion: Keep the strict equality if prompt stability is a hard requirement, but rename the trace step or add a comment clarifying it guards prompt-identity for cache stability; otherwise compare a normalized form (e.g., strip known-volatile segments) instead.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

new feature Introduces a new feature

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add default communication guidance to system prompt (focus mode)

1 participant