@codedrifters/configulator 0.0.226 → 0.0.228
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/index.js +329 -13
- package/lib/index.js.map +1 -1
- package/lib/index.mjs +329 -13
- package/lib/index.mjs.map +1 -1
- package/package.json +1 -1
package/lib/index.js
CHANGED
|
@@ -2267,6 +2267,148 @@ var companyProfileBundle = {
|
|
|
2267
2267
|
|
|
2268
2268
|
// src/agent/bundles/github-workflow.ts
|
|
2269
2269
|
var import_github = require("projen/lib/github");
|
|
2270
|
+
var setIssueTypeProcedure = {
|
|
2271
|
+
name: "set-issue-type.sh",
|
|
2272
|
+
description: "Assign a GitHub issue type (Feature / Task / Epic / Bug / etc.) via the updateIssueIssueType GraphQL mutation in a single step",
|
|
2273
|
+
content: [
|
|
2274
|
+
"#!/usr/bin/env bash",
|
|
2275
|
+
"# set-issue-type.sh \u2014 Assign a GitHub issue type in one step.",
|
|
2276
|
+
"#",
|
|
2277
|
+
"# Wraps the two-step GraphQL flow used to set an issue's type:",
|
|
2278
|
+
"# 1. Look up the repo's issue type node IDs.",
|
|
2279
|
+
"# 2. Call the updateIssueIssueType mutation.",
|
|
2280
|
+
"#",
|
|
2281
|
+
"# Usage:",
|
|
2282
|
+
"# .claude/procedures/set-issue-type.sh <issue-number> <type-name>",
|
|
2283
|
+
"#",
|
|
2284
|
+
"# Where <type-name> is the human-readable GitHub issue type name",
|
|
2285
|
+
"# (e.g. Feature, Task, Epic, Bug). Matching is case-insensitive.",
|
|
2286
|
+
"#",
|
|
2287
|
+
"# Exits 0 on success. Exits non-zero with a clear diagnostic on stderr",
|
|
2288
|
+
"# for any validation error or API failure.",
|
|
2289
|
+
"",
|
|
2290
|
+
"set -uo pipefail",
|
|
2291
|
+
"",
|
|
2292
|
+
"# \u2500\u2500 helpers \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500",
|
|
2293
|
+
"",
|
|
2294
|
+
"err() {",
|
|
2295
|
+
' printf "set-issue-type.sh: %s\\n" "$*" >&2',
|
|
2296
|
+
"}",
|
|
2297
|
+
"",
|
|
2298
|
+
"usage() {",
|
|
2299
|
+
" cat >&2 <<'USAGE'",
|
|
2300
|
+
"Usage: set-issue-type.sh <issue-number> <type-name>",
|
|
2301
|
+
"",
|
|
2302
|
+
" <issue-number> Positive integer GitHub issue number.",
|
|
2303
|
+
" <type-name> Human-readable issue type (Feature, Task, Epic, Bug,",
|
|
2304
|
+
" or any type defined at the org level). Case-insensitive.",
|
|
2305
|
+
"",
|
|
2306
|
+
"Examples:",
|
|
2307
|
+
" set-issue-type.sh 123 Feature",
|
|
2308
|
+
" set-issue-type.sh 456 bug",
|
|
2309
|
+
"USAGE",
|
|
2310
|
+
"}",
|
|
2311
|
+
"",
|
|
2312
|
+
"# \u2500\u2500 argument validation \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500",
|
|
2313
|
+
"",
|
|
2314
|
+
"if [[ $# -ne 2 ]]; then",
|
|
2315
|
+
' err "expected 2 arguments, got $#"',
|
|
2316
|
+
" usage",
|
|
2317
|
+
" exit 2",
|
|
2318
|
+
"fi",
|
|
2319
|
+
"",
|
|
2320
|
+
'issue_number="$1"',
|
|
2321
|
+
'type_name="$2"',
|
|
2322
|
+
"",
|
|
2323
|
+
'if ! [[ "$issue_number" =~ ^[1-9][0-9]*$ ]]; then',
|
|
2324
|
+
` err "issue number must be a positive integer (got: '$issue_number')"`,
|
|
2325
|
+
" exit 2",
|
|
2326
|
+
"fi",
|
|
2327
|
+
"",
|
|
2328
|
+
'if [[ -z "${type_name// /}" ]]; then',
|
|
2329
|
+
' err "type name must be non-empty"',
|
|
2330
|
+
" exit 2",
|
|
2331
|
+
"fi",
|
|
2332
|
+
"",
|
|
2333
|
+
"# \u2500\u2500 dependency checks \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500",
|
|
2334
|
+
"",
|
|
2335
|
+
"for cmd in gh jq; do",
|
|
2336
|
+
' if ! command -v "$cmd" >/dev/null 2>&1; then',
|
|
2337
|
+
' err "required command not found on PATH: $cmd"',
|
|
2338
|
+
" exit 3",
|
|
2339
|
+
" fi",
|
|
2340
|
+
"done",
|
|
2341
|
+
"",
|
|
2342
|
+
"# \u2500\u2500 resolve repo owner/name \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500",
|
|
2343
|
+
"",
|
|
2344
|
+
"repo_json=$(gh repo view --json owner,name 2>/dev/null)",
|
|
2345
|
+
'if [[ -z "$repo_json" ]]; then',
|
|
2346
|
+
` err "could not resolve owning repo via 'gh repo view' (not a GitHub repo or gh not authenticated?)"`,
|
|
2347
|
+
" exit 4",
|
|
2348
|
+
"fi",
|
|
2349
|
+
"",
|
|
2350
|
+
`owner=$(echo "$repo_json" | jq -r '.owner.login // empty')`,
|
|
2351
|
+
`name=$(echo "$repo_json" | jq -r '.name // empty')`,
|
|
2352
|
+
"",
|
|
2353
|
+
'if [[ -z "$owner" || -z "$name" ]]; then',
|
|
2354
|
+
' err "could not parse owner/name from gh repo view output"',
|
|
2355
|
+
" exit 4",
|
|
2356
|
+
"fi",
|
|
2357
|
+
"",
|
|
2358
|
+
"# \u2500\u2500 look up issue type node ID \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500",
|
|
2359
|
+
"",
|
|
2360
|
+
"types_json=$(gh api graphql \\",
|
|
2361
|
+
" -f query='query($owner:String!,$repo:String!){repository(owner:$owner,name:$repo){issueTypes(first:50){nodes{id name}}}}' \\",
|
|
2362
|
+
' -f owner="$owner" -f repo="$name" 2>/dev/null)',
|
|
2363
|
+
"",
|
|
2364
|
+
'if [[ -z "$types_json" ]]; then',
|
|
2365
|
+
' err "failed to query repo issue types via GraphQL"',
|
|
2366
|
+
" exit 5",
|
|
2367
|
+
"fi",
|
|
2368
|
+
"",
|
|
2369
|
+
`types_nodes=$(echo "$types_json" | jq -c '.data.repository.issueTypes.nodes // []')`,
|
|
2370
|
+
"",
|
|
2371
|
+
'if [[ "$types_nodes" == "[]" || "$types_nodes" == "null" ]]; then',
|
|
2372
|
+
' err "repo ${owner}/${name} has no issue types defined"',
|
|
2373
|
+
" exit 5",
|
|
2374
|
+
"fi",
|
|
2375
|
+
"",
|
|
2376
|
+
"# Case-insensitive match by name.",
|
|
2377
|
+
`type_id=$(echo "$types_nodes" | jq -r --arg n "$type_name" '`,
|
|
2378
|
+
" .[] | select((.name | ascii_downcase) == ($n | ascii_downcase)) | .id",
|
|
2379
|
+
"' | head -n 1)",
|
|
2380
|
+
"",
|
|
2381
|
+
'if [[ -z "$type_id" ]]; then',
|
|
2382
|
+
` available=$(echo "$types_nodes" | jq -r '.[].name' | paste -sd ',' - | sed 's/,/, /g')`,
|
|
2383
|
+
" err \"type '${type_name}' not found in ${owner}/${name}. Available types: ${available}\"",
|
|
2384
|
+
" exit 6",
|
|
2385
|
+
"fi",
|
|
2386
|
+
"",
|
|
2387
|
+
"# \u2500\u2500 look up issue node ID \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500",
|
|
2388
|
+
"",
|
|
2389
|
+
`issue_id=$(gh issue view "$issue_number" --json id -q '.id' 2>/dev/null || echo "")`,
|
|
2390
|
+
"",
|
|
2391
|
+
'if [[ -z "$issue_id" ]]; then',
|
|
2392
|
+
' err "issue #${issue_number} not found in ${owner}/${name}"',
|
|
2393
|
+
" exit 7",
|
|
2394
|
+
"fi",
|
|
2395
|
+
"",
|
|
2396
|
+
"# \u2500\u2500 apply the mutation \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500",
|
|
2397
|
+
"",
|
|
2398
|
+
"result=$(gh api graphql \\",
|
|
2399
|
+
" -f query='mutation($issueId:ID!,$typeId:ID!){updateIssueIssueType(input:{issueId:$issueId,issueTypeId:$typeId}){issue{number issueType{name}}}}' \\",
|
|
2400
|
+
' -f issueId="$issue_id" -f typeId="$type_id" 2>&1)',
|
|
2401
|
+
"mutation_exit=$?",
|
|
2402
|
+
"",
|
|
2403
|
+
"if [[ $mutation_exit -ne 0 ]]; then",
|
|
2404
|
+
' err "updateIssueIssueType mutation failed: ${result}"',
|
|
2405
|
+
" exit 8",
|
|
2406
|
+
"fi",
|
|
2407
|
+
"",
|
|
2408
|
+
"# Print the resulting {number, issueType: {name}} JSON line.",
|
|
2409
|
+
`echo "$result" | jq -c '.data.updateIssueIssueType.issue'`
|
|
2410
|
+
].join("\n")
|
|
2411
|
+
};
|
|
2270
2412
|
var githubWorkflowBundle = {
|
|
2271
2413
|
name: "github-workflow",
|
|
2272
2414
|
description: "GitHub issue and PR workflow automation patterns",
|
|
@@ -2329,19 +2471,20 @@ var githubWorkflowBundle = {
|
|
|
2329
2471
|
" - `--title '<type>: <description>'`",
|
|
2330
2472
|
" - `--body '<issue body>'`",
|
|
2331
2473
|
" - `--label '<type-label>' --label '<priority-label>' --label '<status-label>'`",
|
|
2332
|
-
"7. **Set the GitHub issue type**
|
|
2333
|
-
" - Look up the issue's node ID: `gh issue view <issue-number> --json id -q .id`",
|
|
2334
|
-
" - Look up the repo's issue type node IDs (one-time, can be cached):",
|
|
2474
|
+
"7. **Set the GitHub issue type** by invoking the `set-issue-type.sh` helper (shipped with this bundle):",
|
|
2335
2475
|
"",
|
|
2336
|
-
"
|
|
2337
|
-
"
|
|
2338
|
-
"
|
|
2476
|
+
" ```sh",
|
|
2477
|
+
" .claude/procedures/set-issue-type.sh <issue-number> <Feature|Task|Epic|Bug>",
|
|
2478
|
+
" ```",
|
|
2479
|
+
"",
|
|
2480
|
+
" The helper resolves owner/repo, looks up the issue type node ID, looks up the issue node ID, and applies the `updateIssueIssueType` mutation in one step. It exits non-zero with a clear diagnostic on any error and lists available types if the type name is not recognised.",
|
|
2339
2481
|
"",
|
|
2340
|
-
" -
|
|
2482
|
+
" **Under the hood** (documented fallback if the helper is unavailable): the helper performs a two-step GraphQL flow \u2014 first a `repository(...).issueTypes` query to map the human-readable type name to a node ID, then the `updateIssueIssueType` mutation. The canonical queries are:",
|
|
2341
2483
|
"",
|
|
2342
|
-
"
|
|
2343
|
-
"
|
|
2344
|
-
"
|
|
2484
|
+
" ```sh",
|
|
2485
|
+
" gh api graphql -f query='query($owner:String!,$repo:String!){repository(owner:$owner,name:$repo){issueTypes(first:50){nodes{id name}}}}' -f owner=<owner> -f repo=<repo>",
|
|
2486
|
+
" gh api graphql -f query='mutation($issueId:ID!,$typeId:ID!){updateIssueIssueType(input:{issueId:$issueId,issueTypeId:$typeId}){issue{number issueType{name}}}}' -f issueId=<issue-node-id> -f typeId=<issue-type-node-id>",
|
|
2487
|
+
" ```",
|
|
2345
2488
|
"",
|
|
2346
2489
|
"### Issue Body Template",
|
|
2347
2490
|
"",
|
|
@@ -2362,7 +2505,7 @@ var githubWorkflowBundle = {
|
|
|
2362
2505
|
"### Important",
|
|
2363
2506
|
"",
|
|
2364
2507
|
"- Always use the conventional prefix in the issue title",
|
|
2365
|
-
"- Always assign the correct GitHub issue type via the `
|
|
2508
|
+
"- Always assign the correct GitHub issue type via the `set-issue-type.sh` helper (step 7) \u2014 never via `gh issue create --type`",
|
|
2366
2509
|
"- Always include `type:*`, `priority:*`, and `status:*` labels",
|
|
2367
2510
|
"- If the user does not specify a type, ask before creating the issue",
|
|
2368
2511
|
"- If the priority cannot be inferred from the description, ask the user before creating the issue",
|
|
@@ -2414,7 +2557,8 @@ var githubWorkflowBundle = {
|
|
|
2414
2557
|
].join("\n"),
|
|
2415
2558
|
tags: ["workflow"]
|
|
2416
2559
|
}
|
|
2417
|
-
]
|
|
2560
|
+
],
|
|
2561
|
+
procedures: [setIssueTypeProcedure]
|
|
2418
2562
|
};
|
|
2419
2563
|
|
|
2420
2564
|
// src/agent/bundles/industry-discovery.ts
|
|
@@ -6744,7 +6888,179 @@ var prReviewBundle = {
|
|
|
6744
6888
|
"to a PR's branch \u2014 it only reviews, decides, and orchestrates merge",
|
|
6745
6889
|
"or comment. In loop mode, a failed review for one PR never stops",
|
|
6746
6890
|
"the loop; the reviewer comments and moves on. See the `pr-reviewer`",
|
|
6747
|
-
"agent definition for the full phase-by-phase contract."
|
|
6891
|
+
"agent definition for the full phase-by-phase contract.",
|
|
6892
|
+
"",
|
|
6893
|
+
"## Human-in-the-Loop Feedback Protocol",
|
|
6894
|
+
"",
|
|
6895
|
+
"The PR review pipeline is a **human-in-the-loop feedback loop**.",
|
|
6896
|
+
"Reviewers (human or agent) leave comments on the PR; the",
|
|
6897
|
+
"`pr-reviewer` sub-agent classifies each comment, reacts to it,",
|
|
6898
|
+
"delegates in-scope fixes to `issue-worker`, and updates a single",
|
|
6899
|
+
"sticky `## Reviewer notes` comment that is the canonical record of",
|
|
6900
|
+
"PR state. The sections below document the conventions humans need",
|
|
6901
|
+
"to read and drive that loop.",
|
|
6902
|
+
"",
|
|
6903
|
+
"### Trigger Model: Human-Triggered, Single-Pass",
|
|
6904
|
+
"",
|
|
6905
|
+
"Each reviewer pass runs exactly once and does not self-chain. A",
|
|
6906
|
+
"human re-invokes `/review-pr <n>` (or `/review-prs`) whenever the",
|
|
6907
|
+
"PR state changes enough to warrant another look \u2014 a new comment,",
|
|
6908
|
+
"a new commit, a resolved pushback, a label flip. The reviewer",
|
|
6909
|
+
"never reschedules itself and never loops back after handing off to",
|
|
6910
|
+
"`issue-worker`: the worker's run is the terminal step of that",
|
|
6911
|
+
"pass, and a human must re-invoke the reviewer to see the follow-up",
|
|
6912
|
+
"reactions and the auto-merge re-enablement decision.",
|
|
6913
|
+
"",
|
|
6914
|
+
"This keeps the loop cheap to reason about: every agent action is",
|
|
6915
|
+
"traceable to a specific human invocation, and there is no",
|
|
6916
|
+
"background automation to pause or cancel.",
|
|
6917
|
+
"",
|
|
6918
|
+
"### Reaction State Machine",
|
|
6919
|
+
"",
|
|
6920
|
+
"The reviewer signals its disposition toward each human comment via",
|
|
6921
|
+
"GitHub reactions on that comment. Five reactions carry meaning in",
|
|
6922
|
+
"this workflow; every other reaction is ignored.",
|
|
6923
|
+
"",
|
|
6924
|
+
"| Reaction | Meaning | Terminal? |",
|
|
6925
|
+
"|----------|---------|-----------|",
|
|
6926
|
+
"| `eyes` | Seen by reviewer; no terminal decision yet. Queued for processing on this or a later pass. | No |",
|
|
6927
|
+
"| `+1` | Reviewer accepted the comment's request; a fix has been queued or has already landed. | **Yes** |",
|
|
6928
|
+
"| `rocket` | The accepted fix has landed on the branch. The reviewer's reply cites the commit SHA that applied it. | **Yes** |",
|
|
6929
|
+
"| `thinking_face` | Reviewer pushback \u2014 the comment conflicts with an acceptance criterion, a CLAUDE.md convention, the project-context doc, or is ambiguous. **Blocks auto-merge** until resolved. | No |",
|
|
6930
|
+
"| `-1` | Declined as out-of-scope. A separate tracking issue was created; the reviewer's reply links to it. | **Yes** |",
|
|
6931
|
+
"",
|
|
6932
|
+
"Terminal reactions (`+1`, `rocket`, `-1`) are applied **only after**",
|
|
6933
|
+
"the corresponding action has truly completed \u2014 the fix accepted,",
|
|
6934
|
+
"the commit landed on the branch, or the out-of-scope tracking",
|
|
6935
|
+
"issue created and linked in a reply. The reviewer never applies a",
|
|
6936
|
+
"terminal reaction pre-emptively.",
|
|
6937
|
+
"",
|
|
6938
|
+
"A comment carrying only `eyes` or `thinking_face` from the",
|
|
6939
|
+
"reviewer is **non-terminal** and will be re-evaluated on the next",
|
|
6940
|
+
"pass. A comment carrying any terminal reaction authored by the",
|
|
6941
|
+
"reviewer is dropped from future classification.",
|
|
6942
|
+
"",
|
|
6943
|
+
"GitHub's reactions API uses `confused` as the content string for",
|
|
6944
|
+
"the `thinking_face` reaction (`content=confused` when POSTing).",
|
|
6945
|
+
"",
|
|
6946
|
+
"### Resolving a Pushback",
|
|
6947
|
+
"",
|
|
6948
|
+
"When the reviewer pushes back on a comment with `thinking_face`,",
|
|
6949
|
+
"auto-merge is blocked until the dispute is resolved. Humans have",
|
|
6950
|
+
"three ways to clear a pushback:",
|
|
6951
|
+
"",
|
|
6952
|
+
"1. **Withdraw the comment.** Delete the comment, or edit out the",
|
|
6953
|
+
" disputed request, then re-invoke `/review-pr <n>`. The reviewer",
|
|
6954
|
+
" drops the withdrawn item from its queue on the next pass.",
|
|
6955
|
+
"2. **Reply with clarification.** Post a reply on the same thread",
|
|
6956
|
+
" that addresses the reviewer's objection (cite the acceptance",
|
|
6957
|
+
" criterion you meant, supply the missing context, or concede the",
|
|
6958
|
+
" point). Re-invoke `/review-pr <n>` \u2014 the reviewer re-classifies",
|
|
6959
|
+
" the thread and may promote `thinking_face` to `+1` if the",
|
|
6960
|
+
" clarification satisfies it.",
|
|
6961
|
+
"3. **Force through with `review:auto-ok`.** Apply the",
|
|
6962
|
+
" `review:auto-ok` label to the PR as an explicit maintainer",
|
|
6963
|
+
" override. The reviewer will log the override in the sticky",
|
|
6964
|
+
" `## Reviewer notes` comment and proceed with auto-merge even",
|
|
6965
|
+
" though the dispute was never resolved by reply or withdrawal.",
|
|
6966
|
+
"",
|
|
6967
|
+
"### Fix-List Comment Format",
|
|
6968
|
+
"",
|
|
6969
|
+
"When Phase 4 delegates in-scope fixes to `issue-worker`, it posts",
|
|
6970
|
+
"a single PR-level comment whose body carries both a human-readable",
|
|
6971
|
+
"checkbox summary and a fenced ```json fix-list``` block. The JSON",
|
|
6972
|
+
"block is the authoritative payload the worker parses; the",
|
|
6973
|
+
"checkbox list is for humans reading the PR.",
|
|
6974
|
+
"",
|
|
6975
|
+
"```markdown",
|
|
6976
|
+
"## Reviewer: fix list for @issue-worker",
|
|
6977
|
+
"",
|
|
6978
|
+
"- [ ] @<author> \u2014 <instruction summary> (<file>:<line>)",
|
|
6979
|
+
"",
|
|
6980
|
+
"```json fix-list",
|
|
6981
|
+
"{",
|
|
6982
|
+
' "pr": <pr-number>,',
|
|
6983
|
+
' "branch": "<head-ref-name>",',
|
|
6984
|
+
' "generated_at": "<ISO-8601 timestamp>",',
|
|
6985
|
+
' "items": [',
|
|
6986
|
+
' {"comment_id": "<id>", "author": "<login>", "file": "<path>", "line": <n>, "instruction": "<imperative instruction>"}',
|
|
6987
|
+
" ]",
|
|
6988
|
+
"}",
|
|
6989
|
+
"```",
|
|
6990
|
+
"```",
|
|
6991
|
+
"",
|
|
6992
|
+
"Each `items[]` entry corresponds to one in-scope comment the",
|
|
6993
|
+
"reviewer queued on this pass. The `comment_id` is preserved",
|
|
6994
|
+
"exactly as returned by the GitHub API so that `issue-worker` can",
|
|
6995
|
+
"report per-item outcomes and the reviewer can apply `rocket` or",
|
|
6996
|
+
"`thinking_face` to the correct source comment on the next pass.",
|
|
6997
|
+
"",
|
|
6998
|
+
"### Sticky `## Reviewer notes` Comment",
|
|
6999
|
+
"",
|
|
7000
|
+
"Every PR has **one** canonical reviewer-notes comment. The",
|
|
7001
|
+
"reviewer creates it on the first pass, then **edits it in place**",
|
|
7002
|
+
"on every subsequent pass via",
|
|
7003
|
+
"`gh api .../issues/comments/<id> -X PATCH`. It is never",
|
|
7004
|
+
"duplicated and never replaced by a fresh per-pass summary.",
|
|
7005
|
+
"",
|
|
7006
|
+
"This sticky comment is the **single human-facing source of truth**",
|
|
7007
|
+
"for the PR's current state. Humans scanning the PR should read",
|
|
7008
|
+
"the sticky first, before scrolling back through individual threads.",
|
|
7009
|
+
"It carries, at a minimum:",
|
|
7010
|
+
"",
|
|
7011
|
+
"- **Mode** \u2014 `auto-merge` or `human-required`, with the Phase 2.75",
|
|
7012
|
+
" reason that chose that mode.",
|
|
7013
|
+
"- **AC status** \u2014 met, partial, or missing, with evidence links",
|
|
7014
|
+
" to files or tests.",
|
|
7015
|
+
"- **CI status** \u2014 green, pending, or red.",
|
|
7016
|
+
"- **Outstanding** \u2014 comments still carrying a non-terminal",
|
|
7017
|
+
" reviewer reaction (`eyes`, open `thinking_face`).",
|
|
7018
|
+
"- **Pushbacks** \u2014 every unresolved `thinking_face` the reviewer",
|
|
7019
|
+
" has left, with the reason captured in its pushback reply.",
|
|
7020
|
+
"- **Last pass** \u2014 the ISO 8601 timestamp of the most recent run.",
|
|
7021
|
+
"",
|
|
7022
|
+
"The sticky is updated on every pass \u2014 including passes that ended",
|
|
7023
|
+
"in a pushback-gated skip, a `NEEDS_CHANGES` findings comment, or",
|
|
7024
|
+
"a `human-required` hand-off \u2014 so it never goes stale while the",
|
|
7025
|
+
"reviewer is actively processing the PR.",
|
|
7026
|
+
"",
|
|
7027
|
+
"### Label Glossary",
|
|
7028
|
+
"",
|
|
7029
|
+
"Five review-workflow labels drive the feedback loop. Consumers",
|
|
7030
|
+
"that adopt this workflow are responsible for creating them in",
|
|
7031
|
+
"their own repos (the same way they create `priority:*` and",
|
|
7032
|
+
"`status:*` labels).",
|
|
7033
|
+
"",
|
|
7034
|
+
"| Label | Purpose |",
|
|
7035
|
+
"|-------|---------|",
|
|
7036
|
+
"| `origin:issue-worker` | PR was opened by the `issue-worker` agent. Eligible for auto-delegation of in-scope fixes. Human-authored PRs lack this label and will not trigger delegation unless the reviewer is invoked with `--allow-human-author`. |",
|
|
7037
|
+
"| `review:human-required` | Force human review regardless of what the policy would otherwise decide. The reviewer never enables auto-merge on a PR carrying this label. |",
|
|
7038
|
+
"| `review:auto-ok` | Force auto-merge regardless of what the policy would otherwise decide. **Also resolves outstanding `thinking_face` pushbacks** as an explicit maintainer override; the reviewer logs the override in the sticky summary. |",
|
|
7039
|
+
"| `review:awaiting-human` | Set by the reviewer when it completes its work on a `human-required` PR and is handing off the final merge decision. Cleared by a human (or by `review:auto-ok` flipping the PR back to `auto-merge` mode). |",
|
|
7040
|
+
"| `review:fixing` | Short-lived lease held by the reviewer while an `issue-worker` feedback-mode delegation is mid-run. Released automatically at the end of Phase 4 step (g). Contention on this label means a prior delegation crashed without releasing it and needs human investigation. |",
|
|
7041
|
+
"",
|
|
7042
|
+
"### Reviewing Human-Authored PRs: the `--allow-human-author` Flag",
|
|
7043
|
+
"",
|
|
7044
|
+
"By default the reviewer only **delegates** in-scope fixes on",
|
|
7045
|
+
"bot-authored PRs \u2014 those carrying the `origin:issue-worker`",
|
|
7046
|
+
"label. Running `/review-pr <n>` or `/review-prs` on a",
|
|
7047
|
+
"human-authored PR still produces a full review (reactions,",
|
|
7048
|
+
"replies, sticky summary, and auto-merge when the policy allows",
|
|
7049
|
+
"it) but skips the delegation hand-off to `issue-worker` \u2014 the",
|
|
7050
|
+
"human author is expected to apply the fixes themselves.",
|
|
7051
|
+
"",
|
|
7052
|
+
"Pass `--allow-human-author` to opt into delegation on",
|
|
7053
|
+
"human-authored PRs for a single invocation:",
|
|
7054
|
+
"",
|
|
7055
|
+
"```",
|
|
7056
|
+
"/review-pr <pr-number> --allow-human-author",
|
|
7057
|
+
"/review-prs --allow-human-author",
|
|
7058
|
+
"```",
|
|
7059
|
+
"",
|
|
7060
|
+
"The flag does **not** persist across invocations. Subsequent",
|
|
7061
|
+
"invocations return to the bot-only default and require the flag",
|
|
7062
|
+
"to be re-supplied if delegation on a human-authored PR is desired",
|
|
7063
|
+
"again."
|
|
6748
7064
|
].join("\n"),
|
|
6749
7065
|
platforms: {
|
|
6750
7066
|
cursor: { exclude: true }
|