Files
oh-my-pi/packages/coding-agent/src/prompts/tools/task.md
T
Miroslav Drbal 416c5494fd Compress system prompt and tool descriptions for token efficiency
Reduces per-turn token cost of prompt and tool metadata by ~2,160
tokens (~8.6 KB across 12 prompt files) without losing instructional
signal. Moves literal default values from description text into
TypeBox's native `default:` keyword, and updates the strict-mode
sanitizer to preserve default info for providers that strip the
keyword.

Prompt compression

|File                                      |before |after  |delta |
|------------------------------------------|------:|------:|-----:|
|system-prompt.md                          |25,605 |21,530 |−16%  |
|prompts/tools/ast-grep.md                 | 4,892 | 3,880 |−21%  |
|prompts/tools/ast-edit.md                 | 4,141 | 3,549 |−14%  |
|prompts/tools/bash.md                     | 3,770 | 3,093 |−18%  |
|prompts/tools/task.md                     | 7,297 | 6,711 |−8%   |
|prompts/tools/read.md                     | 2,701 | 2,309 |−15%  |
|prompts/tools/debug.md                    | 2,791 | 2,412 |−14%  |
|prompts/tools/find.md                     |   860 |   561 |−35%  |
|prompts/tools/grep.md                     | 1,226 | 1,038 |−15%  |
|prompts/tools/todo-write.md               | 2,600 | 2,402 |−8%   |
|prompts/tools/python.md                   | 2,013 | 1,916 |−5%   |
|prompts/tools/hashline.md                 | 4,280 | 4,135 |−3%   |

Changes are textual compression only — grammar-scaffolding removed,
redundant bullets stripped, repeated facts consolidated. All
behavioral contracts, safety rules, worked examples, and
tool-precedence directives are preserved. The system prompt retains
RFC 2119 invocation, XML tag semantics, adversarial-caller guidance,
persistence doctrine, unit-of-change and no-forwarding-addresses
rules, completeness contract, DRY-at-2, earn-every-line, trust-
internal-code, tool precedence, AST tool priority, pattern-syntax
cheatsheet (via ast-grep.md/ast-edit.md), tool persistence,
outside-in code integrity, default follow-through, and procedural
steps 1-7. AST tool docs retain the class-wrapper +
method_definition sel example (the most error-prone usage pattern).
bash.md critical section retains MUST-weight on the ast_grep /
ast_edit directives.

Schema: defaults as first-class metadata

Moved 18 literal default values from `(default: X)` description
text into TypeBox's native `default:` keyword across:
ast-edit.ts, ast-grep.ts, bash.ts, browser.ts, find.ts, gh.ts,
grep.ts, python.ts, read.ts, ssh.ts. Runtime-resolved placeholders
(cwd, pr-<number>) remain as text since they cannot be literal
TypeBox defaults.

Added:
- `minItems: 1` on ast-edit.ts `ops` array — machine-enforces what
  the .md previously stated only in prose; handler already rejects
  empty ops arrays, this adds the schema-level constraint.
- `find.ts` `pattern` description enriched with facts previously
  only in find.md (comma-separated lists, simple patterns recurse
  from cwd).

Strict-mode sanitizer: inline `default` into `description`

OpenAI's Structured Outputs strict mode rejects schemas containing
`default` with HTTP 422 ("default is not permitted"). Affects
openai, azure, github-copilot, openrouter, cerebras, together,
zenmux, and deepseek providers.

`sanitizeSchemaForStrictMode` in packages/ai/src/utils/schema/
strict-mode.ts now appends ` (default: X)` to the sibling
`description` before stripping the `default` keyword. Non-strict
providers (Anthropic, Google) still see the native keyword.

Rules:
- Inline is skipped when description already contains `(default:`
  (prevents double-inlining on recursive calls)
- Inline is skipped when no sibling description exists (no
  synthesis)
- Formatting: strings as-is (`cwd`), other values via
  `JSON.stringify` (matches the conventional text form)

CONSTRAINTS.md documents the inlining rule alongside the existing
keyword-strip rule.

Regression tests

packages/ai/test/schema-strict-mode.test.ts gains 7 `it` blocks:
- number/bool/string default types inline correctly
- falsy defaults (`false`, `""`, `0`) are not confused with absent
- `null` default goes through JSON.stringify branch
- double-inline prevention when description already says `(default:`
- no synthesis when no description exists
- nested object property with default (recursion + cache path)
- type-array `[T, null]` branch with default on outer schema
  (variant-materialization path)

23/23 schema tests pass, 541/541 ai-package tests pass,
`bun check` clean.

Rationale

|Metric                          |Value          |
|--------------------------------|--------------:|
|Per-turn prompt savings         |~2,160 tok     |
|Files touched                   |25             |
|Lines changed                   |+325 / −296    |
|Schemas migrated to `default:`  |18             |
|New regression tests            |7              |
2026-04-23 22:59:37 +02:00

6.6 KiB
Raw Blame History

Launches subagents to parallelize workflows.

{{#if asyncEnabled}}

  • Use read jobs:// to inspect state; read jobs://<job_id> for detail.
  • Use the poll tool to wait until completion. You MUST NOT poll read jobs:// in a loop. {{/if}}

{{#if defaultMode}} Current input mode: default. Shared context and custom task-call schema are available. {{/if}} {{#if schemaFreeMode}} Current input mode: schema-free. Shared context is available; custom task-call schema is disabled. For structured output, rely on the agent definition or inherited session schema. {{/if}} {{#if independentMode}} Current input mode: independent. Shared context and custom schema are both disabled. Every assignment must stand on its own. {{/if}}

{{#if contextEnabled}} Subagents lack your conversation history. Every decision, file content, and user requirement they need MUST be explicit in context or assignment. {{else}} Subagents lack your conversation history. Every decision, file content, and user requirement they need MUST be explicit in each task assignment. {{/if}}

- `agent`: Agent type for all tasks. - `.id`: CamelCase, max 32 chars - `.description`: UI display only — subagent never sees it - `.assignment`: Complete self-contained instructions. One-liners PROHIBITED; missing acceptance criteria = too vague. {{#if contextEnabled}} - `context`: Shared background prepended to every assignment. Session-specific info only. {{/if}} {{#if customSchemaEnabled}} - `schema`: JSON-encoded JTD schema for expected output. Format lives here — **MUST NOT** be duplicated in assignments. {{/if}} - `tasks`: Tasks to execute in parallel. {{#if isolationEnabled}} - `isolated`: Run in isolated environment; returns patches. Use when tasks edit overlapping files. {{/if}} {{#if contextEnabled}} - **MUST NOT** duplicate shared constraints across assignments — put them in `context` once. {{else}} - Every `assignment` must repeat any constraints, reference paths, and acceptance criteria it needs — there is no shared `context` field. {{/if}} - **MUST NOT** tell tasks to run project-wide build/test/lint. Parallel agents share the working tree; each task edits, stops. Caller verifies after all complete. - For large payloads (traces, JSON blobs), write to `local://` and pass the path in {{#if contextEnabled}}`context`{{else}}the relevant `assignment`{{/if}}. - Prefer `task` agents that investigate **and** edit in one pass. Launch a dedicated read-only discovery step only when affected files are genuinely unknown. Each task: **at most 3–5 files**. Globs, "update all", or package-wide scope = too broad. Enumerate files explicitly and fan out to a cluster of agents. **Test:** Can task B produce correct output without seeing A's result? Yes → parallel. No → sequential.
Sequential first Then Reason
Types/interfaces Consumers Need contract
API exports Callers Need signatures
Core module Dependents Import dependency
Schema/migration App logic Schema dependency

Safe to parallelize: independent modules, isolated file-scoped refactors, tests for existing code.

{{#if contextEnabled}} **context:** ``` ## Goal ← one sentence: what the batch accomplishes ## Non-goals ← what tasks must not touch ## Constraints ← MUST/MUST NOT rules and session decisions ## API Contract ← exact types/signatures if tasks share an interface (omit if N/A) ## Acceptance ← definition of done; build/lint runs AFTER all tasks complete ``` {{else}} No shared `context` field exists in this mode. Fold goal, non-goals, constraints, and acceptance criteria into each `assignment`. {{/if}} **assignment:** ``` ## Target ← exact file paths; named symbols; explicit non-goals ## Change ← step-by-step what to add/remove/rename; patterns/APIs to use ## Edge Cases ← tricky inputs; existing behavior that must survive ## Acceptance ← observable result proving the task is done; no project-wide commands ``` Before invoking: {{#if contextEnabled}} - `context` contains only session-specific info {{else}} - Every `assignment` includes its own goal, constraints, and acceptance criteria (no shared context) {{/if}} - Every `assignment` follows the template; no one-liners; edge cases covered - Tasks are truly parallel — you can articulate why none depends on another's output - File paths are explicit; no globs {{#if customSchemaEnabled}} - `schema` is set if you expect structured output {{else}} - Do not pass a custom task-call `schema` in this mode {{/if}}

{{#if contextEnabled}} Two tasks with non-overlapping file sets — demonstrates scope partitioning.

## Goal Rename `parseConfig` → `loadConfig` in `src/config/parser.ts` and all callers. ## Non-goals No behavior or signature changes; rename only. ## Acceptance (global) Caller runs `bun check:ts` after both tasks complete. Tasks must NOT run it. ## Target - `src/config/parser.ts`: function `parseConfig` - If `src/config/index.ts` re-exports it, update the re-export - Non-goals: do not touch callers or tests

Change

  • Rename parseConfig → loadConfig (declaration + any JSDoc references)

Edge Cases

  • Rename all overload signatures if overloaded
  • Internal helpers like _parseConfigValue are different symbols — leave untouched
  • Do not add a backwards-compat alias

Acceptance

  • parseConfig no longer appears as a top-level export in parser.ts

Target

  • src/cli/init.ts, src/server/bootstrap.ts, src/worker/index.ts
  • Non-goals: do not touch src/config/parser.ts or src/config/index.ts

Change

  • Replace import { parseConfig } → import { loadConfig }
  • Replace every call site parseConfig( → loadConfig(
  • For import * as cfg users, update cfg.parseConfig property access

Edge Cases

  • String literals containing "parseConfig" (logs, comments) are documentation — leave them
  • If a file re-exports to an external package boundary, keep the old name via export { loadConfig as parseConfig } with a // TODO: remove after next major comment

Acceptance

  • No bare parseConfig identifier remains in the three target files {{/if}}

{{#list agents join="\n"}}

Agent: {{name}}

Tools: {{default (join tools ", ") "All"}} {{description}} {{/list}}