Files
claude-plugin-inference-arb…/references/issue-template.md
T
2026-07-29 17:50:20 +03:00

165 lines
6.5 KiB
Markdown

# issue-template.md — the issue body contract
The shape of every issue this plugin causes to be filed on a **target plugin's
own repo** (output path A, `design/plan.md` §10, FR-6). Loaded at runtime by
`bin/filing-plan`, which renders it; it is kept here rather than in the script
body so that a change to what an issue says is a reviewable diff.
Format is the same as `signals-catalog.md`: each `## <section>` heading below is
followed by **exactly one fenced block**, and the fenced block is the only part
the parser reads. Prose outside the fences is for humans.
Placeholders are `{{name}}`. Every placeholder in a template must be supplied —
`filing-plan` fails loudly on an unknown or missing one rather than rendering a
half-filled issue.
## Who decides what
`filing-plan` renders the **body**, because the body is the contract: the marker,
the measurement, the rubric verdict, and the falsifiability triple are all
already-computed values and rendering them is a `pure-script` step.
It does **not** decide where the issue goes. Repo, final title, labels beyond
`token-offload`, and milestone are `anxious:issuer-agent`'s call, per its own
taxonomy. The `issue-title` section below is a *proposal* passed to `issuer`,
not an instruction.
## The marker is load-bearing
The first line of every body — and of every update comment — is
```text
<!-- ia-candidate: <candidate_id> -->
```
It is how a re-run recognizes its own prior work (FR-6.3). It renders invisible
in Gitea, is stable across runs because `candidate_id` is, and must never be
edited by hand on a filed issue. Removing it from an issue causes the next audit
to file a duplicate — which the spec names as the single most likely way for
this plugin to become hated.
## issue-title
A proposal. `issuer` may rewrite it.
```text
token-offload: {{headline}} ({{skill}})
```
## issue-body
`{{examples}}` renders as a markdown list, one input→output pair per line, with
the edge case marked. `{{determinism_tests}}` renders as `T1 ✓ T2 ✓ …`, using ✗
for a failed test. `{{evidence}}` always renders — it states whether the cost
claim is `measured`, `thin`, or `unmeasured`, so a reader never has to guess
whether the number is evidence or arithmetic.
```markdown
<!-- ia-candidate: {{candidate_id}} -->
**Measured cost.** {{measured_cost}}
**Evidence strength.** {{evidence}}
**Boundary position.** {{position}} — confidence {{boundary_confidence}}.
Determinism tests: {{determinism_tests}}
**Proposed signature.**
`{{signature}}`
**Examples.**
{{examples}}
**When a human would overrule this.** {{overrule_case}}
**Escalation path.** {{escalation_path}}
**What crosses the boundary.** {{digest_schema}}
---
This is a proposal from an audit, not an accepted design. It is deliberately
falsifiable: if the overrule case above is *common*, the cut belongs earlier in
the pipeline than proposed, and this issue should be reshaped rather than
implemented. Closing this as `wontfix` is a useful outcome and is tracked as a
calibration signal.
Audit: `{{audit_page}}` on the {{wiki_repo}} wiki. Rubric v{{rubric_version}}.
```
## update-comment
Posted instead of a new issue when the marker is already present on the repo
(FR-6.3). It carries the marker again so that the search finds this issue
whether the marker lives in the body or only in a comment.
```markdown
<!-- ia-candidate: {{candidate_id}} -->
**Re-measured {{run_date}}** — window {{window}}. Status: {{status}}.
{{measured_cost}}
Evidence strength: {{evidence}}
Boundary position {{position}}, confidence {{boundary_confidence}} (rubric
v{{rubric_version}}).
Audit: `{{audit_page}}` on the {{wiki_repo}} wiki.
```
## marker-search
How the pre-filing search is actually performed (FR-6.3). This is not
hand-waved: both queries below run against the **target** repo, through
`anxious:issuer-agent``cluster:gitea-agent`, and their merged results are
what `filing-plan plan --existing` consumes.
**Three steps, not one.** The obvious one-query design does not work, and the
reason was established empirically against the live Gitea (2026-07-29, probe
issue `kotkan/claude-plugin-inference-arbitrage#9`, since closed):
> **Neither `search_issues` nor `list_issues` returns the issue `body`.** Both
> return metadata only — number, title, state, labels, timestamps. A marker
> match therefore *cannot* be made from a search result. The body must be
> fetched per issue with `issue_read(method="get")`, and comments with
> `issue_read(method="get_comments")`.
Also established by the same probe: `search_issues` **does** full-text match on
body content, including text inside an HTML comment (a query for a string that
appeared only in the body, never in the title, returned the issue). So the
full-text path works — it just cannot be trusted to *confirm* a match, only to
suggest one.
```text
1. candidates list_issues(owner, repo, labels=["token-offload"], state="all")
search_issues(query="ia-candidate: <candidate_id>", owner, state="all")
-> union of issue numbers; bodies are NOT in these responses
2. fetch issue_read(method="get", index=N) -> body
issue_read(method="get_comments", index=N) -> comment bodies
(comments only needed when the body has no marker)
3. match filing-plan plan --existing <merged.json> -> local literal match
```
Step 1's label scan is the authoritative half: every issue this plugin files
carries `token-offload`, so it is a bounded, exact superset of the issues that
can carry a marker. The full-text query is the safety net for an issue whose
label a human removed. Step 3's match is a literal string comparison and is the
only thing that decides identity — the search engine never does.
If step 1 finds no `token-offload` label on the target repo, that is the
first-audit case: there are no prior issues, `issuer` creates the label with the
first filing, and the empty result is correct.
The merged shape handed to `--existing` is a JSON array of
`{number, state, title, body, comments: [...]}`. `filing-plan` matches
`<!--\s*ia-candidate:\s*<id>\s*-->` against the body **and each comment**, so an
issue keeps its identity even if a human rewrites the body entirely, as long as
one update comment survives — also verified against the live probe issue.
**`--existing` is mandatory, even when empty.** `filing-plan plan` refuses to
run without it rather than defaulting to "nothing exists", because that default
turns a failed search into a duplicate-filing spree — the exact outcome FR-6.3
exists to prevent.