Compare commits
1 Commits
472e6850fe
...
0bbbca4223
| Author | SHA1 | Date | |
|---|---|---|---|
| 0bbbca4223 |
@@ -227,7 +227,7 @@ tied to an issue number so the work is traceable end to end:
|
|||||||
| Issue | `#123` (claimed with `status:in-progress`) |
|
| Issue | `#123` (claimed with `status:in-progress`) |
|
||||||
| Branch | `(fix\|feat\|docs\|chore)/issue-123-<slug>` (review: `review/pr-456-<slug>`) |
|
| Branch | `(fix\|feat\|docs\|chore)/issue-123-<slug>` (review: `review/pr-456-<slug>`) |
|
||||||
| Worktree | `branches/fix-issue-123-<slug>` (slashes → hyphens) |
|
| Worktree | `branches/fix-issue-123-<slug>` (slashes → hyphens) |
|
||||||
| PR | body says `Closes #123` (closes) or `Refs #123` (related) |
|
| PR | body says `Closes #123` or `Fixes #123` (closes issue); `Implements #123` or `Refs #123` (does NOT close) |
|
||||||
| Cleanup | remove remote+local branch + worktree folder; drop `status:in-progress` |
|
| Cleanup | remove remote+local branch + worktree folder; drop `status:in-progress` |
|
||||||
|
|
||||||
`scripts/worktree-start` **rejects** implementation branches that are not
|
`scripts/worktree-start` **rejects** implementation branches that are not
|
||||||
|
|||||||
+1
-1
@@ -53,7 +53,7 @@ mcp = FastMCP("gitea-tools", instructions=(
|
|||||||
def extract_linked_issue_numbers(text: str | None, branch_name: str | None = None) -> list[int]:
|
def extract_linked_issue_numbers(text: str | None, branch_name: str | None = None) -> list[int]:
|
||||||
issues = set()
|
issues = set()
|
||||||
if text:
|
if text:
|
||||||
pattern = re.compile(r'(?i)(?:close[sd]?|fix(?:e[sd])?|resolve[sd]?|ref[s]?)\s+#(\d+)')
|
pattern = re.compile(r'(?i)(?:close[sd]?|fix(?:e[sd])?|resolve[sd]?|implement[s]?|implemented)\s+#(\d+)')
|
||||||
issues.update(int(m) for m in pattern.findall(text))
|
issues.update(int(m) for m in pattern.findall(text))
|
||||||
if branch_name:
|
if branch_name:
|
||||||
pattern = re.compile(r'(?i)issue-(\d+)')
|
pattern = re.compile(r'(?i)issue-(\d+)')
|
||||||
|
|||||||
@@ -90,8 +90,8 @@ is maintained by:
|
|||||||
- the branch name (contains the issue number),
|
- the branch name (contains the issue number),
|
||||||
- a claim comment on the issue, e.g.
|
- a claim comment on the issue, e.g.
|
||||||
`Claimed. Branch: fix/issue-123-short-description. Worktree: branches/fix-issue-123-short-description.`,
|
`Claimed. Branch: fix/issue-123-short-description. Worktree: branches/fix-issue-123-short-description.`,
|
||||||
- the PR body — `Closes #123` when the PR should close the issue, `Refs #123`
|
- the PR body — `Closes #123` or `Fixes #123` when the PR should close the issue
|
||||||
when related but not closing,
|
(do NOT use `Implements #123` or `Refs #123` to close, as Gitea will not auto-close),
|
||||||
- cleanup after merge — remove the remote branch, local branch, and the issue
|
- cleanup after merge — remove the remote branch, local branch, and the issue
|
||||||
worktree folder, and drop `status:in-progress`.
|
worktree folder, and drop `status:in-progress`.
|
||||||
|
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ Steps:
|
|||||||
- Target task role: merger identity (must NOT be the PR author)
|
- Target task role: merger identity (must NOT be the PR author)
|
||||||
*If the current identity does not match the required role (or is the PR author), STOP. Relaunch/switch to the correct profile first.*
|
*If the current identity does not match the required role (or is the PR author), STOP. Relaunch/switch to the correct profile first.*
|
||||||
2. Verify authenticated identity + active profile.
|
2. Verify authenticated identity + active profile.
|
||||||
3. Confirm PR #<pr>: author (not you), state open, mergeable, review approved.
|
3. Confirm PR #<pr>: author (not you), state open, mergeable, review approved. Check if PR body uses `Closes #N` or `Fixes #N`; if it uses `Implements #N` or `Refs #N`, manual closing will be needed in step 29.
|
||||||
4. If any gate fails → STOP and report.
|
4. If any gate fails → STOP and report.
|
||||||
4. Merge with explicit confirmation (e.g. confirmation="MERGE PR <pr>"),
|
4. Merge with explicit confirmation (e.g. confirmation="MERGE PR <pr>"),
|
||||||
optionally pinning the reviewed head SHA / changed-file set.
|
optionally pinning the reviewed head SHA / changed-file set.
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ Steps:
|
|||||||
4. scripts/worktree-review <pr-head-branch> # detached, branches/review-*
|
4. scripts/worktree-review <pr-head-branch> # detached, branches/review-*
|
||||||
cd branches/review-<pr-head-branch-slug>
|
cd branches/review-<pr-head-branch-slug>
|
||||||
5. Confirm the worktree is clean. Inspect the FULL diff; confirm scope matches
|
5. Confirm the worktree is clean. Inspect the FULL diff; confirm scope matches
|
||||||
issue #<n>; flag any unrelated files, secrets, or formatting churn.
|
issue #<n>; flag any unrelated files, secrets, or formatting churn. Check that the PR body correctly uses Gitea-closing keywords (`Closes #N` or `Fixes #N`) instead of non-closing ones (`Implements #N`, `Refs #N`).
|
||||||
6. Run the test suite; note results.
|
6. Run the test suite; note results.
|
||||||
7. Post the review verdict: approve only if scope is clean and checks pass;
|
7. Post the review verdict: approve only if scope is clean and checks pass;
|
||||||
otherwise request changes with specifics. Never merge from this review step.
|
otherwise request changes with specifics. Never merge from this review step.
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ Steps:
|
|||||||
6. Checks: run the test suite, compile/lint changed files, git diff --check,
|
6. Checks: run the test suite, compile/lint changed files, git diff --check,
|
||||||
and scan the diff for secrets.
|
and scan the diff for secrets.
|
||||||
7. Commit (issue-linked message), push the branch, open a PR to master.
|
7. Commit (issue-linked message), push the branch, open a PR to master.
|
||||||
|
*The PR body MUST use closing keywords like `Closes #N` or `Fixes #N` to close the issue; do NOT use `Implements #N` or `Refs #N` for closing, as Gitea will not auto-close it.*
|
||||||
Include an "LLM Handoff Metadata" block in the PR body (attribution only;
|
Include an "LLM Handoff Metadata" block in the PR body (attribution only;
|
||||||
never an eligibility input — docs/llm-agent-sha.md):
|
never an eligibility input — docs/llm-agent-sha.md):
|
||||||
|
|
||||||
|
|||||||
@@ -1649,3 +1649,23 @@ class TestTrackerHygieneCleanup(unittest.TestCase):
|
|||||||
res = gitea_close_issue(issue_number=1)
|
res = gitea_close_issue(issue_number=1)
|
||||||
self.assertTrue(res["success"])
|
self.assertTrue(res["success"])
|
||||||
self.assertIn("error:", res["cleanup_status"].get(1))
|
self.assertIn("error:", res["cleanup_status"].get(1))
|
||||||
|
|
||||||
|
def test_extract_linked_issue_numbers_hygiene(self):
|
||||||
|
from mcp_server import extract_linked_issue_numbers
|
||||||
|
# Standard closing keywords
|
||||||
|
self.assertEqual(extract_linked_issue_numbers("Closes #123"), [123])
|
||||||
|
self.assertEqual(extract_linked_issue_numbers("Fixes #123"), [123])
|
||||||
|
self.assertEqual(extract_linked_issue_numbers("Resolves #123"), [123])
|
||||||
|
|
||||||
|
# New implements/implemented keywords
|
||||||
|
self.assertEqual(extract_linked_issue_numbers("Implements #123"), [123])
|
||||||
|
self.assertEqual(extract_linked_issue_numbers("implemented #123"), [123])
|
||||||
|
self.assertEqual(extract_linked_issue_numbers("implement #123"), [123])
|
||||||
|
|
||||||
|
# refs / ref should NOT match
|
||||||
|
self.assertEqual(extract_linked_issue_numbers("Refs #123"), [])
|
||||||
|
self.assertEqual(extract_linked_issue_numbers("ref #123"), [])
|
||||||
|
|
||||||
|
# branch name fallback
|
||||||
|
self.assertEqual(extract_linked_issue_numbers("", branch_name="issue-123"), [123])
|
||||||
|
self.assertEqual(extract_linked_issue_numbers("", branch_name="feat/issue-123-foo"), [123])
|
||||||
|
|||||||
Reference in New Issue
Block a user