@oswaldzsh/devhive 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.
Files changed (46) hide show
  1. package/README.md +91 -0
  2. package/__init__.py +0 -0
  3. package/agents/__init__.py +0 -0
  4. package/agents/base.py +118 -0
  5. package/agents/execute.py +150 -0
  6. package/agents/verifier_dynamic.py +164 -0
  7. package/agents/verifier_semantic.py +84 -0
  8. package/agents/verifier_static.py +153 -0
  9. package/bin/dh +77 -0
  10. package/config.yaml +71 -0
  11. package/control_plane/__init__.py +0 -0
  12. package/control_plane/cli.py +596 -0
  13. package/control_plane/dashboard.py +57 -0
  14. package/control_plane/notifications.py +54 -0
  15. package/control_plane/tui.py +352 -0
  16. package/install.sh +67 -0
  17. package/orchestrator/__init__.py +0 -0
  18. package/orchestrator/agent_pool.py +107 -0
  19. package/orchestrator/convergence_gate.py +133 -0
  20. package/orchestrator/engine.py +353 -0
  21. package/orchestrator/event_bus.py +58 -0
  22. package/orchestrator/task_queue.py +59 -0
  23. package/package.json +50 -0
  24. package/protocol/__init__.py +0 -0
  25. package/protocol/schemas.py +222 -0
  26. package/setup.py +44 -0
  27. package/signature/__init__.py +0 -0
  28. package/signature/engine.py +211 -0
  29. package/signature/extractor.py +156 -0
  30. package/signature/learner.py +75 -0
  31. package/signature/src/matcher.c +263 -0
  32. package/signature/src/matcher.h +135 -0
  33. package/signatures/seed_signatures.json +174 -0
  34. package/storage/__init__.py +0 -0
  35. package/storage/checkpoint.py +153 -0
  36. package/storage/signature_db.py +62 -0
  37. package/tools/__init__.py +0 -0
  38. package/tools/api_client.py +101 -0
  39. package/tools/git.py +75 -0
  40. package/tools/sandbox.py +79 -0
  41. package/verification/__init__.py +0 -0
  42. package/verification/diagnostic.py +124 -0
  43. package/verification/patterns/api_breaking.yaml +25 -0
  44. package/verification/patterns/code_quality.yaml +41 -0
  45. package/verification/patterns/security.yaml +41 -0
  46. package/verification/pipeline.py +61 -0
@@ -0,0 +1,75 @@
1
+ """Signature learner — automatically extracts new signatures from resolved escalations."""
2
+
3
+ import json
4
+ import hashlib
5
+ from datetime import datetime, timezone
6
+ from typing import Optional
7
+
8
+
9
+ class SignatureLearner:
10
+ """Creates new signatures from resolved human interventions."""
11
+
12
+ def __init__(self, signature_db, extractor=None):
13
+ self.db = signature_db
14
+ self.extractor = extractor
15
+
16
+ def learn_from_escalation(
17
+ self,
18
+ task_id: str,
19
+ error_output: str,
20
+ changed_files: list[str],
21
+ root_cause: str,
22
+ root_cause_category: str,
23
+ fix_strategy: str,
24
+ fix_template: str,
25
+ verification_required: list[str] = None,
26
+ ) -> str:
27
+ """Create a new signature from a resolved escalation.
28
+
29
+ Returns the new signature_id.
30
+ """
31
+ from signature.extractor import extract_feature_vector
32
+
33
+ fv_data = extract_feature_vector(error_output, changed_files)
34
+ fv = fv_data["feature_vector"]
35
+
36
+ sig_id = f"sig-{hashlib.sha256(error_output.encode()).hexdigest()[:10]}"
37
+
38
+ signature = {
39
+ "signature_id": sig_id,
40
+ "created_at": datetime.now(timezone.utc).replace(tzinfo=None).isoformat(),
41
+ "last_matched": datetime.now(timezone.utc).replace(tzinfo=None).isoformat(),
42
+ "match_count": 0,
43
+ "feature_vector": fv,
44
+ "diagnosis": {
45
+ "root_cause": root_cause,
46
+ "root_cause_category": root_cause_category,
47
+ "reliability": 0.5, # Starts low, increases with successful matches
48
+ },
49
+ "resolution": {
50
+ "strategy": fix_strategy,
51
+ "fix_template": fix_template,
52
+ "verification_required": verification_required or [],
53
+ },
54
+ "source_task": task_id,
55
+ }
56
+
57
+ self.db.add(signature)
58
+ return sig_id
59
+
60
+ def reinforce(self, sig_id: str, success: bool = True):
61
+ """Update signature reliability based on match outcome."""
62
+ sig = self.db.get(sig_id)
63
+ if not sig:
64
+ return
65
+
66
+ diag = sig.get("diagnosis", {})
67
+ current = diag.get("reliability", 0.5)
68
+
69
+ if success:
70
+ diag["reliability"] = min(1.0, current + 0.05)
71
+ else:
72
+ diag["reliability"] = max(0.1, current - 0.1)
73
+
74
+ sig["diagnosis"] = diag
75
+ self.db.add(sig) # Overwrites
@@ -0,0 +1,263 @@
1
+ /*
2
+ * matcher.c — Signature Matching Engine Implementation
3
+ */
4
+
5
+ #include "matcher.h"
6
+ #include <stdlib.h>
7
+ #include <string.h>
8
+ #include <math.h>
9
+
10
+ /* ── Helpers ───────────────────────────────────────────────── */
11
+
12
+ static int min_int(int a, int b) { return a < b ? a : b; }
13
+
14
+ /* Jaccard similarity for two sets of uint64 hashes */
15
+ static double jaccard_hashes(const uint64_t *a, int a_len,
16
+ const uint64_t *b, int b_len) {
17
+ if (a_len == 0 && b_len == 0) return 1.0;
18
+ if (a_len == 0 || b_len == 0) return 0.0;
19
+
20
+ int intersection = 0;
21
+ for (int i = 0; i < a_len; i++) {
22
+ if (a[i] == 0) continue;
23
+ for (int j = 0; j < b_len; j++) {
24
+ if (a[i] == b[j]) {
25
+ intersection++;
26
+ break;
27
+ }
28
+ }
29
+ }
30
+ int union_size = a_len + b_len - intersection;
31
+ return union_size > 0 ? (double)intersection / union_size : 0.0;
32
+ }
33
+
34
+ /* Check if two strings share a common prefix path (e.g., same directory) */
35
+ static double location_similarity(const char *a, const char *b) {
36
+ if (strcmp(a, b) == 0) return 1.0;
37
+ if (a[0] == '\0' || b[0] == '\0') return 0.0;
38
+
39
+ /* Find the last '/' to split into dir + filename */
40
+ const char *slash_a = strrchr(a, '/');
41
+ const char *slash_b = strrchr(b, '/');
42
+
43
+ if (slash_a && slash_b) {
44
+ /* Compare directory parts */
45
+ int dir_len_a = (int)(slash_a - a);
46
+ int dir_len_b = (int)(slash_b - b);
47
+ if (dir_len_a == dir_len_b && strncmp(a, b, dir_len_a) == 0) {
48
+ /* Same directory → 0.7 */
49
+ /* Same filename → check */
50
+ if (strcmp(slash_a + 1, slash_b + 1) == 0) return 1.0;
51
+ return 0.7;
52
+ }
53
+ return 0.0;
54
+ }
55
+
56
+ return strcmp(a, b) == 0 ? 1.0 : 0.0;
57
+ }
58
+
59
+ /* ── Hash ──────────────────────────────────────────────────── */
60
+
61
+ uint64_t hash_error_message(const char *msg) {
62
+ /* FNV-1a 64-bit hash */
63
+ uint64_t hash = 14695981039346656037ULL;
64
+ if (!msg) return hash;
65
+
66
+ /* Normalize: lowercase, collapse whitespace */
67
+ char c;
68
+ int last_was_space = 0;
69
+ while ((c = *msg++)) {
70
+ /* Lowercase */
71
+ if (c >= 'A' && c <= 'Z') c += 32;
72
+ /* Collapse whitespace */
73
+ if (c == ' ' || c == '\t' || c == '\n' || c == '\r') {
74
+ if (last_was_space) continue;
75
+ c = ' ';
76
+ last_was_space = 1;
77
+ } else {
78
+ last_was_space = 0;
79
+ }
80
+ hash ^= (uint64_t)(unsigned char)c;
81
+ hash *= 1099511628211ULL;
82
+ }
83
+ return hash;
84
+ }
85
+
86
+ void extract_location_pattern(const char *file_line, char *out, int out_len) {
87
+ if (!file_line || !out || out_len <= 0) return;
88
+ out[0] = '\0';
89
+
90
+ const char *colon = strrchr(file_line, ':');
91
+ int copy_len;
92
+ if (colon) {
93
+ copy_len = min_int((int)(colon - file_line), out_len - 1);
94
+ } else {
95
+ copy_len = min_int((int)strlen(file_line), out_len - 1);
96
+ }
97
+ strncpy(out, file_line, copy_len);
98
+ out[copy_len] = '\0';
99
+ }
100
+
101
+ /* ── Database ──────────────────────────────────────────────── */
102
+
103
+ SignatureDB* db_create(int initial_capacity) {
104
+ SignatureDB *db = (SignatureDB*)calloc(1, sizeof(SignatureDB));
105
+ if (!db) return NULL;
106
+
107
+ db->capacity = initial_capacity > 0 ? initial_capacity : 256;
108
+ db->signatures = (Signature*)calloc(db->capacity, sizeof(Signature));
109
+ if (!db->signatures) {
110
+ free(db);
111
+ return NULL;
112
+ }
113
+ db->count = 0;
114
+ return db;
115
+ }
116
+
117
+ void db_destroy(SignatureDB *db) {
118
+ if (!db) return;
119
+ free(db->signatures);
120
+ free(db);
121
+ }
122
+
123
+ int db_add(SignatureDB *db, const Signature *sig) {
124
+ if (!db || !sig || db->count >= db->capacity) {
125
+ /* Attempt to grow */
126
+ if (db && db->count >= db->capacity) {
127
+ int new_cap = db->capacity * 2;
128
+ Signature *new_sigs = (Signature*)realloc(
129
+ db->signatures, new_cap * sizeof(Signature));
130
+ if (!new_sigs) return -1;
131
+ db->signatures = new_sigs;
132
+ db->capacity = new_cap;
133
+ } else {
134
+ return -1;
135
+ }
136
+ }
137
+ memcpy(&db->signatures[db->count], sig, sizeof(Signature));
138
+ db->count++;
139
+ return 0;
140
+ }
141
+
142
+ /* ── Similarity Computation ────────────────────────────────── */
143
+
144
+ double vector_similarity(const MatcherConfig *config,
145
+ const FeatureVector *a, const FeatureVector *b) {
146
+ double score = 0.0;
147
+
148
+ /* 1. Error type match (exact) */
149
+ score += config->w_error_type *
150
+ (strcmp(a->error_type, b->error_type) == 0 ? 1.0 : 0.0);
151
+
152
+ /* 2. Error message hash similarity */
153
+ score += config->w_error_message *
154
+ (a->error_message_hash == b->error_message_hash ? 1.0 :
155
+ (a->error_message_hash && b->error_message_hash ? 0.1 : 0.0));
156
+
157
+ /* 3. Location similarity */
158
+ score += config->w_location *
159
+ location_similarity(a->location_pattern, b->location_pattern);
160
+
161
+ /* 4. Stack trace similarity (Jaccard) */
162
+ score += config->w_stack_trace *
163
+ jaccard_hashes(a->stack_hashes, a->stack_depth,
164
+ b->stack_hashes, b->stack_depth);
165
+
166
+ /* 5. Change context similarity */
167
+ double ctx_sim = 0.0;
168
+ if (a->change_type == b->change_type) ctx_sim += 0.5;
169
+ if (a->distance_to_error == b->distance_to_error) ctx_sim += 0.5;
170
+ score += config->w_change_context * ctx_sim;
171
+
172
+ /* 6. Temporal bonus — if the signature was recently active */
173
+ if (b->is_new_in_diff) {
174
+ score += config->w_temporal * 0.5;
175
+ }
176
+
177
+ return score;
178
+ }
179
+
180
+ /* ── Matching ──────────────────────────────────────────────── */
181
+
182
+ static int compare_results(const void *a, const void *b) {
183
+ const MatchResult *ra = (const MatchResult *)a;
184
+ const MatchResult *rb = (const MatchResult *)b;
185
+ if (ra->similarity > rb->similarity) return -1;
186
+ if (ra->similarity < rb->similarity) return 1;
187
+ return 0;
188
+ }
189
+
190
+ int db_match(const SignatureDB *db, const MatcherConfig *config,
191
+ const FeatureVector *query,
192
+ MatchResult *results, int k) {
193
+ if (!db || !config || !query || !results || k <= 0) return 0;
194
+
195
+ int result_count = 0;
196
+
197
+ /* Linear scan with top-K tracking */
198
+ for (int i = 0; i < db->count; i++) {
199
+ double sim = vector_similarity(config, query,
200
+ &db->signatures[i].features);
201
+ if (sim < config->min_confidence) continue;
202
+
203
+ /* Insert into sorted results array */
204
+ if (result_count < k) {
205
+ /* Fill first k slots */
206
+ int pos = result_count;
207
+ while (pos > 0 && results[pos - 1].similarity < sim) {
208
+ results[pos] = results[pos - 1];
209
+ pos--;
210
+ }
211
+ memset(&results[pos], 0, sizeof(MatchResult));
212
+ strncpy(results[pos].sig_id, db->signatures[i].sig_id,
213
+ MATCHER_MAX_SIG_ID - 1);
214
+ results[pos].similarity = sim;
215
+ results[pos].reliability = db->signatures[i].reliability;
216
+ results[pos].match_count = db->signatures[i].match_count;
217
+ strncpy(results[pos].resolution_strategy,
218
+ db->signatures[i].resolution_strategy,
219
+ MATCHER_MAX_STRATEGY - 1);
220
+ strncpy(results[pos].fix_template, db->signatures[i].fix_template,
221
+ MATCHER_MAX_FIX_TEMPLATE - 1);
222
+ result_count++;
223
+ } else if (sim > results[k - 1].similarity) {
224
+ /* Replace the lowest (last) element */
225
+ int pos = k - 1;
226
+ while (pos > 0 && results[pos - 1].similarity < sim) {
227
+ results[pos] = results[pos - 1];
228
+ pos--;
229
+ }
230
+ memset(&results[pos], 0, sizeof(MatchResult));
231
+ strncpy(results[pos].sig_id, db->signatures[i].sig_id,
232
+ MATCHER_MAX_SIG_ID - 1);
233
+ results[pos].similarity = sim;
234
+ results[pos].reliability = db->signatures[i].reliability;
235
+ results[pos].match_count = db->signatures[i].match_count;
236
+ strncpy(results[pos].resolution_strategy,
237
+ db->signatures[i].resolution_strategy,
238
+ MATCHER_MAX_STRATEGY - 1);
239
+ strncpy(results[pos].fix_template, db->signatures[i].fix_template,
240
+ MATCHER_MAX_FIX_TEMPLATE - 1);
241
+ }
242
+ }
243
+
244
+ /* Ensure results are sorted descending */
245
+ qsort(results, result_count, sizeof(MatchResult), compare_results);
246
+
247
+ return result_count;
248
+ }
249
+
250
+ /* ── Default Config ────────────────────────────────────────── */
251
+
252
+ MatcherConfig config_default(void) {
253
+ MatcherConfig c;
254
+ c.w_error_type = 0.30;
255
+ c.w_error_message = 0.15;
256
+ c.w_location = 0.25;
257
+ c.w_stack_trace = 0.15;
258
+ c.w_change_context = 0.10;
259
+ c.w_temporal = 0.05;
260
+ c.min_confidence = 0.65;
261
+ c.top_k = 3;
262
+ return c;
263
+ }
@@ -0,0 +1,135 @@
1
+ /*
2
+ * matcher.h — Signature Matching Engine
3
+ *
4
+ * Multi-dimensional feature-vector similarity matching for
5
+ * failure signature identification. Designed for low-latency
6
+ * lookup (<1ms for <100K signatures) without external dependencies.
7
+ */
8
+
9
+ #ifndef MATCHER_H
10
+ #define MATCHER_H
11
+
12
+ #include <stdint.h>
13
+
14
+ /* ── Constants ─────────────────────────────────────────────── */
15
+ #define MATCHER_MAX_STACK_DEPTH 10
16
+ #define MATCHER_MAX_LOCATION_LEN 256
17
+ #define MATCHER_MAX_ERROR_TYPE 64
18
+ #define MATCHER_MAX_SIG_ID 32
19
+ #define MATCHER_MAX_STRATEGY 32
20
+ #define MATCHER_MAX_FIX_TEMPLATE 512
21
+ #define MATCHER_MAX_RESULTS 16
22
+
23
+ /* ── Enums ─────────────────────────────────────────────────── */
24
+ typedef enum {
25
+ DISTANCE_SAME_FILE = 0,
26
+ DISTANCE_SAME_MODULE = 1,
27
+ DISTANCE_DIFFERENT_MODULE = 2
28
+ } DistanceToError;
29
+
30
+ typedef enum {
31
+ CHANGE_LOGIC_FIX = 0,
32
+ CHANGE_NEW_FEATURE = 1,
33
+ CHANGE_REFACTOR = 2,
34
+ CHANGE_CONFIG = 3,
35
+ CHANGE_DEPENDENCY = 4
36
+ } ChangeType;
37
+
38
+ /* ── Data Structures ───────────────────────────────────────── */
39
+ typedef struct {
40
+ char error_type[MATCHER_MAX_ERROR_TYPE];
41
+ uint64_t error_message_hash;
42
+ char location_pattern[MATCHER_MAX_LOCATION_LEN];
43
+ int stack_depth;
44
+ uint64_t stack_hashes[MATCHER_MAX_STACK_DEPTH];
45
+ int change_type;
46
+ int distance_to_error;
47
+ int is_new_in_diff;
48
+ } FeatureVector;
49
+
50
+ typedef struct {
51
+ char sig_id[MATCHER_MAX_SIG_ID];
52
+ FeatureVector features;
53
+ double reliability;
54
+ int match_count;
55
+ char resolution_strategy[MATCHER_MAX_STRATEGY];
56
+ char fix_template[MATCHER_MAX_FIX_TEMPLATE];
57
+ } Signature;
58
+
59
+ typedef struct {
60
+ char sig_id[MATCHER_MAX_SIG_ID];
61
+ double similarity;
62
+ double reliability;
63
+ int match_count;
64
+ char resolution_strategy[MATCHER_MAX_STRATEGY];
65
+ char fix_template[MATCHER_MAX_FIX_TEMPLATE];
66
+ } MatchResult;
67
+
68
+ typedef struct {
69
+ Signature *signatures;
70
+ int count;
71
+ int capacity;
72
+ } SignatureDB;
73
+
74
+ /* ── Weight Configuration ──────────────────────────────────── */
75
+ typedef struct {
76
+ double w_error_type; /* default: 0.30 */
77
+ double w_error_message; /* default: 0.15 */
78
+ double w_location; /* default: 0.25 */
79
+ double w_stack_trace; /* default: 0.15 */
80
+ double w_change_context; /* default: 0.10 */
81
+ double w_temporal; /* default: 0.05 */
82
+ double min_confidence; /* default: 0.65 */
83
+ int top_k; /* default: 3 */
84
+ } MatcherConfig;
85
+
86
+ /* ── API ───────────────────────────────────────────────────── */
87
+
88
+ /*
89
+ * Initialize a new signature database with the given capacity.
90
+ * Returns NULL on allocation failure.
91
+ */
92
+ SignatureDB* db_create(int initial_capacity);
93
+
94
+ /*
95
+ * Free the signature database and all its signatures.
96
+ */
97
+ void db_destroy(SignatureDB *db);
98
+
99
+ /*
100
+ * Add a signature to the database. Returns 0 on success, -1 if full.
101
+ */
102
+ int db_add(SignatureDB *db, const Signature *sig);
103
+
104
+ /*
105
+ * Match a query feature vector against the database.
106
+ * Results are written to `results` (caller-allocated, size `k`).
107
+ * Returns the number of results above min_confidence.
108
+ */
109
+ int db_match(const SignatureDB *db, const MatcherConfig *config,
110
+ const FeatureVector *query,
111
+ MatchResult *results, int k);
112
+
113
+ /*
114
+ * Get default matcher configuration.
115
+ */
116
+ MatcherConfig config_default(void);
117
+
118
+ /*
119
+ * Compute similarity between two feature vectors (0.0 to 1.0).
120
+ */
121
+ double vector_similarity(const MatcherConfig *config,
122
+ const FeatureVector *a, const FeatureVector *b);
123
+
124
+ /*
125
+ * Hash a normalized error message string for fast comparison.
126
+ */
127
+ uint64_t hash_error_message(const char *msg);
128
+
129
+ /*
130
+ * Extract location pattern from a file:line string.
131
+ * E.g., "auth/session.py:validate_token" → "auth/session.py"
132
+ */
133
+ void extract_location_pattern(const char *file_line, char *out, int out_len);
134
+
135
+ #endif /* MATCHER_H */
@@ -0,0 +1,174 @@
1
+ {
2
+ "signatures": [
3
+ {
4
+ "signature_id": "sig-seed-001",
5
+ "created_at": "2026-01-01T00:00:00",
6
+ "last_matched": "2026-01-01T00:00:00",
7
+ "match_count": 0,
8
+ "feature_vector": {
9
+ "error_type": "AttributeError",
10
+ "error_message_hash": "abc123def456",
11
+ "error_location_pattern": "",
12
+ "stack_trace_signature": [],
13
+ "change_context": {
14
+ "files_touched": [],
15
+ "change_types": ["refactor"],
16
+ "distance_to_error": "SAME_FILE"
17
+ },
18
+ "temporal": {
19
+ "is_new_in_this_diff": true,
20
+ "frequency_30d": 0
21
+ }
22
+ },
23
+ "diagnosis": {
24
+ "root_cause": "属性/方法重命名后,调用方未同步更新",
25
+ "root_cause_category": "refactor",
26
+ "reliability": 0.7
27
+ },
28
+ "resolution": {
29
+ "strategy": "FIX_AND_RETEST",
30
+ "fix_template": "检查所有调用方,将旧的属性/方法名更新为新名称",
31
+ "verification_required": [
32
+ "搜索旧方法名的所有引用,确认已全部更新",
33
+ "运行受影响的测试"
34
+ ]
35
+ }
36
+ },
37
+ {
38
+ "signature_id": "sig-seed-002",
39
+ "created_at": "2026-01-01T00:00:00",
40
+ "last_matched": "2026-01-01T00:00:00",
41
+ "match_count": 0,
42
+ "feature_vector": {
43
+ "error_type": "ImportError",
44
+ "error_message_hash": "def456ghi789",
45
+ "error_location_pattern": "",
46
+ "stack_trace_signature": [],
47
+ "change_context": {
48
+ "files_touched": [],
49
+ "change_types": ["dependency"],
50
+ "distance_to_error": "SAME_FILE"
51
+ },
52
+ "temporal": {
53
+ "is_new_in_this_diff": true,
54
+ "frequency_30d": 0
55
+ }
56
+ },
57
+ "diagnosis": {
58
+ "root_cause": "缺少依赖或依赖版本不兼容",
59
+ "root_cause_category": "dependency",
60
+ "reliability": 0.8
61
+ },
62
+ "resolution": {
63
+ "strategy": "FIX_AND_RETEST",
64
+ "fix_template": "检查并安装缺失的依赖,或锁定到兼容版本",
65
+ "verification_required": [
66
+ "确认 requirements.txt 包含所需依赖",
67
+ "运行 pip install 确认无冲突"
68
+ ]
69
+ }
70
+ },
71
+ {
72
+ "signature_id": "sig-seed-003",
73
+ "created_at": "2026-01-01T00:00:00",
74
+ "last_matched": "2026-01-01T00:00:00",
75
+ "match_count": 0,
76
+ "feature_vector": {
77
+ "error_type": "AssertionError",
78
+ "error_message_hash": "ghi789jkl012",
79
+ "error_location_pattern": "",
80
+ "stack_trace_signature": [],
81
+ "change_context": {
82
+ "files_touched": [],
83
+ "change_types": ["logic_fix"],
84
+ "distance_to_error": "SAME_FILE"
85
+ },
86
+ "temporal": {
87
+ "is_new_in_this_diff": true,
88
+ "frequency_30d": 0
89
+ }
90
+ },
91
+ "diagnosis": {
92
+ "root_cause": "测试断言值与实际输出不匹配——代码行为改变了但测试预期未更新,或代码逻辑错误",
93
+ "root_cause_category": "logic_error",
94
+ "reliability": 0.6
95
+ },
96
+ "resolution": {
97
+ "strategy": "DIAGNOSE_AND_FIX",
98
+ "fix_template": "对比预期值和实际值,判断是代码逻辑错误还是测试预期需要更新",
99
+ "verification_required": [
100
+ "确认实际输出是否符合 Spec 预期",
101
+ "如果实际输出正确,更新测试;否则修复代码"
102
+ ]
103
+ }
104
+ },
105
+ {
106
+ "signature_id": "sig-seed-004",
107
+ "created_at": "2026-01-01T00:00:00",
108
+ "last_matched": "2026-01-01T00:00:00",
109
+ "match_count": 0,
110
+ "feature_vector": {
111
+ "error_type": "TypeError",
112
+ "error_message_hash": "jkl012mno345",
113
+ "error_location_pattern": "",
114
+ "stack_trace_signature": [],
115
+ "change_context": {
116
+ "files_touched": [],
117
+ "change_types": ["refactor"],
118
+ "distance_to_error": "SAME_FILE"
119
+ },
120
+ "temporal": {
121
+ "is_new_in_this_diff": true,
122
+ "frequency_30d": 0
123
+ }
124
+ },
125
+ "diagnosis": {
126
+ "root_cause": "函数调用参数类型或数量不匹配——签名变更未同步",
127
+ "root_cause_category": "refactor",
128
+ "reliability": 0.75
129
+ },
130
+ "resolution": {
131
+ "strategy": "FIX_AND_RETEST",
132
+ "fix_template": "检查函数签名变更,确保所有调用方传递正确的参数类型和数量",
133
+ "verification_required": [
134
+ "检查所有调用点的参数是否与新签名匹配",
135
+ "运行类型检查器"
136
+ ]
137
+ }
138
+ },
139
+ {
140
+ "signature_id": "sig-seed-005",
141
+ "created_at": "2026-01-01T00:00:00",
142
+ "last_matched": "2026-01-01T00:00:00",
143
+ "match_count": 0,
144
+ "feature_vector": {
145
+ "error_type": "KeyError",
146
+ "error_message_hash": "mno345pqr678",
147
+ "error_location_pattern": "",
148
+ "stack_trace_signature": [],
149
+ "change_context": {
150
+ "files_touched": [],
151
+ "change_types": ["config"],
152
+ "distance_to_error": "SAME_FILE"
153
+ },
154
+ "temporal": {
155
+ "is_new_in_this_diff": true,
156
+ "frequency_30d": 0
157
+ }
158
+ },
159
+ "diagnosis": {
160
+ "root_cause": "字典/配置键缺失——需要的配置项未被设置",
161
+ "root_cause_category": "config",
162
+ "reliability": 0.7
163
+ },
164
+ "resolution": {
165
+ "strategy": "FIX_AND_RETEST",
166
+ "fix_template": "确认配置文件中包含所需键,或添加默认值兜底",
167
+ "verification_required": [
168
+ "检查所有环境下的配置文件",
169
+ "添加配置缺失时的降级逻辑"
170
+ ]
171
+ }
172
+ }
173
+ ]
174
+ }
File without changes