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
60 changes: 60 additions & 0 deletions internal/toolsnaps/toolsnaps_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -252,3 +252,63 @@ func TestToolSnapKeysSorted(t *testing.T) {
assert.Greater(t, mmmIndex, aaaIndex, "mmm should come after aaa")
assert.Greater(t, zzzIndex, mmmIndex, "zzz should come after mmm")
}

func TestStructFieldOrderingSortedAlphabetically(t *testing.T) {
withIsolatedWorkingDir(t)

// Given a struct with fields defined in non-alphabetical order
// This test ensures that struct field order doesn't affect the JSON output
type toolWithNonAlphabeticalFields struct {
ZField string `json:"zField"` // Should appear last in JSON
AField string `json:"aField"` // Should appear first in JSON
MField string `json:"mField"` // Should appear in the middle
Comment on lines +262 to +264
Copy link

Copilot AI Jan 15, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The PR description claims to add TOOLSNAP_CHURN_EXPLANATION.md documenting why toolsnaps showed churn, but this file is not present in the changes. The documentation mentioned in the 'What changed' and 'Docs' sections of the PR description is missing. If documentation was intended to be added, it should be included in the PR.

Copilot uses AI. Check for mistakes.
}

tool := toolWithNonAlphabeticalFields{
ZField: "z value",
AField: "a value",
MField: "m value",
}

// When we write the snapshot
t.Setenv("UPDATE_TOOLSNAPS", "true")
err := Test("struct_field_order", tool)
require.NoError(t, err)

// Then the snapshot file should have alphabetically sorted keys despite struct field order
snapJSON, err := os.ReadFile("__toolsnaps__/struct_field_order.snap")
require.NoError(t, err)

snapStr := string(snapJSON)

// Find the positions of each field in the JSON string
aFieldIndex := -1
mFieldIndex := -1
zFieldIndex := -1
for i := 0; i < len(snapStr)-7; i++ {
Copy link

Copilot AI Jan 15, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The loop boundary condition is incorrect. To safely access snapStr[i : i+6] (a 6-character substring), the condition should be i < len(snapStr)-5 not i < len(snapStr)-7. The current condition stops 2 characters too early, potentially missing field names near the end of the string.

This issue also appears in the following locations of the same file:

  • line 289
Suggested change
for i := 0; i < len(snapStr)-7; i++ {
for i := 0; i < len(snapStr)-5; i++ {

Copilot uses AI. Check for mistakes.
switch snapStr[i : i+6] {
case "aField":
aFieldIndex = i
case "mField":
mFieldIndex = i
case "zField":
zFieldIndex = i
}
}

// Verify alphabetical ordering in the JSON output
require.NotEqual(t, -1, aFieldIndex, "aField should be present")
require.NotEqual(t, -1, mFieldIndex, "mField should be present")
require.NotEqual(t, -1, zFieldIndex, "zField should be present")
assert.Less(t, aFieldIndex, mFieldIndex, "aField should appear before mField")
assert.Less(t, mFieldIndex, zFieldIndex, "mField should appear before zField")

// Also verify idempotency - running the test again should produce identical output
err = Test("struct_field_order", tool)
require.NoError(t, err)

snapJSON2, err := os.ReadFile("__toolsnaps__/struct_field_order.snap")
require.NoError(t, err)

assert.Equal(t, string(snapJSON), string(snapJSON2), "Multiple runs should produce identical output")
}
60 changes: 30 additions & 30 deletions pkg/github/__toolsnaps__/add_comment_to_pending_review.snap
Original file line number Diff line number Diff line change
Expand Up @@ -4,69 +4,69 @@
},
"description": "Add review comment to the requester's latest pending pull request review. A pending review needs to already exist to call this (check with the user if not sure).",
"inputSchema": {
"type": "object",
"required": [
"owner",
"repo",
"pullNumber",
"path",
"body",
"subjectType"
],
"properties": {
"body": {
"type": "string",
"description": "The text of the review comment"
"description": "The text of the review comment",
"type": "string"
},
"line": {
"type": "number",
"description": "The line of the blob in the pull request diff that the comment applies to. For multi-line comments, the last line of the range"
"description": "The line of the blob in the pull request diff that the comment applies to. For multi-line comments, the last line of the range",
"type": "number"
},
"owner": {
"type": "string",
"description": "Repository owner"
"description": "Repository owner",
"type": "string"
},
"path": {
"type": "string",
"description": "The relative path to the file that necessitates a comment"
"description": "The relative path to the file that necessitates a comment",
"type": "string"
},
"pullNumber": {
"type": "number",
"description": "Pull request number"
"description": "Pull request number",
"type": "number"
},
"repo": {
"type": "string",
"description": "Repository name"
"description": "Repository name",
"type": "string"
},
"side": {
"type": "string",
"description": "The side of the diff to comment on. LEFT indicates the previous state, RIGHT indicates the new state",
"enum": [
"LEFT",
"RIGHT"
]
],
"type": "string"
},
"startLine": {
"type": "number",
"description": "For multi-line comments, the first line of the range that the comment applies to"
"description": "For multi-line comments, the first line of the range that the comment applies to",
"type": "number"
},
"startSide": {
"type": "string",
"description": "For multi-line comments, the starting side of the diff that the comment applies to. LEFT indicates the previous state, RIGHT indicates the new state",
"enum": [
"LEFT",
"RIGHT"
]
],
"type": "string"
},
"subjectType": {
"type": "string",
"description": "The level at which the comment is targeted",
"enum": [
"FILE",
"LINE"
]
],
"type": "string"
}
}
},
"required": [
"owner",
"repo",
"pullNumber",
"path",
"body",
"subjectType"
],
"type": "object"
},
"name": "add_comment_to_pending_review"
}
46 changes: 23 additions & 23 deletions pkg/github/__toolsnaps__/assign_copilot_to_issue.snap
Original file line number Diff line number Diff line change
Expand Up @@ -4,43 +4,43 @@
"title": "Assign Copilot to issue"
},
"description": "Assign Copilot to a specific issue in a GitHub repository.\n\nThis tool can help with the following outcomes:\n- a Pull Request created with source code changes to resolve the issue\n\n\nMore information can be found at:\n- https://docs.github.com/en/copilot/using-github-copilot/using-copilot-coding-agent-to-work-on-tasks/about-assigning-tasks-to-copilot\n",
"icons": [
{
"mimeType": "image/png",
"src": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABmJLR0QA/wD/AP+gvaeTAAAC20lEQVRIidWUS4wMURSGv3O7kWmPEMRrSMzcbl1dpqtmGuOxsCKECCKxEBusSJhIWEhsWLFAbC1sWFiISBARCyQ2kzSZGaMxHokgXvGIiMH0PRZjpJqqHpb+TeX+59z//H/q5sD/DqlX9H1/zFeX2qzIKoFWYDKgwBtUymL0UkNaT3V3d3/+5wG2EGxB9TDIxGFMvhVhb9/drpN/NaDJC7MGdwJk6TDCv0Gvq0lve9R762GUNdFDLleaZNBrICGq+4yhvf9TJtP/KZNB2PrLlbBliBfRhajuAwnFVa/n8/nkxFkv3GO9oJrzgwVxdesV71ov6I2r5fxggfWCatYL9yYmUJgLPH7Q29WZ4OED6Me4wuAdeQK6MMqna9t0GuibBHFAmgZ9JMG9BhkXZWoSCDSATIq7aguBD0wBplq/tZBgYDIwKnZAs99mFRYD9vd/YK0dpcqhobM6d9haWyOULRTbAauwuNlvsxHTYP3iBnVyXGAa8BIYC3oVeAKioCtAPEE7FCOgR0ErIJdBBZgNskzh40+NF6K6s+9e91lp9osrxMnFoTSmSmPVsF+E5cB0YEDgtoMjjypd5wCy+WC9GnajhEAa4bkqV9LOHKwa9/yneYeyUqwX3AdyQ5EeVrrqro/hYL0g+ggemKh4HGbPmVu0+fB8U76lpR6XgJwZpoGUpNYiusZg1tXjkmCAav0OMTXfJC4eVYPqwbot6l4BCPqyLhd7lwMAWC/cYb3gi/UCzRaKOxsbFzVEM1iv2Ebt5v2Dm14qZbJecZf1Ah3UCrcTbbB+awHnjgHLgHeinHYqZ8aPSXWWy+XvcQZLpdKI9/0D7UbZiLIJmABckVSqo+/OrUrNgF+D8q1LEdcBrAJGAJ8ROlGeicorABWdAswE5gOjge8CF8Ad66v03IjqJb75WS0tE0YOmNWqLBGReaAzgIkMLrt3oM9UpSzCzW9pd+FpT8/7JK3/Gz8Ao5X6wtwP7N4AAAAASUVORK5CYII=",
"theme": "light"
},
{
"mimeType": "image/png",
"src": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABmJLR0QA/wD/AP+gvaeTAAACCElEQVRIid2UPWsUYRSFn3dxWWJUkESiBgslFokfhehGiGClBBQx4h9IGlEh2ijYxh+gxEL/hIWwhYpF8KNZsFRJYdJEiUbjCkqisj4W+y6Mk5nd1U4PDMOce+45L3fmDvzXUDeo59WK+kb9rn5TF9R76jm1+2/NJ9QPtseSOv4nxrvVmQ6M05hRB9qZ98ZR1NRralntitdEwmw8wQ9HbS329rQKuKLW1XJO/aX6IqdWjr1Xk/y6lG4vMBdCqOacoZZ3uBBCVZ0HDrcK2AYs5ZkAuwBb1N8Dm5JEISXoAnqzOtU9QB+wVR3KCdgClDIr6kCc4c/0O1BLNnahiYpaSmmGY62e/JpCLJ4FpmmMaBHYCDwC5mmMZBQYBC7HnhvAK+B+fN4JHAM+R4+3wGQI4S7qaExtol+9o86pq+oX9Yk6ljjtGfVprK2qr9Xb6vaET109jjqb3Jac2XaM1PLNpok1Aep+G/+dfa24nADTX1EWTgOngLE2XCYKQL0DTfKex2WhXgCutxG9i/fFNlwWpgBQL6orcWyTaldToRbUA2pow61XL0WPFfXCb1HqkPowCj6q0+qIWsw7nlpUj6i31OXY+0AdbGpCRtNRGgt1AigCX4EqsJAYTR+wAzgEdAM/gApwM4TwOOm3JiARtBk4CYwAB4F+oIfGZi/HwOfAM6ASQviU5/Vv4xcBzmW2eT1nrQAAAABJRU5ErkJggg==",
"theme": "dark"
}
],
"inputSchema": {
"type": "object",
"properties": {
"base_ref": {
"type": "string",
"description": "Git reference (e.g., branch) that the agent will start its work from. If not specified, defaults to the repository's default branch"
"description": "Git reference (e.g., branch) that the agent will start its work from. If not specified, defaults to the repository's default branch",
"type": "string"
},
"issue_number": {
"type": "number",
"description": "Issue number"
"description": "Issue number",
"type": "number"
},
"owner": {
"type": "string",
"description": "Repository owner"
"description": "Repository owner",
"type": "string"
},
"repo": {
"type": "string",
"description": "Repository name"
"description": "Repository name",
"type": "string"
}
},
"required": [
"owner",
"repo",
"issue_number"
]
],
"type": "object"
},
"name": "assign_copilot_to_issue",
"icons": [
{
"src": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABmJLR0QA/wD/AP+gvaeTAAAC20lEQVRIidWUS4wMURSGv3O7kWmPEMRrSMzcbl1dpqtmGuOxsCKECCKxEBusSJhIWEhsWLFAbC1sWFiISBARCyQ2kzSZGaMxHokgXvGIiMH0PRZjpJqqHpb+TeX+59z//H/q5sD/DqlX9H1/zFeX2qzIKoFWYDKgwBtUymL0UkNaT3V3d3/+5wG2EGxB9TDIxGFMvhVhb9/drpN/NaDJC7MGdwJk6TDCv0Gvq0lve9R762GUNdFDLleaZNBrICGq+4yhvf9TJtP/KZNB2PrLlbBliBfRhajuAwnFVa/n8/nkxFkv3GO9oJrzgwVxdesV71ov6I2r5fxggfWCatYL9yYmUJgLPH7Q29WZ4OED6Me4wuAdeQK6MMqna9t0GuibBHFAmgZ9JMG9BhkXZWoSCDSATIq7aguBD0wBplq/tZBgYDIwKnZAs99mFRYD9vd/YK0dpcqhobM6d9haWyOULRTbAauwuNlvsxHTYP3iBnVyXGAa8BIYC3oVeAKioCtAPEE7FCOgR0ErIJdBBZgNskzh40+NF6K6s+9e91lp9osrxMnFoTSmSmPVsF+E5cB0YEDgtoMjjypd5wCy+WC9GnajhEAa4bkqV9LOHKwa9/yneYeyUqwX3AdyQ5EeVrrqro/hYL0g+ggemKh4HGbPmVu0+fB8U76lpR6XgJwZpoGUpNYiusZg1tXjkmCAav0OMTXfJC4eVYPqwbot6l4BCPqyLhd7lwMAWC/cYb3gi/UCzRaKOxsbFzVEM1iv2Ebt5v2Dm14qZbJecZf1Ah3UCrcTbbB+awHnjgHLgHeinHYqZ8aPSXWWy+XvcQZLpdKI9/0D7UbZiLIJmABckVSqo+/OrUrNgF+D8q1LEdcBrAJGAJ8ROlGeicorABWdAswE5gOjge8CF8Ad66v03IjqJb75WS0tE0YOmNWqLBGReaAzgIkMLrt3oM9UpSzCzW9pd+FpT8/7JK3/Gz8Ao5X6wtwP7N4AAAAASUVORK5CYII=",
"mimeType": "image/png",
"theme": "light"
},
{
"src": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABmJLR0QA/wD/AP+gvaeTAAACCElEQVRIid2UPWsUYRSFn3dxWWJUkESiBgslFokfhehGiGClBBQx4h9IGlEh2ijYxh+gxEL/hIWwhYpF8KNZsFRJYdJEiUbjCkqisj4W+y6Mk5nd1U4PDMOce+45L3fmDvzXUDeo59WK+kb9rn5TF9R76jm1+2/NJ9QPtseSOv4nxrvVmQ6M05hRB9qZ98ZR1NRralntitdEwmw8wQ9HbS329rQKuKLW1XJO/aX6IqdWjr1Xk/y6lG4vMBdCqOacoZZ3uBBCVZ0HDrcK2AYs5ZkAuwBb1N8Dm5JEISXoAnqzOtU9QB+wVR3KCdgClDIr6kCc4c/0O1BLNnahiYpaSmmGY62e/JpCLJ4FpmmMaBHYCDwC5mmMZBQYBC7HnhvAK+B+fN4JHAM+R4+3wGQI4S7qaExtol+9o86pq+oX9Yk6ljjtGfVprK2qr9Xb6vaET109jjqb3Jac2XaM1PLNpok1Aep+G/+dfa24nADTX1EWTgOngLE2XCYKQL0DTfKex2WhXgCutxG9i/fFNlwWpgBQL6orcWyTaldToRbUA2pow61XL0WPFfXCb1HqkPowCj6q0+qIWsw7nlpUj6i31OXY+0AdbGpCRtNRGgt1AigCX4EqsJAYTR+wAzgEdAM/gApwM4TwOOm3JiARtBk4CYwAB4F+oIfGZi/HwOfAM6ASQviU5/Vv4xcBzmW2eT1nrQAAAABJRU5ErkJggg==",
"mimeType": "image/png",
"theme": "dark"
}
]
"name": "assign_copilot_to_issue"
}
26 changes: 13 additions & 13 deletions pkg/github/__toolsnaps__/get_label.snap
Original file line number Diff line number Diff line change
Expand Up @@ -5,26 +5,26 @@
},
"description": "Get a specific label from a repository.",
"inputSchema": {
"type": "object",
"required": [
"owner",
"repo",
"name"
],
"properties": {
"name": {
"type": "string",
"description": "Label name."
"description": "Label name.",
"type": "string"
},
"owner": {
"type": "string",
"description": "Repository owner (username or organization name)"
"description": "Repository owner (username or organization name)",
"type": "string"
},
"repo": {
"type": "string",
"description": "Repository name"
"description": "Repository name",
"type": "string"
}
}
},
"required": [
"owner",
"repo",
"name"
],
"type": "object"
},
"name": "get_label"
}
44 changes: 22 additions & 22 deletions pkg/github/__toolsnaps__/label_write.snap
Original file line number Diff line number Diff line change
Expand Up @@ -4,48 +4,48 @@
},
"description": "Perform write operations on repository labels. To set labels on issues, use the 'update_issue' tool.",
"inputSchema": {
"type": "object",
"required": [
"method",
"owner",
"repo",
"name"
],
"properties": {
"color": {
"type": "string",
"description": "Label color as 6-character hex code without '#' prefix (e.g., 'f29513'). Required for 'create', optional for 'update'."
"description": "Label color as 6-character hex code without '#' prefix (e.g., 'f29513'). Required for 'create', optional for 'update'.",
"type": "string"
},
"description": {
"type": "string",
"description": "Label description text. Optional for 'create' and 'update'."
"description": "Label description text. Optional for 'create' and 'update'.",
"type": "string"
},
"method": {
"type": "string",
"description": "Operation to perform: 'create', 'update', or 'delete'",
"enum": [
"create",
"update",
"delete"
]
],
"type": "string"
},
"name": {
"type": "string",
"description": "Label name - required for all operations"
"description": "Label name - required for all operations",
"type": "string"
},
"new_name": {
"type": "string",
"description": "New name for the label (used only with 'update' method to rename)"
"description": "New name for the label (used only with 'update' method to rename)",
"type": "string"
},
"owner": {
"type": "string",
"description": "Repository owner (username or organization name)"
"description": "Repository owner (username or organization name)",
"type": "string"
},
"repo": {
"type": "string",
"description": "Repository name"
"description": "Repository name",
"type": "string"
}
}
},
"required": [
"method",
"owner",
"repo",
"name"
],
"type": "object"
},
"name": "label_write"
}
20 changes: 10 additions & 10 deletions pkg/github/__toolsnaps__/list_label.snap
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,21 @@
},
"description": "List labels from a repository",
"inputSchema": {
"type": "object",
"required": [
"owner",
"repo"
],
"properties": {
"owner": {
"type": "string",
"description": "Repository owner (username or organization name) - required for all operations"
"description": "Repository owner (username or organization name) - required for all operations",
"type": "string"
},
"repo": {
"type": "string",
"description": "Repository name - required for all operations"
"description": "Repository name - required for all operations",
"type": "string"
}
}
},
"required": [
"owner",
"repo"
],
"type": "object"
},
"name": "list_label"
}
Loading
Loading