diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..e9a7038 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,130 @@ +# AGENTS.md + +## Issue Discovery Standard + +When looking for new issues, do not rely only on casual code inspection. Prefer evidence-backed discovery methods and only file issues that are narrow, reproducible, and worth tracking. + +### Core rule + +A new issue should only be created if it is: +- verified on the current codebase state +- narrow in scope +- reproducible with a concrete command, test, request flow, or minimal example +- supported by actual observed behavior +- easy for another engineer to validate and pick up + +### Preferred issue-finding strategies + +Use these methods before proposing new issues: + +1. Run code paths, not just static scans +- Prefer executing small targeted checks over only reading code. +- Use focused commands, test nodes, or minimal scripts to validate behavior. + +2. Re-run stale or suspicious test suites +- Look for: + - `XPASS` + - `xfail` + - skipped tests that may now be stale + - stale or obsolete tests that may no longer match reality +- Unexpected passes and stale expected failures are strong sources of real issues. + +3. Compare public API surfaces +- Check package-level exports vs submodule exports. +- Look for duplicated helper names with different behavior. +- Validate that documented imports and actual imports behave consistently. + +4. Compare claims vs runnable behavior +- Check README/docs statements such as: + - "supported" + - "in progress" + - "planned" + - "coming soon" +- Verify whether the smallest runnable path actually matches the claim. + +5. Compare neighboring execution paths +- Look for behavior that differs across: + - runtime vs test client + - native backend vs fallback backend + - sync vs async + - middleware vs no middleware + - top-level import vs direct submodule import + +6. Use differential testing mindset +- When relevant, compare behavior to a reference implementation or expected contract. +- For framework-style repos, compare against the documented compatibility target. + +7. Use property-based or fuzz-style thinking +- Especially for: + - routers + - parsers + - protocol handlers + - validation layers + - path/header/query normalization +- Prefer generated edge cases where practical. + +8. Look for issue-worthy drift +- Documentation says one thing +- tests assume another +- runtime does a third +- public exports expose a fourth +- These mismatches often produce strong, narrow issues. + +### What counts as a strong issue + +A strong issue has: +- one concrete problem +- one reproducible path +- actual observed failure or mismatch +- clear expected behavior +- nearby passing controls or guards +- narrow, testable acceptance criteria +- explicit non-goals if scope could sprawl + +### What does not count as a strong issue + +Do not file issues that are: +- speculative +- based only on code inspection when runtime proof is possible +- broad umbrella complaints +- duplicate broad trackers without narrowing them +- warning-only cleanup unless there is a compelling reason +- multiple unrelated findings bundled together + +### Required issue evidence + +Before creating an issue, gather: + +1. Exact repro +- One concrete command, test node, API call, UI flow, or script. + +2. Observed result +- The actual failure output, incorrect result, mismatch, or unexpected behavior. + +3. Expected result +- What should happen instead. + +4. Nearby passing checks +- One or two closely related tests/commands/behaviors that still pass. + +5. Narrow acceptance criteria +- The repro passes. +- The expected behavior is present. +- Nearby guards remain green. + +6. Non-goals +- Clarify what the issue is not asking for. + +### Filing rule + +If the issue cannot be reduced to: +- one concrete problem +- one reproducible path +- one observed failure +- one expected behavior +- one or two nearby passing checks +- one narrow fix target + +do not file it yet. + +Gather better evidence first. diff --git a/src/tools.zig b/src/tools.zig index d935b83..b1482d5 100644 --- a/src/tools.zig +++ b/src/tools.zig @@ -95,7 +95,7 @@ fn validateIssueDraft(alloc: std.mem.Allocator, title: []const u8, body: []const if (std.mem.trim(u8, body, " \t\n\r").len == 0) { return std.fmt.allocPrint( alloc, - "issue body is required and must follow the CONTRIBUTING.md / AGENT.md issue template. Missing body.\n\nRequired template:\n{s}", + "issue body is required and must follow the CONTRIBUTING.md / AGENTS.md issue template. Missing body.\n\nRequired template:\n{s}", .{ISSUE_TEMPLATE}, ) catch null; } @@ -119,7 +119,7 @@ fn validateIssueDraft(alloc: std.mem.Allocator, title: []const u8, body: []const return std.fmt.allocPrint( alloc, - "issue body does not satisfy CONTRIBUTING.md / AGENT.md issue requirements. Missing required section(s): {s}.\n\nRequired template:\n{s}", + "issue body does not satisfy CONTRIBUTING.md / AGENTS.md issue requirements. Missing required section(s): {s}.\n\nRequired template:\n{s}", .{ joined.items, ISSUE_TEMPLATE }, ) catch null; } @@ -281,8 +281,8 @@ pub const tools_list = \\{"name":"get_project_state","description":"Return all open issues grouped by status label, all open branches, and all open PRs. Use this to understand current project state before picking up work.","inputSchema":{"type":"object","properties":{},"required":[]}}, \\{"name":"get_next_task","description":"Return the single highest-priority unblocked issue that has no open branch. Use this to decide what to work on next.","inputSchema":{"type":"object","properties":{},"required":[]}}, \\{"name":"prioritize_issues","description":"Apply priority labels (priority:p0–p3) to a set of issues based on their dependency order. Sinks (no dependents) get p0; independent issues get p2.","inputSchema":{"type":"object","properties":{"issue_numbers":{"type":"array","items":{"type":"integer"},"description":"Issue numbers to prioritize"}},"required":["issue_numbers"]}}, - \\{"name":"create_issue","description":"Create a single GitHub issue with title, body, labels, and optional milestone. Automatically applies status:backlog if no status label is provided. This tool enforces the issue requirements from CONTRIBUTING.md and AGENT.md: the body must include One-sentence problem, Exact repro, Observed result, Expected result, Nearby passing checks, Acceptance criteria, and Non-goals. If parent_issue is provided, create_issue only appends `Parent issue: #N` to the issue body for context; use link_issues for explicit dependency relationships.","inputSchema":{"type":"object","properties":{"title":{"type":"string"},"body":{"type":"string","description":"Required. Must follow the CONTRIBUTING.md / AGENT.md issue template with the required evidence sections."},"labels":{"type":"array","items":{"type":"string"}},"milestone":{"type":"string"},"parent_issue":{"type":"integer","description":"Optional parent issue number to append as `Parent issue: #N` in the issue body for context only. This does not create a durable GitHub subtask/dependency relationship; use link_issues for explicit links."}},"required":["title","body"]}}, - \\{"name":"create_issues_batch","description":"Create multiple GitHub issues in one call. Issues are fired concurrently in batches of 5 with a 200ms collection window. Use this after decompose_feature to create all issues at once. Each issue body must satisfy the same CONTRIBUTING.md / AGENT.md evidence template enforced by create_issue.","inputSchema":{"type":"object","properties":{"issues":{"type":"array","items":{"type":"object","properties":{"title":{"type":"string"},"body":{"type":"string","description":"Required. Must follow the CONTRIBUTING.md / AGENT.md issue template with the required evidence sections."},"labels":{"type":"array","items":{"type":"string"}},"milestone":{"type":"string"}},"required":["title","body"]}}},"required":["issues"]}}, + \\{"name":"create_issue","description":"Create a single GitHub issue with title, body, labels, and optional milestone. Automatically applies status:backlog if no status label is provided. This tool enforces the issue requirements from CONTRIBUTING.md and AGENTS.md: the body must include One-sentence problem, Exact repro, Observed result, Expected result, Nearby passing checks, Acceptance criteria, and Non-goals. If parent_issue is provided, create_issue only appends `Parent issue: #N` to the issue body for context; use link_issues for explicit dependency relationships.","inputSchema":{"type":"object","properties":{"title":{"type":"string"},"body":{"type":"string","description":"Required. Must follow the CONTRIBUTING.md / AGENTS.md issue template with the required evidence sections."},"labels":{"type":"array","items":{"type":"string"}},"milestone":{"type":"string"},"parent_issue":{"type":"integer","description":"Optional parent issue number to append as `Parent issue: #N` in the issue body for context only. This does not create a durable GitHub subtask/dependency relationship; use link_issues for explicit links."}},"required":["title","body"]}}, + \\{"name":"create_issues_batch","description":"Create multiple GitHub issues in one call. Issues are fired concurrently in batches of 5 with a 200ms collection window. Use this after decompose_feature to create all issues at once. Each issue body must satisfy the same CONTRIBUTING.md / AGENTS.md evidence template enforced by create_issue.","inputSchema":{"type":"object","properties":{"issues":{"type":"array","items":{"type":"object","properties":{"title":{"type":"string"},"body":{"type":"string","description":"Required. Must follow the CONTRIBUTING.md / AGENTS.md issue template with the required evidence sections."},"labels":{"type":"array","items":{"type":"string"}},"milestone":{"type":"string"}},"required":["title","body"]}}},"required":["issues"]}}, \\{"name":"update_issue","description":"Update an existing issue's title, body, or labels.","inputSchema":{"type":"object","properties":{"issue_number":{"type":"integer"},"title":{"type":"string"},"body":{"type":"string"},"add_labels":{"type":"array","items":{"type":"string"}},"remove_labels":{"type":"array","items":{"type":"string"}}},"required":["issue_number"]}}, \\{"name":"close_issues_batch","description":"Close multiple issues at once. Each issue is marked status:done. Use this instead of calling close_issue N times.","inputSchema":{"type":"object","properties":{"issue_numbers":{"type":"array","items":{"type":"integer"},"description":"Issue numbers to close"},"pr_number":{"type":"integer","description":"PR number that resolves all these issues (optional)"}},"required":["issue_numbers"]}}, \\{"name":"close_issue","description":"Close an issue and mark it status:done. Optionally reference the PR that resolved it.","inputSchema":{"type":"object","properties":{"issue_number":{"type":"integer"},"pr_number":{"type":"integer","description":"PR number that resolves this issue"}},"required":["issue_number"]}}, @@ -3122,9 +3122,9 @@ fn handleRunTask( } test "tools_list encodes evidence-backed issue filing guidance" { - try std.testing.expect(std.mem.indexOf(u8, tools_list, "This tool enforces the issue requirements from CONTRIBUTING.md and AGENT.md") != null); - try std.testing.expect(std.mem.indexOf(u8, tools_list, "Each issue body must satisfy the same CONTRIBUTING.md / AGENT.md evidence template enforced by create_issue") != null); - try std.testing.expect(std.mem.indexOf(u8, tools_list, "CONTRIBUTING.md and AGENT.md") != null); + try std.testing.expect(std.mem.indexOf(u8, tools_list, "This tool enforces the issue requirements from CONTRIBUTING.md and AGENTS.md") != null); + try std.testing.expect(std.mem.indexOf(u8, tools_list, "Each issue body must satisfy the same CONTRIBUTING.md / AGENTS.md evidence template enforced by create_issue") != null); + try std.testing.expect(std.mem.indexOf(u8, tools_list, "CONTRIBUTING.md and AGENTS.md") != null); try std.testing.expect(std.mem.indexOf(u8, tools_list, "run_explorer") != null); try std.testing.expect(std.mem.indexOf(u8, tools_list, "Maximum time for agent execution (default 300, max 600)") != null); try std.testing.expect(std.mem.indexOf(u8, tools_list, "Maximum total time for the full chain (default 300, max 600)") != null);