feat: block vague-reference issue creation with content preflight (Closes #582) #586

Merged
sysadmin merged 1 commits from feat/issue-582-issue-content-preflight into master 2026-07-09 13:20:03 -05:00
Owner

Summary

Adds a pre-create content gate to gitea_create_issue that fails closed with BLOCKED + DIAGNOSE when an issue's title/body is a vague placeholder reference to out-of-band draft content — "the drafted issue", "the prepared issue", "the issue we discussed", "the previous draft" — and no durable source pointer is present. Implements the #582 rule that an LLM must never fabricate issue content from stale chat memory.

Closes #582

Changes

  • issue_content_gate.py (new): assess_issue_content / pre_create_issue_content_gate.
    • Vague-phrase detection over a normalized field.
    • Durable-source-pointer escape hatch (existing issue/PR #582, comment 8155, checked-in file path, URL, scratchpad path) — a pointer means the content is retrievable, so it is allowed.
    • Domination check so long, specific bodies that merely mention a phrase in passing are not falsely blocked.
  • gitea_mcp_server.py: runs the gate after preflight purity, before duplicate search; returns BLOCKED + DIAGNOSE naming the exact vague/missing fields. New allow_incomplete_content operator override (off by default). Empty body is NOT required — explicit title-only creation stays allowed, so existing callers keep working.
  • tests/test_issue_content_gate.py (new): unit coverage for normalization, pointer detection, vague detection, and the assessment; MCP integration proving a vague prompt blocks without any API call, concrete content creates, and the override creates.
  • create-issue.md: new §14a documenting the enforced preflight with valid/invalid prompt examples.

Acceptance criteria mapping (#582)

  • Preflight check for vague/missing issue content → issue_content_gate wired into gitea_create_issue.
  • Returns BLOCKED + DIAGNOSE with exact fields when content is unavailable → block path lists missing_fields / vague_fields and a diagnose string.
  • Never fabricates from stale chat memory → vague-phrase blocklist, no durable pointer ⇒ block.
  • Valid short prompts pointing at durable sources → allowed via pointer escape hatch (documented + tested).
  • Invalid vague prompts → blocked (documented + tested).

Validation

tests/test_issue_content_gate.py and tests/test_llm_workflow_split.py pass (63 passed) against the branch. py_compile clean.

Note: tests/test_mcp_server.py::TestMergePR::test_unknown_profile_blocks fails on this branch AND on unmodified master (reproduces with that file alone) — a pre-existing intra-file global-state leak in the review-mutation ledger (#332), untouched by this change. Diagnosed for separate tracking; not introduced here.

## Summary Adds a pre-create content gate to `gitea_create_issue` that fails closed with `BLOCKED + DIAGNOSE` when an issue's title/body is a vague placeholder reference to out-of-band draft content — "the drafted issue", "the prepared issue", "the issue we discussed", "the previous draft" — and no durable source pointer is present. Implements the #582 rule that an LLM must never fabricate issue content from stale chat memory. Closes #582 ## Changes - **`issue_content_gate.py`** (new): `assess_issue_content` / `pre_create_issue_content_gate`. - Vague-phrase detection over a normalized field. - Durable-source-pointer escape hatch (existing issue/PR `#582`, `comment 8155`, checked-in file path, URL, scratchpad path) — a pointer means the content is retrievable, so it is allowed. - Domination check so long, specific bodies that merely mention a phrase in passing are not falsely blocked. - **`gitea_mcp_server.py`**: runs the gate after preflight purity, before duplicate search; returns `BLOCKED + DIAGNOSE` naming the exact vague/missing fields. New `allow_incomplete_content` operator override (off by default). Empty body is NOT required — explicit title-only creation stays allowed, so existing callers keep working. - **`tests/test_issue_content_gate.py`** (new): unit coverage for normalization, pointer detection, vague detection, and the assessment; MCP integration proving a vague prompt blocks without any API call, concrete content creates, and the override creates. - **`create-issue.md`**: new §14a documenting the enforced preflight with valid/invalid prompt examples. ## Acceptance criteria mapping (#582) - Preflight check for vague/missing issue content → `issue_content_gate` wired into `gitea_create_issue`. - Returns `BLOCKED + DIAGNOSE` with exact fields when content is unavailable → block path lists `missing_fields` / `vague_fields` and a diagnose string. - Never fabricates from stale chat memory → vague-phrase blocklist, no durable pointer ⇒ block. - Valid short prompts pointing at durable sources → allowed via pointer escape hatch (documented + tested). - Invalid vague prompts → blocked (documented + tested). ## Validation `tests/test_issue_content_gate.py` and `tests/test_llm_workflow_split.py` pass (63 passed) against the branch. `py_compile` clean. Note: `tests/test_mcp_server.py::TestMergePR::test_unknown_profile_blocks` fails on this branch AND on unmodified master (reproduces with that file alone) — a pre-existing intra-file global-state leak in the review-mutation ledger (#332), untouched by this change. Diagnosed for separate tracking; not introduced here.
jcwalker3 added 1 commit 2026-07-09 12:09:45 -05:00
Add a pre-create content gate to gitea_create_issue that fails closed with
BLOCKED + DIAGNOSE when the title/body is a vague reference to out-of-band
draft content ("the drafted issue", "the prepared issue", "the issue we
discussed", "the previous draft") and no durable source pointer (existing
issue/PR/comment, checked-in file, URL, or scratchpad path) is present.

- issue_content_gate.py: assess_issue_content / pre_create_issue_content_gate
  with vague-phrase detection, durable-source-pointer escape hatch, and a
  domination check so long specific bodies are not falsely blocked.
- gitea_create_issue: runs the gate after preflight purity, before duplicate
  search; new allow_incomplete_content override (off by default). Title-only
  creation stays allowed (no empty-body requirement) to preserve behavior.
- tests/test_issue_content_gate.py: unit + MCP integration coverage.
- create-issue.md: documents the enforced preflight with valid/invalid
  prompt examples.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Owner

repo: Scaled-Tech-Consulting/Gitea-Tools
pr: #586
issue: #582
reviewer_identity: sysadmin
profile: prgs-reviewer
session_id: 55582-e2f5256acef3
worktree: /Users/jasonwalker/Development/Gitea-Tools/branches/review-pr-586-issue-582
phase: claimed
candidate_head: 5debfcf178
target_branch: master
target_branch_sha: none
last_activity: 2026-07-09T18:06:00Z
expires_at: 2026-07-09T20:06:00Z
blocker: none

<!-- mcp-review-lease:v1 --> repo: Scaled-Tech-Consulting/Gitea-Tools pr: #586 issue: #582 reviewer_identity: sysadmin profile: prgs-reviewer session_id: 55582-e2f5256acef3 worktree: /Users/jasonwalker/Development/Gitea-Tools/branches/review-pr-586-issue-582 phase: claimed candidate_head: 5debfcf17841f03a2df51189de062561cd3b1cc5 target_branch: master target_branch_sha: none last_activity: 2026-07-09T18:06:00Z expires_at: 2026-07-09T20:06:00Z blocker: none
sysadmin approved these changes 2026-07-09 13:06:51 -05:00
sysadmin left a comment
Owner

Canonical PR State

STATE: approved
WHO_IS_NEXT: merger
NEXT_ACTION: merge PR #586 at expected head 5debfcf178 after explicit operator authorization
NEXT_PROMPT:

Use prgs-merger. MERGE PR 586 only with explicit operator authorization. Expected head SHA 5debfcf17841f03a2df51189de062561cd3b1cc5. Adopt reviewer lease if needed, then gitea_merge_pr. Linked issue #582.

WHAT_HAPPENED: Reviewed PR #586 for Issue #582. Adds issue_content_gate pre-create fail-closed for vague draft references without durable source pointers; wires into gitea_create_issue with BLOCKED+DIAGNOSE; docs §14a; tests pass. APPROVE at pinned head.
WHY: LLMs must not fabricate issues from stale chat memory; gate enforces durable content or source pointer with operator override only.
ISSUE: #582
HEAD_SHA: 5debfcf178
REVIEW_STATUS: approved
MERGE_READY: yes
BLOCKERS: none
VALIDATION: pytest tests/test_issue_content_gate.py tests/test_llm_workflow_split.py -q -> 63 passed (6 subtests); worktree branches/review-pr-586-issue-582
LAST_UPDATED_BY: sysadmin (prgs-reviewer)

Review findings

  • New issue_content_gate.py: vague-phrase + domination check; durable pointers (#N, comment, URL, file, scratchpad)
  • Empty body still allowed (title-only); only placeholder references blocked
  • allow_incomplete_content operator override (default off)
  • create-issue.md §14a documents valid/invalid prompts
  • Author jcwalker3; reviewer sysadmin — not self-review
  • Note: pre-existing master test_unknown_profile_blocks leak tracked separately as #590; not introduced here
## Canonical PR State STATE: approved WHO_IS_NEXT: merger NEXT_ACTION: merge PR #586 at expected head 5debfcf17841f03a2df51189de062561cd3b1cc5 after explicit operator authorization NEXT_PROMPT: ```text Use prgs-merger. MERGE PR 586 only with explicit operator authorization. Expected head SHA 5debfcf17841f03a2df51189de062561cd3b1cc5. Adopt reviewer lease if needed, then gitea_merge_pr. Linked issue #582. ``` WHAT_HAPPENED: Reviewed PR #586 for Issue #582. Adds issue_content_gate pre-create fail-closed for vague draft references without durable source pointers; wires into gitea_create_issue with BLOCKED+DIAGNOSE; docs §14a; tests pass. APPROVE at pinned head. WHY: LLMs must not fabricate issues from stale chat memory; gate enforces durable content or source pointer with operator override only. ISSUE: #582 HEAD_SHA: 5debfcf17841f03a2df51189de062561cd3b1cc5 REVIEW_STATUS: approved MERGE_READY: yes BLOCKERS: none VALIDATION: pytest tests/test_issue_content_gate.py tests/test_llm_workflow_split.py -q -> 63 passed (6 subtests); worktree branches/review-pr-586-issue-582 LAST_UPDATED_BY: sysadmin (prgs-reviewer) ### Review findings - New issue_content_gate.py: vague-phrase + domination check; durable pointers (#N, comment, URL, file, scratchpad) - Empty body still allowed (title-only); only placeholder references blocked - allow_incomplete_content operator override (default off) - create-issue.md §14a documents valid/invalid prompts - Author jcwalker3; reviewer sysadmin — not self-review - Note: pre-existing master test_unknown_profile_blocks leak tracked separately as #590; not introduced here
Owner

adopted_at: 2026-07-09T18:19:02Z
adopted_by_identity: sysadmin
adopted_by_profile: prgs-merger
adopted_from_session_id: 55582-e2f5256acef3
adopted_from_profile: prgs-reviewer
adopted_from_reviewer_identity: sysadmin
adopted_from_comment_id: 8408
adoption_reason: merger-handoff-approved-head

repo: Scaled-Tech-Consulting/Gitea-Tools
pr: #586
issue: #582
reviewer_identity: sysadmin
profile: prgs-merger
session_id: 4927-7c2ab1af97cc
worktree: /Users/jasonwalker/Development/Gitea-Tools/branches/merge-pr-586
phase: adopted
candidate_head: 5debfcf178
target_branch: master
target_branch_sha: none
last_activity: 2026-07-09T18:19:02Z
expires_at: 2026-07-09T20:19:02Z
blocker: none

<!-- mcp-review-lease-adoption:v1 --> adopted_at: 2026-07-09T18:19:02Z adopted_by_identity: sysadmin adopted_by_profile: prgs-merger adopted_from_session_id: 55582-e2f5256acef3 adopted_from_profile: prgs-reviewer adopted_from_reviewer_identity: sysadmin adopted_from_comment_id: 8408 adoption_reason: merger-handoff-approved-head <!-- mcp-review-lease:v1 --> repo: Scaled-Tech-Consulting/Gitea-Tools pr: #586 issue: #582 reviewer_identity: sysadmin profile: prgs-merger session_id: 4927-7c2ab1af97cc worktree: /Users/jasonwalker/Development/Gitea-Tools/branches/merge-pr-586 phase: adopted candidate_head: 5debfcf17841f03a2df51189de062561cd3b1cc5 target_branch: master target_branch_sha: none last_activity: 2026-07-09T18:19:02Z expires_at: 2026-07-09T20:19:02Z blocker: none
sysadmin merged commit 6913ac98f1 into master 2026-07-09 13:20:03 -05:00
Owner

repo: Scaled-Tech-Consulting/Gitea-Tools
pr: #586
issue: #582
reviewer_identity: sysadmin
profile: prgs-merger
session_id: 4927-7c2ab1af97cc
worktree: /Users/jasonwalker/Development/Gitea-Tools/branches/merge-pr-586
phase: released
candidate_head: 5debfcf178
target_branch: master
target_branch_sha: none
last_activity: 2026-07-09T18:25:18Z
expires_at: 2026-07-09T20:25:18Z
blocker: post-merge-moot

<!-- mcp-review-lease:v1 --> repo: Scaled-Tech-Consulting/Gitea-Tools pr: #586 issue: #582 reviewer_identity: sysadmin profile: prgs-merger session_id: 4927-7c2ab1af97cc worktree: /Users/jasonwalker/Development/Gitea-Tools/branches/merge-pr-586 phase: released candidate_head: 5debfcf17841f03a2df51189de062561cd3b1cc5 target_branch: master target_branch_sha: none last_activity: 2026-07-09T18:25:18Z expires_at: 2026-07-09T20:25:18Z blocker: post-merge-moot
Sign in to join this conversation.
No Reviewers
No labels
2 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: Scaled-Tech-Consulting/Gitea-Tools#586