ystack 0.1.0
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/CHANGELOG.md +24 -0
- package/LICENSE +21 -0
- package/LINTING.md +198 -0
- package/PHILOSOPHY.md +132 -0
- package/PLAN.md +515 -0
- package/README.md +103 -0
- package/RUNTIMES.md +199 -0
- package/bin/cli.js +973 -0
- package/hooks/context-monitor.js +30 -0
- package/hooks/session-start.sh +35 -0
- package/hooks/workflow-nudge.js +107 -0
- package/package.json +39 -0
- package/skills/address-review/SKILL.md +244 -0
- package/skills/build/SKILL.md +246 -0
- package/skills/build/resources/plan-checker.md +121 -0
- package/skills/docs/SKILL.md +160 -0
- package/skills/go/SKILL.md +216 -0
- package/skills/go/resources/executor.md +57 -0
- package/skills/import/SKILL.md +306 -0
- package/skills/pr/SKILL.md +152 -0
- package/skills/review/SKILL.md +184 -0
- package/skills/scaffold/SKILL.md +549 -0
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ystack context monitor — PostToolUse hook
|
|
3
|
+
*
|
|
4
|
+
* Warns when context usage gets high. Uses runtime-provided
|
|
5
|
+
* context metrics when available, stays silent otherwise.
|
|
6
|
+
*
|
|
7
|
+
* Supported env vars (set by the runtime):
|
|
8
|
+
* CLAUDE_CONTEXT_TOKENS_USED — tokens consumed so far
|
|
9
|
+
* CLAUDE_CONTEXT_TOKENS_MAX — total context window size
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
const used = Number.parseInt(process.env.CLAUDE_CONTEXT_TOKENS_USED || "0", 10);
|
|
13
|
+
const max = Number.parseInt(process.env.CLAUDE_CONTEXT_TOKENS_MAX || "0", 10);
|
|
14
|
+
|
|
15
|
+
// If the runtime doesn't expose context metrics, stay silent
|
|
16
|
+
if (!used || !max) {
|
|
17
|
+
process.exit(0);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const pct = Math.round((used / max) * 100);
|
|
21
|
+
|
|
22
|
+
if (pct >= 80) {
|
|
23
|
+
console.log(
|
|
24
|
+
`[ystack] Context ${pct}% full. Finish current task soon. Use /pause to save state if needed.`,
|
|
25
|
+
);
|
|
26
|
+
} else if (pct >= 60) {
|
|
27
|
+
console.log(
|
|
28
|
+
`[ystack] Context ${pct}% full. Consider spawning subagents for remaining work.`,
|
|
29
|
+
);
|
|
30
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# ystack session start — shows project status on session start
|
|
3
|
+
|
|
4
|
+
# Check for ystack project
|
|
5
|
+
if [ ! -f "ystack.config.json" ]; then
|
|
6
|
+
exit 0
|
|
7
|
+
fi
|
|
8
|
+
|
|
9
|
+
echo "[ystack] Project detected"
|
|
10
|
+
|
|
11
|
+
# Show Beads ready front
|
|
12
|
+
if [ -d ".beads" ] && command -v bd &> /dev/null; then
|
|
13
|
+
READY=$(bd ready --json 2>/dev/null | head -5)
|
|
14
|
+
if [ -n "$READY" ]; then
|
|
15
|
+
echo ""
|
|
16
|
+
echo "Ready to work on:"
|
|
17
|
+
bd ready 2>/dev/null | head -10
|
|
18
|
+
fi
|
|
19
|
+
fi
|
|
20
|
+
|
|
21
|
+
# Check for in-progress plans
|
|
22
|
+
if [ -d ".context" ]; then
|
|
23
|
+
PLANS=$(find .context -name "PLAN.md" -maxdepth 2 2>/dev/null)
|
|
24
|
+
if [ -n "$PLANS" ]; then
|
|
25
|
+
echo ""
|
|
26
|
+
echo "In-progress plans:"
|
|
27
|
+
for plan in $PLANS; do
|
|
28
|
+
FEATURE=$(dirname "$plan" | xargs basename)
|
|
29
|
+
TITLE=$(head -1 "$plan" | sed 's/^# //')
|
|
30
|
+
echo " $FEATURE — $TITLE"
|
|
31
|
+
done
|
|
32
|
+
echo ""
|
|
33
|
+
echo "Run /go to continue, or /build for new work."
|
|
34
|
+
fi
|
|
35
|
+
fi
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ystack workflow nudge — PreToolUse hook on Edit/Write
|
|
3
|
+
*
|
|
4
|
+
* Soft warning when editing multiple source files without an active plan.
|
|
5
|
+
* Tracks edits per session — only nudges after 3+ distinct source files
|
|
6
|
+
* are edited without a plan. One-off fixes don't trigger it.
|
|
7
|
+
*
|
|
8
|
+
* Dismissible: creating a file at .context/.no-nudge silences it for
|
|
9
|
+
* the session (e.g., when the developer intentionally works without a plan).
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import { existsSync, readFileSync, writeFileSync, readdirSync } from "node:fs";
|
|
13
|
+
import { join } from "node:path";
|
|
14
|
+
import { tmpdir } from "node:os";
|
|
15
|
+
|
|
16
|
+
// Session state file — tracks edited files and nudge status
|
|
17
|
+
const STATE_FILE = join(tmpdir(), ".ystack-nudge-state.json");
|
|
18
|
+
|
|
19
|
+
// Load state
|
|
20
|
+
let state = { editedFiles: [], nudged: false };
|
|
21
|
+
try {
|
|
22
|
+
if (existsSync(STATE_FILE)) {
|
|
23
|
+
state = JSON.parse(readFileSync(STATE_FILE, "utf-8"));
|
|
24
|
+
}
|
|
25
|
+
} catch {
|
|
26
|
+
// Fresh state
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// Already nudged this session
|
|
30
|
+
if (state.nudged) {
|
|
31
|
+
process.exit(0);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// Developer dismissed nudges
|
|
35
|
+
if (existsSync(".context/.no-nudge")) {
|
|
36
|
+
process.exit(0);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// Get the file being edited
|
|
40
|
+
const filePath = process.env.CLAUDE_TOOL_INPUT_FILE_PATH || "";
|
|
41
|
+
if (!filePath) {
|
|
42
|
+
process.exit(0);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// Skip non-source files — these never need a plan
|
|
46
|
+
const skipPatterns = [
|
|
47
|
+
/\.md$/,
|
|
48
|
+
/\.mdx$/,
|
|
49
|
+
/\.json$/,
|
|
50
|
+
/\.yaml$/,
|
|
51
|
+
/\.yml$/,
|
|
52
|
+
/\.toml$/,
|
|
53
|
+
/\.env/,
|
|
54
|
+
/\.config\./,
|
|
55
|
+
/\.css$/,
|
|
56
|
+
/_meta\.ts$/,
|
|
57
|
+
/meta\.json$/,
|
|
58
|
+
/\.gitignore$/,
|
|
59
|
+
/\.context\//,
|
|
60
|
+
/node_modules\//,
|
|
61
|
+
/\.next\//,
|
|
62
|
+
/dist\//,
|
|
63
|
+
/\.test\./,
|
|
64
|
+
/\.spec\./,
|
|
65
|
+
/__tests__\//,
|
|
66
|
+
];
|
|
67
|
+
|
|
68
|
+
if (skipPatterns.some((p) => p.test(filePath))) {
|
|
69
|
+
process.exit(0);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Check if there's an active plan
|
|
73
|
+
let hasActivePlan = false;
|
|
74
|
+
if (existsSync(".context")) {
|
|
75
|
+
try {
|
|
76
|
+
for (const entry of readdirSync(".context")) {
|
|
77
|
+
if (existsSync(join(".context", entry, "PLAN.md"))) {
|
|
78
|
+
hasActivePlan = true;
|
|
79
|
+
break;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
} catch {
|
|
83
|
+
// Can't read .context
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// If there's a plan, no nudge needed
|
|
88
|
+
if (hasActivePlan) {
|
|
89
|
+
process.exit(0);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// Track this file edit
|
|
93
|
+
if (!state.editedFiles.includes(filePath)) {
|
|
94
|
+
state.editedFiles.push(filePath);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// Only nudge after 3+ distinct source files edited without a plan
|
|
98
|
+
// One or two files = probably a quick fix, not feature work
|
|
99
|
+
if (state.editedFiles.length >= 3) {
|
|
100
|
+
console.log(
|
|
101
|
+
`[ystack] Editing ${state.editedFiles.length} source files without a plan. Consider /build for tracked changes, or touch .context/.no-nudge to dismiss.`,
|
|
102
|
+
);
|
|
103
|
+
state.nudged = true;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// Save state
|
|
107
|
+
writeFileSync(STATE_FILE, JSON.stringify(state));
|
package/package.json
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "ystack",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "An agent harness for doc-driven development",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"ystack": "./bin/cli.js"
|
|
8
|
+
},
|
|
9
|
+
"files": [
|
|
10
|
+
"skills/",
|
|
11
|
+
"hooks/",
|
|
12
|
+
"bin/",
|
|
13
|
+
"README.md",
|
|
14
|
+
"PHILOSOPHY.md",
|
|
15
|
+
"LINTING.md",
|
|
16
|
+
"RUNTIMES.md",
|
|
17
|
+
"PLAN.md",
|
|
18
|
+
"CHANGELOG.md",
|
|
19
|
+
"LICENSE"
|
|
20
|
+
],
|
|
21
|
+
"keywords": [
|
|
22
|
+
"ai",
|
|
23
|
+
"agent",
|
|
24
|
+
"harness",
|
|
25
|
+
"documentation",
|
|
26
|
+
"claude-code",
|
|
27
|
+
"beads",
|
|
28
|
+
"workflow"
|
|
29
|
+
],
|
|
30
|
+
"author": "Yulong He",
|
|
31
|
+
"license": "MIT",
|
|
32
|
+
"repository": {
|
|
33
|
+
"type": "git",
|
|
34
|
+
"url": "https://github.com/yulonghe97/ystack.git"
|
|
35
|
+
},
|
|
36
|
+
"dependencies": {
|
|
37
|
+
"@clack/prompts": "^1.2.0"
|
|
38
|
+
}
|
|
39
|
+
}
|
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: address-review
|
|
3
|
+
description: >
|
|
4
|
+
Fetch PR review comments, triage them by priority, and address them. Use this skill when the user says 'address review', '/address-review', 'address comments',
|
|
5
|
+
'fix review comments', 'address feedback', 'handle PR comments', 'review feedback',
|
|
6
|
+
'what do reviewers say', 'check PR comments', or when a PR has review comments that
|
|
7
|
+
need to be addressed.
|
|
8
|
+
Works with comments from human reviewers, AI reviewers, and CI checks.
|
|
9
|
+
user-invocable: true
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
# /address-review — Address Review Comments
|
|
13
|
+
|
|
14
|
+
You fetch review comments from a PR, triage them by priority and validity, present the triage to the user, then address the approved fixes.
|
|
15
|
+
|
|
16
|
+
## Phase 0: Find the PR
|
|
17
|
+
|
|
18
|
+
1. Detect the current PR:
|
|
19
|
+
```bash
|
|
20
|
+
gh pr view --json number,title,url,state,reviewDecision 2>/dev/null
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
2. If no PR is found on the current branch:
|
|
24
|
+
> No PR found for this branch. Provide a PR number or URL, or run `/pr` first.
|
|
25
|
+
|
|
26
|
+
3. If a PR number or URL was passed as an argument, use that instead.
|
|
27
|
+
|
|
28
|
+
## Phase 1: Fetch All Comments
|
|
29
|
+
|
|
30
|
+
Gather every piece of feedback on the PR.
|
|
31
|
+
|
|
32
|
+
### Review comments (inline on code)
|
|
33
|
+
```bash
|
|
34
|
+
gh api repos/{owner}/{repo}/pulls/{number}/comments --jq '.[] | {id, path, line: .original_line, body, user: .user.login, created_at}'
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### Review summaries (top-level reviews)
|
|
38
|
+
```bash
|
|
39
|
+
gh api repos/{owner}/{repo}/pulls/{number}/reviews --jq '.[] | {id, state, body, user: .user.login}'
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### General PR comments (conversation)
|
|
43
|
+
```bash
|
|
44
|
+
gh api repos/{owner}/{repo}/issues/{number}/comments --jq '.[] | {id, body, user: .user.login, created_at}'
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### CI check failures
|
|
48
|
+
```bash
|
|
49
|
+
gh pr checks --json name,state,description --jq '.[] | select(.state != "SUCCESS")'
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Combine all sources into a single list of feedback items.
|
|
53
|
+
|
|
54
|
+
## Phase 2: Triage
|
|
55
|
+
|
|
56
|
+
For each comment, evaluate and categorize it. Read the actual code the comment refers to before making a judgment.
|
|
57
|
+
|
|
58
|
+
### Categories
|
|
59
|
+
|
|
60
|
+
**MUST FIX** — Blocking issues that must be addressed before merge:
|
|
61
|
+
- Correctness bugs (logic errors, wrong behavior)
|
|
62
|
+
- Security issues (injection, auth bypass, secret exposure)
|
|
63
|
+
- Failed CI checks (typecheck, lint, build, tests)
|
|
64
|
+
- Reviewer explicitly requested changes (`CHANGES_REQUESTED` review state)
|
|
65
|
+
- Missing functionality that was promised in the PR description
|
|
66
|
+
|
|
67
|
+
**SHOULD FIX** — Valid improvements worth making:
|
|
68
|
+
- Accessibility gaps (missing ARIA, no keyboard support)
|
|
69
|
+
- Missing error handling at system boundaries
|
|
70
|
+
- Naming that doesn't match project conventions
|
|
71
|
+
- Performance concerns with evidence
|
|
72
|
+
- Suggestions that genuinely improve clarity
|
|
73
|
+
|
|
74
|
+
**WON'T FIX** — Comments to acknowledge but not act on:
|
|
75
|
+
- Style preferences not backed by project rules
|
|
76
|
+
- "Consider refactoring" on code outside the PR's scope
|
|
77
|
+
- Feature requests disguised as review comments
|
|
78
|
+
- Suggestions that contradict the locked decisions from DECISIONS.md
|
|
79
|
+
- Nitpicks on unchanged lines (pre-existing issues)
|
|
80
|
+
|
|
81
|
+
**FALSE POSITIVE** — Incorrect or misguided feedback:
|
|
82
|
+
- Reviewer misunderstood the code (explain why)
|
|
83
|
+
- Comment about code that doesn't exist (outdated diff)
|
|
84
|
+
- Suggestion that would break existing functionality
|
|
85
|
+
- CI flake (test passed on re-run, or unrelated to this PR)
|
|
86
|
+
|
|
87
|
+
### Triage output
|
|
88
|
+
|
|
89
|
+
Present the triage to the user:
|
|
90
|
+
|
|
91
|
+
```markdown
|
|
92
|
+
## PR Review Triage
|
|
93
|
+
|
|
94
|
+
### PR: #123 — feat(payments): add refund reason tracking
|
|
95
|
+
Reviewers: @sarah (changes requested), @ci-bot (2 checks failed)
|
|
96
|
+
|
|
97
|
+
---
|
|
98
|
+
|
|
99
|
+
### MUST FIX (3)
|
|
100
|
+
|
|
101
|
+
1. **@sarah** on `apps/api/src/routes/payments.ts:92`
|
|
102
|
+
> Missing validation for empty string — `reason: ""` would pass the enum check.
|
|
103
|
+
|
|
104
|
+
**Assessment:** Valid. Zod enum allows empty string if not explicitly excluded.
|
|
105
|
+
**Fix:** Add `.min(1)` or use `z.enum([...])` which already excludes empty. Quick fix.
|
|
106
|
+
|
|
107
|
+
2. **CI: typecheck** — FAILED
|
|
108
|
+
> Type 'string' is not assignable to type 'RefundReason'
|
|
109
|
+
|
|
110
|
+
**Assessment:** Real type error introduced by this PR.
|
|
111
|
+
**Fix:** Update the type cast in `admin/src/app/transactions/[id]/page.tsx`.
|
|
112
|
+
|
|
113
|
+
3. **@sarah** on `packages/db/src/schema.ts:48`
|
|
114
|
+
> This migration needs a default value for existing rows.
|
|
115
|
+
|
|
116
|
+
**Assessment:** Valid. Existing transactions have no refundReason. Column should be nullable or have a default.
|
|
117
|
+
**Fix:** Change column to `.default(null)` and update type to `RefundReason | null`.
|
|
118
|
+
|
|
119
|
+
---
|
|
120
|
+
|
|
121
|
+
### SHOULD FIX (1)
|
|
122
|
+
|
|
123
|
+
4. **@sarah** on `apps/admin/src/components/RefundReasonBadge.tsx:12`
|
|
124
|
+
> Badge should have different colors per reason type for visual distinction.
|
|
125
|
+
|
|
126
|
+
**Assessment:** Good UX suggestion. Not blocking but improves the feature.
|
|
127
|
+
**Fix:** Add variant colors — maps to existing badge color system.
|
|
128
|
+
|
|
129
|
+
---
|
|
130
|
+
|
|
131
|
+
### WON'T FIX (1)
|
|
132
|
+
|
|
133
|
+
5. **@sarah** on `packages/shared/src/types/payments.ts:25`
|
|
134
|
+
> Should we also add a `refundRequestedAt` timestamp?
|
|
135
|
+
|
|
136
|
+
**Assessment:** Feature request, not in scope. This was explicitly deferred in DECISIONS.md.
|
|
137
|
+
**Response:** Acknowledge and note it's tracked for future work.
|
|
138
|
+
|
|
139
|
+
---
|
|
140
|
+
|
|
141
|
+
### FALSE POSITIVE (1)
|
|
142
|
+
|
|
143
|
+
6. **CI: e2e-tests** — FAILED
|
|
144
|
+
> Timeout on unrelated test: `auth/login.spec.ts`
|
|
145
|
+
|
|
146
|
+
**Assessment:** Flaky test, not related to this PR. Passed on previous run.
|
|
147
|
+
**Action:** Re-run or ignore.
|
|
148
|
+
|
|
149
|
+
---
|
|
150
|
+
|
|
151
|
+
> **Recommended:** Fix items 1-3 (must fix) and item 4 (should fix).
|
|
152
|
+
> Skip items 5-6. I'll reply to item 5 explaining it's deferred and re-run CI for item 6.
|
|
153
|
+
>
|
|
154
|
+
> Proceed?
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
**Wait for the user to confirm** which items to fix and which to skip.
|
|
158
|
+
|
|
159
|
+
## Phase 3: Apply Fixes
|
|
160
|
+
|
|
161
|
+
For each approved fix:
|
|
162
|
+
|
|
163
|
+
1. **Read the file** at the referenced line.
|
|
164
|
+
|
|
165
|
+
2. **Make the fix.** Follow the same rules as `/go`:
|
|
166
|
+
- Match existing code patterns
|
|
167
|
+
- Minimal change — fix the issue, don't refactor surrounding code
|
|
168
|
+
- Run the linter after changes
|
|
169
|
+
|
|
170
|
+
3. **Verify the fix** — re-run the check that flagged it:
|
|
171
|
+
- If it was a typecheck error → `pnpm typecheck`
|
|
172
|
+
- If it was a logic bug → check the behavior
|
|
173
|
+
- If it was a style issue → `pnpm check`
|
|
174
|
+
|
|
175
|
+
4. **Commit.** Group related fixes into logical commits:
|
|
176
|
+
- One commit for all "must fix" code fixes: `fix(<scope>): address review — <summary>`
|
|
177
|
+
- Separate commit if a fix is substantial enough to stand alone
|
|
178
|
+
- Do not amend previous commits — always create new ones
|
|
179
|
+
|
|
180
|
+
## Phase 4: Respond to Comments
|
|
181
|
+
|
|
182
|
+
For items marked WON'T FIX or FALSE POSITIVE, draft reply comments:
|
|
183
|
+
|
|
184
|
+
```markdown
|
|
185
|
+
### Suggested Replies
|
|
186
|
+
|
|
187
|
+
**Comment #5** (@sarah — refundRequestedAt timestamp):
|
|
188
|
+
> Good idea — we've deferred this to a follow-up. Tracked in [bead/issue reference].
|
|
189
|
+
|
|
190
|
+
**Comment #6** (CI: e2e-tests):
|
|
191
|
+
> Flaky test unrelated to this PR — `auth/login.spec.ts` timed out. Re-running CI.
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
Ask the user before posting:
|
|
195
|
+
> Want me to post these replies on the PR?
|
|
196
|
+
|
|
197
|
+
If yes:
|
|
198
|
+
```bash
|
|
199
|
+
gh api repos/{owner}/{repo}/pulls/{number}/comments/{id}/replies -f body="<reply>"
|
|
200
|
+
# or for general comments:
|
|
201
|
+
gh pr comment {number} --body "<reply>"
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
## Phase 5: Push and Report
|
|
205
|
+
|
|
206
|
+
1. **Push fixes:**
|
|
207
|
+
```bash
|
|
208
|
+
git push
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
2. **Re-run failed CI** if applicable:
|
|
212
|
+
```bash
|
|
213
|
+
gh run rerun {run-id} --failed
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
3. **Report:**
|
|
217
|
+
```markdown
|
|
218
|
+
## Fix Summary
|
|
219
|
+
|
|
220
|
+
### Applied (N)
|
|
221
|
+
- Fixed empty string validation in payments route
|
|
222
|
+
- Fixed type error in admin page
|
|
223
|
+
- Added nullable default for migration
|
|
224
|
+
- Added color variants to RefundReasonBadge
|
|
225
|
+
|
|
226
|
+
### Replied (N)
|
|
227
|
+
- Acknowledged deferred timestamp feature
|
|
228
|
+
- Re-running flaky CI
|
|
229
|
+
|
|
230
|
+
### Skipped (N)
|
|
231
|
+
- (none)
|
|
232
|
+
|
|
233
|
+
Pushed to branch. CI re-running.
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
---
|
|
237
|
+
|
|
238
|
+
## What This Skill Does NOT Do
|
|
239
|
+
|
|
240
|
+
- **Does not auto-fix without user approval.** The triage is always presented first.
|
|
241
|
+
- **Does not argue with reviewers.** WON'T FIX replies are respectful acknowledgments, not rebuttals.
|
|
242
|
+
- **Does not refactor beyond the fix.** Fix the comment, not the surrounding code.
|
|
243
|
+
- **Does not merge the PR.** That's still a human decision.
|
|
244
|
+
- **Does not dismiss reviews.** Even after fixing, the reviewer re-approves manually.
|