Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
112 changes: 112 additions & 0 deletions .agents/skills/autopilot-comment/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
---
name: autopilot-comment
activation_card: on
description: >-
Use this skill to post or patch ONE GitHub comment for a microsoft/apm
autopilot run. It owns public vs debug body assembly and the AI
disclaimer footer. Never labels, assigns, requests reviewers, or
merges. Autopilot skills that write comments must load this skill
and must not call gh comment APIs themselves.
---

# autopilot-comment -- Sole GitHub comment writer

Any autopilot skill that would write a GitHub comment loads this
skill in the same session and stops if the card is missing. Do not
spawn a nested session. Do not comment from the caller.

## Activation card

`activation_card: on`. Before any GitHub comment write, emit this
Enter card with every field filled. Missing field -> stop.

```text
skill: autopilot-comment
skill_path: <resolved directory of this SKILL.md>
mode: run
subject: microsoft/apm#<number>
path: comment
intent: post one GitHub comment | patch one GitHub comment
origin: unattended | actor-session
write: on | off
debug: off | on
repo: microsoft/apm
target_kind: issue | pull
target: <positive integer>
source_skill: <canonical autopilot skill name>
comment_id: none | <positive integer>
invocation: agentic-workflow | actor-session
receipt: <HTML comment watermark line>
public_body: <author-facing prose, no JSON, no footer>
debug_body: <full internal template without JSON fence, or none>
```

Rules:

- `write` defaults to `on` when the caller omitted it.
- `write: off` returns the assembled body only. Do not post or
patch.
- `write: on` posts or patches exactly one comment. Never labels,
assigns, requests reviewers, or merges.
- `debug` defaults to `off` when omitted or unknown. Omitted
`debug` is not a missing-field stop.
- `debug: off` -> HTML `receipt` plus `public_body`. Do not post
internal headings from `debug_body`.
- `debug: on` -> first line `[i] Skill debug is on.` then `receipt`
plus `debug_body` (or `public_body` if `debug_body` is `none`).
- `comment_id: none` with intent `post`. A numeric `comment_id`
with intent `patch`. Mismatch -> stop.
- `source_skill` is the caller (for example
`autopilot-issue-triage-worker`). Never `autopilot-comment`.
- `origin` fail-closed unknown -> `unattended`.
- Strip any JSON fence from bodies before assembly. Never post
JSON on GitHub.

After the write (or dry-run), emit this Exit receipt:

```text
skill: autopilot-comment
subject: microsoft/apm#<number>
path: comment
write: on | off
debug: off | on
posted: yes | no
patched: yes | no
comment_id: <id or none>
source_skill: <canonical autopilot skill name>
approved: n/a
```

## Assemble

1. Drop JSON fences and `triage-recommendation` blocks.
2. Build the body from `debug` as above. ASCII only.
3. Append this exact footer, substituting `source_skill`:

```text
---

Generated by <source_skill>. This comment is AI-generated and may contain errors.
```

4. If the footer is already the last lines, do not duplicate it.

## Write

Actor-session / Copilot App / Cloud / Remote:

- issue + post: `gh issue comment <target> --body-file ...`
- pull + post: `gh pr comment <target> --body-file ...`
- patch: `gh api -X PATCH /repos/microsoft/apm/issues/comments/<comment_id>`

Agentic Workflow: `safe-outputs.add-comment` for post. Patch is
not available; stop if intent is `patch`.

One comment per activation. No progress comments.

## Hard nos

- Do not assign, request reviewers, merge, or edit labels.
- Do not implement.
- Do not compose schedulers or other workers.
- ASCII only.
10 changes: 10 additions & 0 deletions .agents/skills/autopilot-comment/apm.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
name: autopilot-comment
version: 0.1.0
description: Sole GitHub comment writer for microsoft/apm autopilot skills. Assembles public vs debug body and appends the AI disclaimer.
author: Microsoft
license: MIT
type: skill

dependencies:
apm: []
mcp: []
6 changes: 5 additions & 1 deletion .agents/skills/autopilot-issue-triage-scheduler/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,11 @@ selected list; when a slot returns, fill it with the next item.
else run the worker in this thread for that one issue, then
the next. When a slot returns, dispatch the next queued
issue. Do not stop because the pool was full. Each slot reads
the complete comment history before advising.
the complete comment history before advising. Pass `debug: off`
unless this run's caller set `debug: on`. Pass
`comment_via: autopilot-comment`. Worker kickoff must load
`autopilot-comment` before any GitHub comment. Workers must
not call `gh issue comment`.
4. Optionally present ONE consolidated triage digest. Wait if the
caller asked for a checkpoint. Never treat silence as accept.
5. Print a final report from the table.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ is empty.
1. Prefer a new session (Copilot App / Cloud / Remote) named
`Issue triage #<issue-number>` whose kickoff runs
`autopilot-issue-triage-worker` on exactly one issue.
Kickoff must also load `autopilot-comment` (`comment_via:
autopilot-comment`, `debug: off` unless the caller set on).
The worker must not call `gh issue comment`.
2. Else spawn a sub-agent (`task`) with the worker skill.
3. Else run the worker sequentially in this session.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,9 @@ def is_bot_author(author: str, author_type: str) -> bool:
def skip_reason(record: dict[str, Any], mode: str) -> str | None:
"""Return a skip token, or None when state/body filters pass.

Bot-authored issues skip. Bot-authored PRs stay eligible so they
can be triaged, accepted, reviewed, and merged.

Completed-advice markers stay eligible; `triage_state.plan_batch` owns
that sweep skip plus the per-author quota.
"""
Expand All @@ -128,7 +131,9 @@ def skip_reason(record: dict[str, Any], mode: str) -> str | None:
return "merged"
if record.get("locked"):
return "locked"
if is_bot_author(str(record["author"]), str(record.get("author_type", "User"))):
if record.get("kind") != "pr" and is_bot_author(
str(record["author"]), str(record.get("author_type", "User"))
):
return "bot-authored"
body = record.get("body")
if not isinstance(body, str) or is_empty_body(body):
Expand Down
84 changes: 57 additions & 27 deletions .agents/skills/autopilot-issue-triage-worker/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ intent: advise one already-selected issue
origin: unattended | actor-session
write: on | off
json: off | on
debug: off | on
repo: microsoft/apm
issue: <positive integer>
invocation: agentic-workflow | actor-session
Expand All @@ -58,13 +59,24 @@ Rules:
- `write` defaults to `on` when the caller omitted it.
- `write: off` returns the filled template only. Do not comment,
add labels, or remove labels.
- `write: on` posts the one advisory comment and processing /
classification labels. Never human decision labels. Never assign.
- `write: on` posts one GitHub comment via
`autopilot-comment` and processing / classification labels.
Never human decision labels. Never assign. Do not call
`gh issue comment` yourself.
- `json` defaults to `off` when omitted or unknown. Omitted `json`
is not a missing-field stop.
- `json: off` -> no `triage-recommendation` JSON receipt.
- `json: on` -> fill that JSON only as an internal payload
(session file or parent Exit). Never post it on GitHub.
- `debug` defaults to `off` when omitted or unknown. Omitted `debug`
is not a missing-field stop.
- `debug: off` -> pass `public_body` as the Suggested issue
comment (unwrap the markdown fence) to `autopilot-comment`.
Do not pass recommendation, classification, brief, next
action, or persona details as `public_body`.
- `debug: on` -> pass `debug_body` as the filled template
without the JSON fence. `autopilot-comment` prefixes
`[i] Skill debug is on.`
- `origin` fail-closed unknown -> `unattended`.
- One issue. Do not nest a scheduler path.

Expand All @@ -76,17 +88,19 @@ subject: microsoft/apm#<issue-number>
path: triage
write: on | off
json: off | on
debug: off | on
posted: yes | no
labels_applied: <comma list or none>
approved: n/a
```

The panel is fixed at **2 mandatory specialist lenses + up to 3
conditional lenses + 1 always-active arbiter = 6 persona sections in
one triage comment**. You play each
the filled template**. You play each
lens in turn from inside a single agent loop (progressive-disclosure
skill model -- no sub-agent dispatch). Routing chooses *which* lenses
execute; it never changes which headings appear in the final comment.
execute; it never changes which headings appear in the filled
template. The public GitHub body still follows `debug`.

This skill mirrors the `autopilot-pr-review-worker` orchestration shape on
purpose. Same single-comment discipline, same completeness gate, same
Expand Down Expand Up @@ -374,26 +388,36 @@ write/receipt step.
7. Now (and only now) load `assets/triage-template.md` and fill it
in with the collected findings, recommendation, classification,
proposed brief, and suggested comment body.
8. Verify the rendered comment contains every top-level heading from
the template, all six persona `<details>` sections, and the closing
`triage-recommendation` JSON block. If any element is missing, re-render
from the template instead of posting a hand-composed substitute.
8. Verify the INTERNAL fill contains every top-level heading from
the template, all six persona `<details>` sections, and (only
when `json: on`) the closing `triage-recommendation` JSON.
If any required element is missing, re-render from the
template. That filled template is not the GitHub body when
`debug: off`.
9. If `write: on`, apply the advisory writes yourself. The scheduler
never comments or labels. A worker summoned without a scheduler
still writes when `write` is on. No-op when target plus
conversation watermark already match. Post exactly one template
comment (`gh issue comment` in actor-session / Copilot App /
Cloud / Remote; Agentic Workflow `safe-outputs.add-comment`).
Add `triage/recommended` plus useful classification from the
contract allowlist (`gh issue edit --add-label` or
`safe-outputs.add-labels`). Never write human decision labels.
Remove only `triage/requested` after successful advice. If
`write: off`, return the filled template only. Also return the
`triage-recommendation` JSON to the caller. Emit the Exit
receipt (`posted: yes` only when a comment was written). Never
authorize implementation. This is the ONLY triage-comment
emission for the entire panel run -- no per-persona comments,
no progress comments.
conversation watermark already match. Probe
`$REPO_ROOT/.agents/skills/autopilot-comment/SKILL.md` (or the
sibling package). Missing -> stop. Do not post. Post exactly
one comment by activating `autopilot-comment` (`source_skill:
autopilot-issue-triage-worker`). Do not call `gh issue comment`
or `safe-outputs.add-comment` yourself. Missing footer after
that write is a failed post -- patch via `autopilot-comment`
(`intent: patch`) rather than leaving the comment bare.
`debug: off`: Suggested issue comment body only as
`public_body`. `debug: on`: filled template as `debug_body`.
Add `triage/recommended` plus useful
classification from the contract allowlist
(`gh issue edit --add-label` or `safe-outputs.add-labels`).
Never write human decision labels. Remove only
`triage/requested` after successful advice. If `write: off`,
return the filled template only. Also return the
`triage-recommendation` JSON to the caller when `json: on`.
Emit the Exit receipt (`posted: yes` only when a comment was
written). Never authorize implementation. This is the ONLY
triage-comment emission for the entire panel run -- no
per-persona comments, no progress comments.

### Persona pass procedure

Expand All @@ -419,15 +443,21 @@ This contract is non-negotiable -- it is the difference between a
triage that lands as one cohesive comment and one that fragments into
per-persona noise.

- Produce **exactly one** comment per triage run.
- Use `assets/triage-template.md` as the comment body. Keep its
- Produce **exactly one** GitHub comment per triage run.
- Always fill `assets/triage-template.md` internally. Keep its
section headings exactly as written. Adapt the body of each
section to the issue. Do not invent new top-level sections or drop
existing ones.
- The GitHub issue comment is human prose only: HTML receipt,
headings, classification, brief, next action, suggested reply,
and persona details. Do not post JSON, machine fences, or
`comment_markdown` dumps on the issue.
- Load `autopilot-comment` before any GitHub comment write.
Fill its card (`source_skill: autopilot-issue-triage-worker`,
`debug` copied from this card, `receipt` = the HTML watermark
line). Missing skill or missing card -> stop. Never post
with `gh issue comment`.
- `debug: off` `public_body`: Suggested issue comment prose
(no wrapping fence, no other headings).
- `debug: on` `debug_body`: the filled template without JSON.
- Do not post JSON, machine fences, or `comment_markdown` dumps
on the issue. `autopilot-comment` appends the AI disclaimer.
- Emit the template's `triage-recommendation` JSON only when
`json: on`. Keep `schema_version: 2` and `advisory_only: true`.
Never attach that JSON to the GitHub comment. Consumers must
Expand Down
3 changes: 2 additions & 1 deletion .agents/skills/autopilot-issue-triage-worker/apm.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,6 @@ type: skill
# against the consumer repo's installed .apm/agents/** or
# .github/agents/** -- identical to the autopilot-pr-review-worker precedent.
dependencies:
apm: []
apm:
- ../autopilot-comment
mcp: []
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,13 @@ conditional lenses say "Not activated -- <reason>". The caller is the
sole writer; direct invocation returns this without posting.
Fill the v2 JSON block only when the activation card has `json: on`.
Default is `json: off`: omit the JSON receipt. Never post that JSON
(or any machine fence) on the GitHub issue. The public comment is
prose plus the HTML receipt. The JSON is advisory data, not a
label/milestone write instruction.
(or any machine fence) on the GitHub issue. Default `debug: off`
posts only the HTML receipt plus the Suggested issue comment body.
`debug: on` posts this filled template prefixed with
`[i] Skill debug is on.` Both paths go through
`autopilot-comment`, which appends the AI disclaimer.
Never post with `gh issue comment`. The JSON is advisory
data, not a label/milestone write instruction.
-->

<!-- apm-triage-advisory:v2 target=issue#<N> watermark=<latest-comment-id-or-updated-at> -->
Expand Down
Loading
Loading