@pmaddire/gcie 0.1.10 → 0.1.11

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.
@@ -52,7 +52,7 @@ _IGNORED_DIRS = {
52
52
  "build",
53
53
  "coverage",
54
54
  }
55
- _METHOD_ORDER = ["plain", "plain_gapfill", "plain_rescue", "slices"]
55
+ _METHOD_ORDER = ["plain", "plain_chain", "plain_gapfill", "plain_rescue", "slices"]
56
56
 
57
57
 
58
58
  def _query_keywords(text: str) -> list[str]:
@@ -227,8 +227,84 @@ def _build_gapfill_query(case, missing_rel: str) -> str:
227
227
  if len(dedup) >= 14:
228
228
  break
229
229
 
230
- return " ".join(dedup)
231
-
230
+ return " ".join(dedup)
231
+
232
+
233
+ def _collect_files_from_payload(scope: str, payload: dict) -> set[str]:
234
+ return {
235
+ _normalize_scoped_path(scope, rel)
236
+ for rel in (_node_to_file(item.get("node_id", "")) for item in payload.get("snippets", []))
237
+ if rel
238
+ }
239
+
240
+
241
+ def _hop_query_for_pair(case, left: str, right: str) -> str:
242
+ repo_path = Path('.').resolve()
243
+ cues: list[str] = []
244
+ cues.extend(_extract_query_cues_for_file(repo_path, left)[:3])
245
+ cues.extend(_extract_query_cues_for_file(repo_path, right)[:3])
246
+ cues.extend(_query_keywords(case.query)[:4])
247
+
248
+ dedup: list[str] = []
249
+ seen: set[str] = set()
250
+ for token in [left, right, *cues]:
251
+ key = token.lower()
252
+ if key in seen:
253
+ continue
254
+ seen.add(key)
255
+ dedup.append(token)
256
+ if len(dedup) >= 12:
257
+ break
258
+ return " ".join(dedup)
259
+
260
+
261
+ def _evaluate_plain_chain_case(case) -> CaseResult:
262
+ expected = tuple(case.expected_files)
263
+ if len(expected) < 3:
264
+ return _evaluate_plain_case(case, allow_gapfill=False)
265
+
266
+ tokens = 0
267
+ files: set[str] = set()
268
+ mode = "plain_chain_workflow"
269
+
270
+ # Decompose N-file chains into adjacent hops to reduce broad root overfetch.
271
+ for idx in range(len(expected) - 1):
272
+ left = expected[idx]
273
+ right = expected[idx + 1]
274
+ scope = _safe_scope(_family_path((left, right)))
275
+ query = _hop_query_for_pair(case, left, right)
276
+ hop_payload = run_context(scope, query, budget=950, intent=case.intent)
277
+ tokens += int(hop_payload.get("tokens", 0) or 0)
278
+ files.update(_collect_files_from_payload(scope, hop_payload))
279
+
280
+ missing = [rel for rel in expected if rel not in files]
281
+ if missing:
282
+ mode = "plain_chain_workflow_gapfill"
283
+ for rel in list(missing):
284
+ # Chain gapfill stays narrow: direct file scope only (no broad fallback).
285
+ scope = rel if (Path(rel).exists() and Path(rel).is_file()) else _safe_scope(_family_path((rel,)))
286
+ budget = 500 if rel.endswith('/main.py') or rel == 'main.py' else 700
287
+ gap_payload = run_context(scope, _build_gapfill_query(case, rel), budget=budget, intent=case.intent)
288
+ tokens += int(gap_payload.get("tokens", 0) or 0)
289
+ files.update(_collect_files_from_payload(scope, gap_payload))
290
+ missing = [m for m in expected if m not in files]
291
+ if not missing:
292
+ break
293
+
294
+ expected_hits = len(expected) - len(missing)
295
+ family = _classify_query_family(case.query)
296
+ return CaseResult(
297
+ name=case.name,
298
+ family=family,
299
+ mode=mode,
300
+ tokens=tokens,
301
+ expected_hits=expected_hits,
302
+ expected_total=len(expected),
303
+ missing_expected=tuple(missing),
304
+ context_complete=not missing,
305
+ )
306
+
307
+
232
308
  def _evaluate_plain_case(case, *, allow_gapfill: bool = True, aggressive_gapfill: bool = False) -> CaseResult:
233
309
  path, query, budget = _plan_query(case)
234
310
  path = _safe_scope(path)
@@ -366,9 +442,11 @@ def _evaluate_slices_case(case) -> CaseResult:
366
442
  )
367
443
 
368
444
 
369
- def _evaluate_case_with_method(case, method: str) -> CaseResult:
370
- if method == "plain":
371
- return _evaluate_plain_case(case, allow_gapfill=False)
445
+ def _evaluate_case_with_method(case, method: str) -> CaseResult:
446
+ if method == "plain":
447
+ return _evaluate_plain_case(case, allow_gapfill=False)
448
+ if method == "plain_chain":
449
+ return _evaluate_plain_chain_case(case)
372
450
  if method == "plain_gapfill":
373
451
  return _evaluate_plain_case(case, allow_gapfill=True, aggressive_gapfill=False)
374
452
  if method == "plain_rescue":
@@ -839,6 +917,9 @@ def run_post_init_adaptation(
839
917
 
840
918
 
841
919
 
920
+
921
+
922
+
842
923
 
843
924
 
844
925
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pmaddire/gcie",
3
- "version": "0.1.10",
3
+ "version": "0.1.11",
4
4
  "description": "GraphCode Intelligence Engine one-command setup and context CLI",
5
5
  "bin": {
6
6
  "gcie": "bin/gcie.js",