bug_record.py
4.73 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).
**skill_defect + skill_iteration_suggestion (resolved 2026-07-31, U-018)**:
03-C §3.10 says root_cause_category=skill_defect "必须同时创建
skill_iteration_suggestion", but skill_iteration.before/after_git_commit_sha
are NOT NULL and can't be populated until an actual skill rewrite happens --
that's c_skill_update (src/skill_update.py), a later, separate step per
04-P §4.3's own transition table (bug_recorded is reached by this function
alone; skill_iteration_triggered -> c_skill_update is a *subsequent*
transition). So `skill_defect` is accepted here with
skill_iteration_suggestion_id left null; src/skill_update.py's
update_skill() fills it in once the iteration actually exists. See that
module's docstring for the full reasoning -- this was originally deferred
as an unenforced gap when U-015 was built (U-018 didn't exist yet to close
the loop) and has since been resolved, not left open.
"""
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()