bug_record.py
4.75 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
"""c_bug_record_create (03-C §3.10): finalizes a Validator-judged bug.
Distinct from c_bug_report_create (03-C §3.1.1, human-submitted feedback with
no root cause yet -- owned by U-023, not this Unit): this controller's
input_contract requires root_cause_category/root_cause_detail/suggested_route
all as required fields, i.e. it's the "record a bug the Validator has already
judged" endpoint, called at the end of p_validator_root_cause_trace's
judging_root_cause -> bug_recorded transition (04-P §4.3).
**Known gap, deliberately unenforced (2026-07-31)**: 03-C §3.10's own text
says "root_cause_category=skill_defect 时必须同时创建 skill_iteration_suggestion,
否则视为字段缺失" -- but 01-M's skill_iteration entity requires
before_git_commit_sha/after_git_commit_sha NOT NULL, fields that can't be
populated until an actual skill rewrite happens (c_skill_update, U-018), which
hasn't occurred yet at bug-creation time. The SDD doesn't define what a
"suggestion" (pre-rewrite) is distinct from an "iteration" (post-rewrite), or
how skill_iteration's NOT NULL commit-sha fields would be satisfied before
one exists. Not guessed at here: REQ-04's own three acceptance cases (06 节)
never exercise root_cause_category=skill_defect, so nothing in this Unit's
actual Done criterion needs this resolved. Left for U-018 (c_skill_update,
the Unit that actually creates skill_iteration rows) to resolve when it's
in scope.
"""
import json
import uuid
# core_engine deliberately excluded -- see src/schema.py's matching CHECK
# constraint and its own comment: PH5-scoped (U-034), not accepted until then.
_VALID_ROOT_CAUSE_CATEGORIES = ("planning", "coder", "skill_defect")
class InvalidRootCauseCategoryError(Exception):
"""INVALID_ROOT_CAUSE_CATEGORY -- 03-C §3.10."""
def create_bug_record(
conn, task_id, description, root_cause_category, root_cause_detail, suggested_route,
repro_steps=None, related_artifact_ids=None, skill_iteration_suggestion_id=None,
):
"""Creates a bug_record(source='validator', status='routed') -- 'routed'
because by the time this is called, triage (root cause + suggested_route)
is already complete; there's no separate triaging step for this origin
(that's the human_reported branch's job, see claim_human_reported_bug /
complete_human_reported_triage below)."""
if root_cause_category not in _VALID_ROOT_CAUSE_CATEGORIES:
raise InvalidRootCauseCategoryError(
"root_cause_category must be one of {}, got {!r}".format(
_VALID_ROOT_CAUSE_CATEGORIES, root_cause_category
)
)
bug_id = str(uuid.uuid4())
conn.execute(
"INSERT INTO bug_record "
"(bug_id, task_id, source, description, repro_steps, root_cause_category, root_cause_detail, "
"related_artifact_ids, suggested_route, skill_iteration_suggestion_id, status) "
"VALUES (?, ?, 'validator', ?, ?, ?, ?, ?, ?, ?, 'routed')",
(
bug_id, task_id, description, repro_steps, root_cause_category, root_cause_detail,
json.dumps(related_artifact_ids) if related_artifact_ids else None,
suggested_route, skill_iteration_suggestion_id,
),
)
conn.commit()
return {"bug_id": bug_id}
def claim_human_reported_bug(conn, bug_id):
"""04-P §4.3: human_reported -> tracing_lineage. Validator claims an
open, source=human bug_record. status: open -> triaging."""
row = conn.execute("SELECT source, status FROM bug_record WHERE bug_id = ?", (bug_id,)).fetchone()
if row is None:
raise ValueError("no such bug_record: " + bug_id)
source, status = row
if source != "human" or status != "open":
raise ValueError(
"bug_record {} is not claimable (source={}, status={}); expected source=human, status=open".format(
bug_id, source, status
)
)
conn.execute("UPDATE bug_record SET status = 'triaging' WHERE bug_id = ?", (bug_id,))
conn.commit()
def complete_human_reported_triage(conn, bug_id, root_cause_category, root_cause_detail, suggested_route):
"""04-P §4.3 补充说明: human_reported 起点的 judging_root_cause->bug_recorded
是对已存在 bug_record 的字段补全式更新,不产生重复记录 -- status: triaging->routed."""
if root_cause_category not in _VALID_ROOT_CAUSE_CATEGORIES:
raise InvalidRootCauseCategoryError(
"root_cause_category must be one of {}, got {!r}".format(
_VALID_ROOT_CAUSE_CATEGORIES, root_cause_category
)
)
conn.execute(
"UPDATE bug_record SET root_cause_category = ?, root_cause_detail = ?, suggested_route = ?, "
"status = 'routed' WHERE bug_id = ?",
(root_cause_category, root_cause_detail, suggested_route, bug_id),
)
conn.commit()