Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -1 +1,14 @@
pnpm-lock.yaml

# Subagent partials and the files that consume them must preserve exact whitespace
# around `<!-- include: ... -->` open/close directives and `<!-- children -->`
# placeholders. Prettier's auto-insertion of blank lines around HTML-comment lines
# breaks slot substitution semantics β€” see packages/agents/content/_partials/README.md.
packages/agents/content/_partials/
packages/agents/content/subagents/_partials/
packages/agents/content/subagents/aspect-code-reviewer.md
packages/agents/content/subagents/aspect-silent-failure-reviewer.md
packages/agents/content/subagents/aspect-test-reviewer.md
packages/agents/content/subagents/code-simplification-reviewer.md
packages/agents/content/subagents/orchestrated-coder.md
packages/agents/content/subagents/orchestrated-reviewer.md
13 changes: 13 additions & 0 deletions packages/agents/.prettierignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,15 @@
coverage/
dist/

# Subagent partials and the files that consume them must preserve exact whitespace
# around `<!-- include: ... -->` open/close directives and `<!-- children -->`
# placeholders. Prettier's auto-insertion of blank lines around HTML-comment lines
# breaks slot substitution semantics β€” see content/_partials/README.md.
content/_partials/
content/subagents/_partials/
content/subagents/aspect-code-reviewer.md
content/subagents/aspect-silent-failure-reviewer.md
content/subagents/aspect-test-reviewer.md
content/subagents/code-simplification-reviewer.md
content/subagents/orchestrated-coder.md
content/subagents/orchestrated-reviewer.md
111 changes: 111 additions & 0 deletions packages/agents/content/_partials/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
# Partials

Partials are reusable Markdown fragments shared across skills, subagents, and platform guidance. The install pipeline expands include directives at install time, before frontmatter merging, marker injection, and link rewriting. Partials never reach installed output as standalone files; their content is inlined into each consumer.

This README is the canonical reference for the partial system. The expander is implemented in `packages/agents/src/lib/directive-expander.ts`.

## Directive grammar

Three include shapes are recognized. Each must occupy a full line, with optional leading and trailing whitespace. Inline directives inside prose or code spans are not expanded.

| Shape | Syntax | Use |
| ------------- | ------------------------------------------------ | --------------------------------------------------------------------------------- |
| Self-close | `<!-- include: path / -->` | Inline a partial with no slot content (or use the partial's empty-slot defaults). |
| Open + close | `<!-- include: path -->` ... `<!-- /include -->` | Inline a partial and pass slot content into its `<!-- children -->` placeholder. |
| Children slot | `<!-- children -->` | Inside a partial: marks where the caller's slot content is substituted. |

Self-close is matched before open so that a path with a trailing slash is read correctly as a self-close, not as an open directive whose path ends with a slash.

The `<!-- children -->` placeholder is a partial-side directive. It appears at most once per partial. If a partial has no `<!-- children -->` and the caller provides slot content, the expander throws `slot-without-children`. If a partial has `<!-- children -->` and the caller provides no slot content (bare self-close, or empty open/close pair), the placeholder line is removed and surrounding lines join verbatim.

## Path resolution

Include paths are resolved relative to the directive-bearing file's directory in the source tree. The resolved target must remain inside `packages/agents/content/` (lexical containment is checked, not symlink resolution). Out-of-tree references throw `out-of-tree`.

A partial's own includes are resolved relative to that partial's directory, not the caller's. This means a deeply nested partial can include a sibling partial without knowing where its caller lives.

## Partial locations

Partials are stored in `_partials/` directories. The directory is recognized at any depth and is excluded from the install copy:

- `content/_partials/` β€” cross-cutting partials shared across skills, subagents, and platform guidance.
- `content/subagents/_partials/` β€” partials shared across subagents.
- `content/skills/_partials/` β€” partials shared across skills.
- `content/skills/{name}/_partials/` β€” partials internal to a single skill.

The `_partials` directory itself never appears in installed output.

## Install pipeline

For each `.md` source file the install pipeline performs, in order:

1. **Expand includes.** `expandIncludes(srcPath, contentDir)` resolves all directive shapes recursively and substitutes slot content.
2. **Merge frontmatter** (subagents only). Platform-specific frontmatter overrides from `_data/{platform}.yml` are merged into the source's frontmatter.
3. **Inject the provenance marker.** A `GENERATED FILE` comment is added at the top of the output, with a `Source:` link to the original file.
4. **Rewrite paths** (skills only, post-write). Bare-relative Markdown links are rewritten to absolute platform paths.
5. **Write the destination file.**

Expansion runs before the dry-run gate, so missing partials, cycles, and out-of-tree references surface even when no files would be written.

## Verbatim slot substitution

When a partial contains `<!-- children -->`, expansion removes that line and inserts the caller's slot lines verbatim β€” no leading-trim, no trailing-trim, no blank-line collapsing. Partial authors control the spacing on their side; caller authors control the spacing on theirs.

A consequence: avoid placing blank lines on both sides of a `<!-- children -->` boundary. If the partial has a blank line above `<!-- children -->` and the caller's slot content begins with a blank line, the result is two consecutive blank lines.

## Common patterns

### Bare self-close β€” no slot

Use when the partial has no `<!-- children -->` placeholder, or when the caller wants the partial's empty-slot rendering:

```
<!-- include: _partials/shared-prose.md / -->
```

### Open/close with slot content

Use when the partial has `<!-- children -->` and the caller wants to fill it:

```
<!-- include: _partials/with-slot.md -->
Caller-provided slot lines.
Multiple lines are allowed.
<!-- /include -->
```

### Empty open/close pair

Functionally equivalent to bare self-close. Useful when the surrounding text reads more naturally as an explicit empty pair:

```
<!-- include: _partials/with-slot.md -->
<!-- /include -->
```

## Forward-compatibility constraints

The grammar reserves additional tokens for future use. Partial authors must not emit them in source content:

- `<!-- slot: name -->`, `<!-- slot: name / -->`, `<!-- /slot -->` β€” reserved for future named-slot support.
- `<!-- children -->` β€” the canonical default-slot placeholder. Use exactly this token; do not invent variants.

The expander rejects unrecognized parameters following `include:` with an `unrecognized-parameter` error. This protects the grammar from typos quietly slipping past.

## Frontmatter constraint

Partials must not contain YAML frontmatter (a leading `---` block). Subagent install merges frontmatter from a platform overlay file with frontmatter in the source `.md`; if a partial carried its own `---` block, the merge would conflict. The expander does not enforce this constraint at runtime β€” partial authors must avoid frontmatter explicitly.

## Errors

The expander surfaces structured errors for the following conditions. Each error includes the file path and line number of the offending directive (or, for slot-without-children, the caller's open-directive line).

| Reason | Cause |
| ------------------------ | ---------------------------------------------------------------------------------------- |
| `cycle` | A partial transitively includes itself. |
| `not-found` | The resolved path does not exist on disk. |
| `orphan-close` | A close directive has no matching open. |
| `out-of-tree` | The resolved path escapes `contentDir`. |
| `slot-without-children` | The caller provided slot content but the partial has no `<!-- children -->` placeholder. |
| `unclosed-open` | An open directive was never followed by a matching close. |
| `unrecognized-parameter` | A directive uses `include:` syntax but does not match any recognized shape. |
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
Read AGENTS.md (if it exists) in the working directory and treat it as fully equivalent to CLAUDE.md.

<!-- include: ../../shared/AGENTS.md -->
<!-- include: ../../shared/AGENTS.md / -->
4 changes: 2 additions & 2 deletions packages/agents/content/guidance/_platforms/rovodev/AGENTS.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
<!-- include: ../../shared/AGENTS.md -->
<!-- include: ./codeassembly-guidance.md -->
<!-- include: ../../shared/AGENTS.md / -->
<!-- include: ./codeassembly-guidance.md / -->
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<HARD-GATE>
For multi-task plans (implementation mode) and for every review-response round, your FIRST implementation tool use MUST be a `Write` of the change-summary scaffold to the orchestrator-supplied artifact path. This guarantees a durable, structurally-complete artifact exists even if your dispatch is interrupted by `max_turns` exhaustion or any other failure.

Single-task implementation plans are exempt β€” write the artifact once at the end.
</HARD-GATE>
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
### Implementation-mode scaffold

After reading the plan, extract each task's title and write exactly this structure:

```markdown
# Change summary β€” ticket #{N}

## Status

In progress β€” task 0 of {K}

## Per-task summary

### Task 0: {title} β€” pending

### Task 1: {title} β€” pending

...

## Files changed

(pending)

## Quality gates

(pending)

## Deferred items

(pending)
```

After completing each plan task, overwrite the file:

- Update that task's section heading to `β€” completed|skipped|deferred`, followed by files changed, outcome, and notes.
- Bump `## Status` to `In progress β€” task {N+1} of {K}`.

Before your final structured return block, finalize:

- `## Files changed` β€” aggregate list of all modified files.
- `## Quality gates` β€” typecheck, lint, tests results.
- `## Deferred items` β€” any intentional omissions or deviations from the plan.
- `## Status` β€” `completed`.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
The change-summary is the orchestrator's primary state-transfer channel. Review cycles, holistic review, and re-dispatched coders all read it. A partial summary listing which tasks are complete vs. pending is strictly more useful than a missing summary β€” interruption must never strand the orchestrator without one. Writing the summary file N times during a dispatch is cheap; the artifact store is not performance-sensitive.
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
### Review-response-mode scaffold

After reading the review, enumerate all finding IDs and write exactly this structure:

```markdown
# Change summary β€” round {R}

## Status

In progress β€” finding 0 of {F}

## Findings addressed

### F1: {title} β€” pending

### F2: {title} β€” pending

### W1: {title} β€” pending

...

## Quality gates

(pending)
```

After addressing each finding, overwrite the file:

- Replace that finding's `β€” pending` marker with the filled subsection:
- `**Status:** FIXED | NOT_FIXED | ALREADY_RESOLVED`
- `**Action:** {what was done, or why no change was made}`
- Bump `## Status` to `In progress β€” finding {N+1} of {F}`.

Before your final structured return block, finalize `## Quality gates` and set `## Status` to `completed`.
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
### Finalize (reserved last 3 turns)

Replace `### Criticality: (pending)` with the aggregate enum value (`none|low|medium|high`) and replace `### Summary`'s `(pending)` placeholder with the 1-2 sentence overall assessment.
<!-- children -->
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<HARD-GATE>
After reading project guidelines and obtaining the diff (typically 2-3 turns), your NEXT tool use MUST be a `Write` of the review scaffold to the orchestrator-supplied artifact path. Not a `Read`, not a `Grep`, not a `Bash` to inspect files β€” a `Write`. This guarantees a durable artifact exists at the canonical path even if your dispatch is interrupted by `max_turns` exhaustion or any other failure.
<!-- children -->
</HARD-GATE>
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
### Interim writes (after each finding)

After each finding crystallizes, overwrite the artifact with the current findings appended under `### Findings`. `### Criticality:` stays `(pending)` and `### Summary` stays `(pending)` until finalize. Example interim form with one finding present:

```markdown
### Criticality: (pending)

### Summary

(pending)

### Findings

<!-- children -->
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
You have `Write` but not `Edit`. Each update is a full overwrite of the artifact file with the growing findings list.

### Scaffold (first write)

Write exactly this structure:

```markdown
### Criticality: (pending)

### Summary

(pending)

### Findings

(none yet)
```

The literal string `(pending)` on the `### Criticality:` line is the interruption sentinel. The orchestrator distinguishes a mid-flight artifact from a finalized one by checking whether `### Criticality:` parses as a known enum value. Do not invent other placeholder strings.
47 changes: 8 additions & 39 deletions packages/agents/content/subagents/aspect-code-reviewer.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,60 +41,29 @@ You will receive:

## Incremental review writes

<HARD-GATE>
After reading project guidelines and obtaining the diff (typically 2-3 turns), your NEXT tool use MUST be a `Write` of the review scaffold to the orchestrator-supplied artifact path. Not a `Read`, not a `Grep`, not a `Bash` to inspect files β€” a `Write`. This guarantees a durable artifact exists at the canonical path even if your dispatch is interrupted by `max_turns` exhaustion or any other failure.
<!-- include: _partials/review-writes-hard-gate.md -->

The HARD-GATE applies on every dispatch, including re-reviews. Re-review starts from a fresh empty scaffold.
</HARD-GATE>
<!-- /include -->

The review file is the orchestrator's primary state-transfer channel. A partial review listing findings discovered so far is strictly more useful than no review β€” interruption must never strand the orchestrator without one. Writing the file N times during a dispatch is cheap; the artifact store is not performance-sensitive.

You have `Write` but not `Edit`. Each update is a full overwrite of the artifact file with the growing findings list.

### Scaffold (first write)

Write exactly this structure:

```markdown
### Criticality: (pending)

### Summary

(pending)

### Findings

(none yet)
```

The literal string `(pending)` on the `### Criticality:` line is the interruption sentinel. The orchestrator distinguishes a mid-flight artifact from a finalized one by checking whether `### Criticality:` parses as a known enum value. Do not invent other placeholder strings.

### Interim writes (after each finding)

After each finding crystallizes, overwrite the artifact with the current findings appended under `### Findings`. `### Criticality:` stays `(pending)` and `### Summary` stays `(pending)` until finalize. Example interim form with one finding present:

```markdown
### Criticality: (pending)

### Summary

(pending)

### Findings
<!-- include: _partials/review-writes-scaffold.md / -->

<!-- include: _partials/review-writes-interim.md -->
#### F1: Null dereference in login handler

- **Severity:** critical
- **Location:** `src/auth/login.ts:42`
- **Description:** {what is wrong}
- **Recommendation:** {what to do}
```

### Finalize (reserved last 3 turns)
<!-- /include -->

Replace `### Criticality: (pending)` with the aggregate enum value (`none|low|medium|high`) and replace `### Summary`'s `(pending)` placeholder with the 1-2 sentence overall assessment. Then emit your structured return block.
<!-- include: _partials/review-writes-finalize.md -->
Then emit your structured return block.

If the review concluded with no findings, the finalized form omits the `### Findings` block entirely β€” see the "If no findings" example in [Output format](#output-format).
<!-- /include -->

## Scope

Expand Down
Loading
Loading