mirror of
https://github.com/github/awesome-copilot.git
synced 2026-08-14 21:26:54 +00:00
chore: publish from main
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
---
|
||||
name: bug-receipt
|
||||
description: 'Close bugs and incidents with an auditable BUG RECEIPT and VERIFIED, PARTIAL, or BLOCKED status. Use for defect repair, regression proof, production incidents, and issue closeout.'
|
||||
description: 'Close defects and incidents with a BUG RECEIPT and VERIFIED, PARTIAL, or BLOCKED status after diagnosis, repair, or recovery.'
|
||||
metadata:
|
||||
version: "1.4.1"
|
||||
---
|
||||
|
||||
# Bug Receipt
|
||||
@@ -27,6 +29,8 @@ Use `not run`, `unproven`, or `none` explicitly. Never omit a row to make the re
|
||||
|
||||
Before editing, record the observed problem, intended behavior, strongest direct check, and evidence source: `executed now`, `supplied`, or `mixed`. Never imply that supplied evidence was executed in the current run.
|
||||
|
||||
Keep evidence privacy-minimal. Redact credentials, tokens, cookies, personal data, private URLs, and sensitive payloads; preserve only the identifiers and excerpts needed to reproduce or correlate the failure.
|
||||
|
||||
Reproduce the failure with the narrowest safe check when possible. If reproduction is unavailable, preserve the evidence obtained and cap the result at `PARTIAL` or `BLOCKED`.
|
||||
|
||||
## Trace and repair
|
||||
@@ -66,7 +70,7 @@ Use these decisive boundaries:
|
||||
|
||||
For `PARTIAL` or `BLOCKED`, name the single minimal experiment or correlated evidence package that closes the decisive gap. Never invent a command, observation, count, location, or result.
|
||||
|
||||
For a machine-readable receipt or CI integration, read [references/receipt-contract.md](references/receipt-contract.md) and conform to its JSON fields and status invariants.
|
||||
For a machine-readable receipt or CI integration, read [references/receipt-contract.md](references/receipt-contract.md) and conform to its JSON fields, evidence-source marker, compatibility rule, and status invariants.
|
||||
|
||||
When a JSON artifact is requested, start from [assets/receipt.template.json](assets/receipt.template.json), write it to a task-owned path, and validate it with `node scripts/validate-receipt.mjs <receipt.json>` from this skill directory. Do not commit the generated receipt unless the user requests it.
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
{
|
||||
"version": 1,
|
||||
"version": 2,
|
||||
"status": "partial",
|
||||
"evidenceSource": "supplied",
|
||||
"problem": "Describe the observed defect and intended behavior.",
|
||||
"baseline": {
|
||||
"command": "Record the exact reproduction command or interaction.",
|
||||
|
||||
@@ -4,8 +4,9 @@ Use JSON only when the user, CI, or another tool needs a structured artifact. Ke
|
||||
|
||||
## Required fields
|
||||
|
||||
- `version`: integer `1`.
|
||||
- `version`: integer `2` for new receipts. Version `1` remains accepted for compatibility.
|
||||
- `status`: `verified`, `partial`, or `blocked`.
|
||||
- `evidenceSource`: `executed-now`, `supplied`, or `mixed` (required in version `2`).
|
||||
- `problem`: concise defect and intended behavior.
|
||||
- `baseline`: object with `command`, `result`, and `evidence`.
|
||||
- `rootCause`: object with `summary` and at least one evidence item for `verified`.
|
||||
@@ -37,4 +38,4 @@ For `blocked`:
|
||||
- Require at least one gap naming the external blocking condition.
|
||||
- Leave unperformed work empty or mark it `not-run`; do not speculate about the result.
|
||||
|
||||
Validate against [receipt.schema.json](receipt.schema.json), run `node scripts/validate-receipt.mjs <file>` from the skill directory, or pipe JSON to `node scripts/validate-receipt.mjs - --json`.
|
||||
Validate against [receipt.schema.json](receipt.schema.json), run `node scripts/validate-receipt.mjs <file>` from the skill directory, pipe JSON to `node scripts/validate-receipt.mjs - --json`, or use `bug-receipt check <file>` when the package CLI is installed.
|
||||
|
||||
@@ -7,8 +7,9 @@
|
||||
"additionalProperties": false,
|
||||
"required": ["version", "status", "problem", "baseline", "rootCause", "changes", "verification", "gaps"],
|
||||
"properties": {
|
||||
"version": { "const": 1 },
|
||||
"version": { "enum": [1, 2] },
|
||||
"status": { "enum": ["verified", "partial", "blocked"] },
|
||||
"evidenceSource": { "enum": ["executed-now", "supplied", "mixed"] },
|
||||
"problem": { "$ref": "#/$defs/nonEmptyString" },
|
||||
"baseline": {
|
||||
"type": "object",
|
||||
@@ -71,6 +72,13 @@
|
||||
"nonEmptyString": { "type": "string", "minLength": 1, "pattern": "\\S" }
|
||||
},
|
||||
"allOf": [
|
||||
{
|
||||
"if": { "properties": { "version": { "const": 2 } }, "required": ["version"] },
|
||||
"then": {
|
||||
"properties": { "evidenceSource": { "enum": ["executed-now", "supplied", "mixed"] } },
|
||||
"required": ["evidenceSource"]
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": { "properties": { "status": { "const": "verified" } }, "required": ["status"] },
|
||||
"then": {
|
||||
|
||||
@@ -3,6 +3,7 @@ import { resolve } from 'node:path'
|
||||
import { pathToFileURL } from 'node:url'
|
||||
|
||||
const statuses = new Set(['verified', 'partial', 'blocked'])
|
||||
const evidenceSources = new Set(['executed-now', 'supplied', 'mixed'])
|
||||
const baselineResults = new Set(['failed', 'observed', 'not-run'])
|
||||
const verificationResults = new Set(['passed', 'failed', 'not-run'])
|
||||
|
||||
@@ -10,8 +11,9 @@ const isObject = (value) => value !== null && typeof value === 'object' && !Arra
|
||||
const nonEmpty = (value) => typeof value === 'string' && value.trim().length > 0
|
||||
|
||||
export const sampleReceipt = {
|
||||
version: 1,
|
||||
version: 2,
|
||||
status: 'verified',
|
||||
evidenceSource: 'executed-now',
|
||||
problem: 'A 10% checkout discount returns 100 instead of 90 after currency rounding.',
|
||||
baseline: {
|
||||
command: 'npm test -- discount.test.ts',
|
||||
@@ -41,10 +43,12 @@ export function validateReceipt(receipt) {
|
||||
}
|
||||
|
||||
if (!isObject(receipt)) return { valid: false, issues: [{ path: '$', message: 'Receipt must be a JSON object.' }] }
|
||||
rejectUnknown(receipt, new Set(['version', 'status', 'problem', 'baseline', 'rootCause', 'changes', 'verification', 'gaps']), '')
|
||||
rejectUnknown(receipt, new Set(['version', 'status', 'evidenceSource', 'problem', 'baseline', 'rootCause', 'changes', 'verification', 'gaps']), '')
|
||||
|
||||
if (receipt.version !== 1) add('version', 'Must equal 1.')
|
||||
if (receipt.version !== 1 && receipt.version !== 2) add('version', 'Must equal 1 or 2.')
|
||||
if (!statuses.has(receipt.status)) add('status', 'Must be verified, partial, or blocked.')
|
||||
if (receipt.evidenceSource !== undefined && !evidenceSources.has(receipt.evidenceSource)) add('evidenceSource', 'Must be executed-now, supplied, or mixed.')
|
||||
if (receipt.version === 2 && !evidenceSources.has(receipt.evidenceSource)) add('evidenceSource', 'Version 2 requires an evidence source.')
|
||||
if (!nonEmpty(receipt.problem)) add('problem', 'Must be a non-empty string.')
|
||||
|
||||
if (!isObject(receipt.baseline)) {
|
||||
@@ -103,7 +107,7 @@ export function validateReceipt(receipt) {
|
||||
if (!Array.isArray(receipt.rootCause?.evidence) || receipt.rootCause.evidence.length === 0) add('rootCause.evidence', 'Verified requires concrete root-cause evidence.')
|
||||
if (!Array.isArray(receipt.changes) || receipt.changes.length === 0) add('changes', 'Verified requires at least one changed file or artifact.')
|
||||
if (!Array.isArray(receipt.verification) || receipt.verification.length === 0) add('verification', 'Verified requires at least one verification check.')
|
||||
if (receipt.verification?.some((entry) => entry?.result !== 'passed')) add('verification', 'Every verification check must pass for verified status.')
|
||||
if (Array.isArray(receipt.verification) && receipt.verification.some((entry) => entry?.result !== 'passed')) add('verification', 'Every verification check must pass for verified status.')
|
||||
if (Array.isArray(receipt.gaps) && receipt.gaps.length > 0) add('gaps', 'Verified status cannot contain proof gaps.')
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user