@@ -22,6 +22,8 @@ typedef struct {
2222 int show_augments ;
2323 int show_attribution ;
2424 gm_output_t * output ;
25+ int filter_ai_only ; /* 1 = AI only */
26+ float min_conf ; /* < 0 disables */
2527} list_ctx_t ;
2628
2729/* Legacy edge callback for listing */
@@ -42,9 +44,18 @@ static int list_edge_callback(const gm_edge_t *edge, void *userdata) {
4244 }
4345
4446 /* Format and print edge */
45- char formatted [GM_FORMAT_BUFFER_SIZE ];
46- gm_edge_format (edge , formatted , sizeof (formatted ));
47- gm_output_print (lctx -> output , "%s\n" , formatted );
47+ if (gm_output_is_porcelain (lctx -> output )) {
48+ gm_output_porcelain (lctx -> output , PORCELAIN_KEY_SOURCE , "%s" , edge -> src_path );
49+ gm_output_porcelain (lctx -> output , PORCELAIN_KEY_TARGET , "%s" , edge -> tgt_path );
50+ gm_output_porcelain (lctx -> output , PORCELAIN_KEY_TYPE , "%d" , edge -> rel_type );
51+ gm_output_porcelain (lctx -> output , PORCELAIN_KEY_CONFIDENCE , GM_FMT_CONFIDENCE ,
52+ (double )gm_confidence_from_half_float (edge -> confidence ));
53+ gm_output_porcelain (lctx -> output , PORCELAIN_KEY_ULID , "%s" , edge -> ulid );
54+ } else {
55+ char formatted [GM_FORMAT_BUFFER_SIZE ];
56+ gm_edge_format (edge , formatted , sizeof (formatted ));
57+ gm_output_print (lctx -> output , "%s\n" , formatted );
58+ }
4859
4960 lctx -> count ++ ;
5061 return 0 ; /* Continue */
@@ -68,16 +79,35 @@ static int list_attributed_edge_callback(const gm_edge_attributed_t *edge,
6879 return 0 ; /* Skip augments edges by default */
6980 }
7081
82+ /* Apply attribution filters */
83+ if (lctx -> filter_ai_only && edge -> attribution .source_type == GM_SOURCE_HUMAN ) {
84+ return 0 ;
85+ }
86+ if (lctx -> min_conf >= 0.0f ) {
87+ if (gm_confidence_from_half_float (edge -> confidence ) < lctx -> min_conf ) {
88+ return 0 ;
89+ }
90+ }
91+
7192 /* Format and print edge */
72- char formatted [GM_FORMAT_BUFFER_SIZE ];
73- if (lctx -> show_attribution ||
74- edge -> attribution .source_type != GM_SOURCE_HUMAN ) {
75- gm_edge_attributed_format_with_attribution (edge , formatted ,
76- sizeof (formatted ));
93+ if (gm_output_is_porcelain (lctx -> output )) {
94+ gm_output_porcelain (lctx -> output , PORCELAIN_KEY_SOURCE , "%s" , edge -> src_path );
95+ gm_output_porcelain (lctx -> output , PORCELAIN_KEY_TARGET , "%s" , edge -> tgt_path );
96+ gm_output_porcelain (lctx -> output , PORCELAIN_KEY_TYPE , "%d" , edge -> rel_type );
97+ gm_output_porcelain (lctx -> output , PORCELAIN_KEY_CONFIDENCE , GM_FMT_CONFIDENCE ,
98+ (double )gm_confidence_from_half_float (edge -> confidence ));
99+ gm_output_porcelain (lctx -> output , PORCELAIN_KEY_ULID , "%s" , edge -> ulid );
77100 } else {
78- gm_edge_attributed_format (edge , formatted , sizeof (formatted ));
101+ char formatted [GM_FORMAT_BUFFER_SIZE ];
102+ if (lctx -> show_attribution ||
103+ edge -> attribution .source_type != GM_SOURCE_HUMAN ) {
104+ gm_edge_attributed_format_with_attribution (edge , formatted ,
105+ sizeof (formatted ));
106+ } else {
107+ gm_edge_attributed_format (edge , formatted , sizeof (formatted ));
108+ }
109+ gm_output_print (lctx -> output , "%s\n" , formatted );
79110 }
80- gm_output_print (lctx -> output , "%s\n" , formatted );
81111
82112 lctx -> count ++ ;
83113 return 0 ; /* Continue */
@@ -114,11 +144,21 @@ static void parse_list_arguments(int argc, char **argv, list_ctx_t *lctx,
114144
115145/* Set up filter based on arguments */
116146/* Filters are currently disabled in minimal CLI; placeholders retained */
117- static void setup_list_filter (gm_output_t * out , const char * source_filter , const char * min_conf_str ) {
118- (void )source_filter ;
119- (void )min_conf_str ;
120- /* TODO: implement filters; avoid silent no-ops */
121- gm_output_verbose (out , "Note: filters are parsed but not yet applied.\n" );
147+ static void setup_list_filter (list_ctx_t * lctx , const char * source_filter , const char * min_conf_str ) {
148+ lctx -> filter_ai_only = 0 ;
149+ lctx -> min_conf = -1.0f ;
150+ if (source_filter && strcmp (source_filter , GM_FILTER_VAL_AI ) == 0 ) {
151+ lctx -> filter_ai_only = 1 ;
152+ }
153+ if (min_conf_str && * min_conf_str ) {
154+ char * endp = NULL ;
155+ float v = strtof (min_conf_str , & endp );
156+ if (endp && * endp == '\0' && v >= 0.0f && v <= 1.0f ) {
157+ lctx -> min_conf = v ;
158+ } else {
159+ gm_output_verbose (lctx -> output , "Ignoring invalid --min-confidence value: %s\n" , min_conf_str );
160+ }
161+ }
122162}
123163
124164/* Execute the list query */
@@ -140,6 +180,11 @@ static int execute_list_query(gm_context_t *ctx, const char *branch,
140180static void format_list_output (const list_ctx_t * lctx ,
141181 const char * source_filter ,
142182 const char * min_conf_str , int use_filter ) {
183+ if (gm_output_is_porcelain (lctx -> output )) {
184+ gm_output_porcelain (lctx -> output , PORCELAIN_KEY_STATUS , PORCELAIN_STATUS_SUCCESS );
185+ gm_output_porcelain (lctx -> output , PORCELAIN_KEY_COUNT , "%d" , lctx -> count );
186+ return ;
187+ }
143188 if (lctx -> count == 0 ) {
144189 if (lctx -> filter_path ) {
145190 gm_output_print (lctx -> output , GM_MSG_NO_LINKS_PATH "\n" , lctx -> filter_path );
@@ -183,7 +228,7 @@ int gm_cmd_list(gm_context_t *ctx, gm_cli_ctx_t *cli, int argc, char **argv) {
183228
184229 /* Set up attribution filter if needed */
185230 if (use_filter ) {
186- setup_list_filter (cli -> out , source_filter , min_conf_str );
231+ setup_list_filter (& lctx , source_filter , min_conf_str );
187232 }
188233
189234 /* Execute the query */
0 commit comments