pi-smart-compact 8.0.6 → 8.0.8

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 (47) hide show
  1. package/ARCHITECTURE.md +513 -0
  2. package/CHANGELOG.md +25 -0
  3. package/README.md +70 -51
  4. package/SECURITY.md +8 -3
  5. package/dist/app/mode-policy.d.ts +0 -1
  6. package/dist/app/mode-policy.d.ts.map +1 -1
  7. package/dist/app/preflight.d.ts +16 -2
  8. package/dist/app/preflight.d.ts.map +1 -1
  9. package/dist/app/steps/extract.d.ts.map +1 -1
  10. package/dist/app/steps/state.d.ts.map +1 -1
  11. package/dist/app/steps/synthesize.d.ts.map +1 -1
  12. package/dist/app/steps/window.d.ts +3 -1
  13. package/dist/app/steps/window.d.ts.map +1 -1
  14. package/dist/constants.d.ts +18 -1
  15. package/dist/constants.d.ts.map +1 -1
  16. package/dist/domain/telemetry.d.ts +3 -0
  17. package/dist/domain/telemetry.d.ts.map +1 -1
  18. package/dist/index.d.ts.map +1 -1
  19. package/dist/index.js +762 -549
  20. package/dist/infra/context-graph.d.ts.map +1 -1
  21. package/dist/infra/fs.d.ts +1 -1
  22. package/dist/infra/fs.d.ts.map +1 -1
  23. package/dist/infra/git.d.ts.map +1 -1
  24. package/dist/infra/session-identity.d.ts +4 -0
  25. package/dist/infra/session-identity.d.ts.map +1 -1
  26. package/dist/phases/verify.d.ts.map +1 -1
  27. package/dist/provider-eval.js +113 -22
  28. package/dist/provider-scenario-eval.js +153 -111
  29. package/dist/telemetry-report.js +138 -41
  30. package/dist/ui/dashboard-insights.d.ts.map +1 -1
  31. package/dist/ui/overlays.d.ts.map +1 -1
  32. package/dist/utils/cache.d.ts.map +1 -1
  33. package/dist/utils/extraction.d.ts +5 -0
  34. package/dist/utils/extraction.d.ts.map +1 -1
  35. package/dist/utils/file-needles.d.ts +7 -0
  36. package/dist/utils/file-needles.d.ts.map +1 -1
  37. package/dist/utils/fingerprint.d.ts +1 -1
  38. package/dist/utils/fingerprint.d.ts.map +1 -1
  39. package/dist/utils/pruning.d.ts.map +1 -1
  40. package/dist/utils/state.d.ts +4 -3
  41. package/dist/utils/state.d.ts.map +1 -1
  42. package/dist/utils/tokens.d.ts.map +1 -1
  43. package/docs/MIGRATING_TO_V8.md +30 -13
  44. package/docs/RELEASE.md +13 -10
  45. package/package.json +2 -1
  46. package/dist/app/explore-wrap.d.ts +0 -8
  47. package/dist/app/explore-wrap.d.ts.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"context-graph.d.ts","sourceRoot":"","sources":["../../src/infra/context-graph.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,eAAe,EAAsB,MAAM,aAAa,CAAC;AAYvE,MAAM,MAAM,iBAAiB,GACzB,MAAM,GAAG,UAAU,GAAG,YAAY,GAAG,OAAO,GAAG,MAAM,GACrD,aAAa,GAAG,UAAU,GAAG,OAAO,GAAG,MAAM,GAC7C,YAAY,GAAG,SAAS,GAAG,WAAW,GAAG,SAAS,CAAC;AAEvD,MAAM,WAAW,iBAAiB;IAChC,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,cAAc,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CACpC;AAED,MAAM,WAAW,oBAAoB;IACnC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,KAAK,CAAC,EAAE,SAAS,iBAAiB,EAAE,CAAC;CACtC;AAED,MAAM,WAAW,mBAAmB;IAClC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,iBAAiB,CAAC;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,YAAY,GAAG,QAAQ,CAAC;IAChC,WAAW,EAAE,OAAO,CAAC;IACrB,UAAU,EAAE,OAAO,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,kBAAkB;IACjC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,OAAO,CAAC,iBAAiB,EAAE,UAAU,GAAG,YAAY,GAAG,YAAY,GAAG,SAAS,GAAG,WAAW,GAAG,SAAS,CAAC,CAAC;IACjH,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;CACzB;AAED,MAAM,WAAW,iBAAiB;IAChC,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;CAC9B;AA4RD,qFAAqF;AACrF,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,eAAe,GAAG,OAAO,CAkFvF;AAqBD,uFAAuF;AACvF,wBAAgB,4BAA4B,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,eAAe,GAAG,OAAO,CAa/F;AAED,gEAAgE;AAChE,wBAAgB,2BAA2B,IAAI,IAAI,CAGlD;AAED,0FAA0F;AAC1F,wBAAgB,kBAAkB,CAChC,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,kBAAkB,CAAC,MAAM,CAAC,EAChC,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,UAAU,GAAG,YAAY,GAChC,MAAM,CAsBR;AAED,wDAAwD;AACxD,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,iBAAiB,EAAE,MAAM,EAAE,IAAI,CAAC,kBAAkB,EAAE,IAAI,CAAC,GAAG,kBAAkB,CA8CtH;AA4DD,kGAAkG;AAClG,wBAAgB,aAAa,CAAC,KAAK,EAAE,iBAAiB,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,GAAE,oBAAyB,GAAG,mBAAmB,EAAE,CAkEhI;AAED,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,mBAAmB,EAAE,EAAE,QAAQ,SAAQ,GAAG,MAAM,CAyB5F;AAED,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,MAAM,GAAG,iBAAiB,CAsBzE"}
1
+ {"version":3,"file":"context-graph.d.ts","sourceRoot":"","sources":["../../src/infra/context-graph.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,eAAe,EAAsB,MAAM,aAAa,CAAC;AAavE,MAAM,MAAM,iBAAiB,GACzB,MAAM,GAAG,UAAU,GAAG,YAAY,GAAG,OAAO,GAAG,MAAM,GACrD,aAAa,GAAG,UAAU,GAAG,OAAO,GAAG,MAAM,GAC7C,YAAY,GAAG,SAAS,GAAG,WAAW,GAAG,SAAS,CAAC;AAEvD,MAAM,WAAW,iBAAiB;IAChC,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,cAAc,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CACpC;AAED,MAAM,WAAW,oBAAoB;IACnC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,KAAK,CAAC,EAAE,SAAS,iBAAiB,EAAE,CAAC;CACtC;AAED,MAAM,WAAW,mBAAmB;IAClC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,iBAAiB,CAAC;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,YAAY,GAAG,QAAQ,CAAC;IAChC,WAAW,EAAE,OAAO,CAAC;IACrB,UAAU,EAAE,OAAO,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,kBAAkB;IACjC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,OAAO,CAAC,iBAAiB,EAAE,UAAU,GAAG,YAAY,GAAG,YAAY,GAAG,SAAS,GAAG,WAAW,GAAG,SAAS,CAAC,CAAC;IACjH,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;CACzB;AAED,MAAM,WAAW,iBAAiB;IAChC,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;CAC9B;AAsVD,qFAAqF;AACrF,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,eAAe,GAAG,OAAO,CAmFvF;AAqBD,uFAAuF;AACvF,wBAAgB,4BAA4B,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,eAAe,GAAG,OAAO,CAa/F;AAED,gEAAgE;AAChE,wBAAgB,2BAA2B,IAAI,IAAI,CAGlD;AAED,0FAA0F;AAC1F,wBAAgB,kBAAkB,CAChC,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,kBAAkB,CAAC,MAAM,CAAC,EAChC,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,UAAU,GAAG,YAAY,GAChC,MAAM,CAsBR;AAED,wDAAwD;AACxD,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,iBAAiB,EAAE,MAAM,EAAE,IAAI,CAAC,kBAAkB,EAAE,IAAI,CAAC,GAAG,kBAAkB,CAkDtH;AA4ED,kGAAkG;AAClG,wBAAgB,aAAa,CAAC,KAAK,EAAE,iBAAiB,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,GAAE,oBAAyB,GAAG,mBAAmB,EAAE,CAuEhI;AAED,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,mBAAmB,EAAE,EAAE,QAAQ,SAAQ,GAAG,MAAM,CAyB5F;AAED,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,MAAM,GAAG,iBAAiB,CAsBzE"}
@@ -27,7 +27,7 @@
27
27
  * Lock acquisition is fail-closed: callers never continue an append/trim
28
28
  * without ownership. Locks older than 5s are reclaimed with an atomic rename.
29
29
  */
30
- /** Ensure a directory exists, ignoring EEXIST races. */
30
+ /** Ensure a private directory exists and normalize an existing target. */
31
31
  export declare function ensureDir(dir: string): void;
32
32
  export declare function ensureDirAsync(dir: string): Promise<void>;
33
33
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"fs.d.ts","sourceRoot":"","sources":["../../src/infra/fs.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAYH,wDAAwD;AACxD,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAQ3C;AAED,wBAAsB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAQ/D;AAMD;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI,CAWnF;AAED,wBAAsB,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAU9F;AAED;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,IAAI,CAgD1D;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAQnE;AAED,iFAAiF;AACjF,wBAAgB,aAAa,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,SAAa,GAAG,CAAC,EAAE,CAoB1F;AAED,oEAAoE;AACpE,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,CAgBzE;AAID,iFAAiF;AACjF,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,CAQ3E;AAED,wBAAgB,YAAY,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,GAAG,CAAC,GAAG,IAAI,CASxD;AAED,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,UAAQ,GAAG,IAAI,CAElF"}
1
+ {"version":3,"file":"fs.d.ts","sourceRoot":"","sources":["../../src/infra/fs.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAYH,0EAA0E;AAC1E,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAG3C;AAED,wBAAsB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAG/D;AAMD;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI,CAYnF;AAED,wBAAsB,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAW9F;AAED;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,IAAI,CAgD1D;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAUnE;AAED,iFAAiF;AACjF,wBAAgB,aAAa,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,SAAa,GAAG,CAAC,EAAE,CAoB1F;AAED,oEAAoE;AACpE,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,CAgBzE;AAID,iFAAiF;AACjF,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,CAQ3E;AAED,wBAAgB,YAAY,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,GAAG,CAAC,GAAG,IAAI,CASxD;AAED,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,UAAQ,GAAG,IAAI,CAElF"}
@@ -1 +1 @@
1
- {"version":3,"file":"git.d.ts","sourceRoot":"","sources":["../../src/infra/git.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAOH,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAatD;AAED,mDAAmD;AACnD,wBAAgB,0BAA0B,IAAI,IAAI,CAEjD"}
1
+ {"version":3,"file":"git.d.ts","sourceRoot":"","sources":["../../src/infra/git.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAOH,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAetD;AAED,mDAAmD;AACnD,wBAAgB,0BAA0B,IAAI,IAAI,CAEjD"}
@@ -32,6 +32,10 @@ import type { ExtensionContext } from "@earendil-works/pi-coding-agent";
32
32
  * object that happens to expose a `sessionManager` field.
33
33
  */
34
34
  export type SessionIdentityContext = Pick<ExtensionContext, "sessionManager">;
35
+ /** Extract the complete ordered ancestry exposed by a session branch. */
36
+ export declare function branchEntryIds(branch: Iterable<{
37
+ id?: unknown;
38
+ }>): string[];
35
39
  /**
36
40
  * Resolve the current pi session id, or mint a per-call sentinel that can
37
41
  * never compare equal to another caller's sentinel.
@@ -1 +1 @@
1
- {"version":3,"file":"session-identity.d.ts","sourceRoot":"","sources":["../../src/infra/session-identity.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAGH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC;AAExE;;;;;;;GAOG;AACH,MAAM,MAAM,sBAAsB,GAAG,IAAI,CAAC,gBAAgB,EAAE,gBAAgB,CAAC,CAAC;AAI9E;;;;;;;;;;;GAWG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,sBAAsB,GAAG,MAAM,CAQpE;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAEzD"}
1
+ {"version":3,"file":"session-identity.d.ts","sourceRoot":"","sources":["../../src/infra/session-identity.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAGH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC;AAExE;;;;;;;GAOG;AACH,MAAM,MAAM,sBAAsB,GAAG,IAAI,CAAC,gBAAgB,EAAE,gBAAgB,CAAC,CAAC;AAI9E,yEAAyE;AACzE,wBAAgB,cAAc,CAAC,MAAM,EAAE,QAAQ,CAAC;IAAE,EAAE,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC,GAAG,MAAM,EAAE,CAE3E;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,sBAAsB,GAAG,MAAM,CAQpE;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAEzD"}
@@ -1 +1 @@
1
- {"version":3,"file":"verify.d.ts","sourceRoot":"","sources":["../../src/phases/verify.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACzE,OAAO,KAAK,EAAE,eAAe,EAAE,oBAAoB,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAW9G,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAEjE,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,eAAe,GAAG,MAAM,CAYlE;AAED,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,kBAAkB,GAAG,MAAM,GAAG,IAAI,CAOpF;AAED,wFAAwF;AACxF,qBAAa,qBAAsB,SAAQ,KAAK;IAC9C,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,QAAQ,EAAE,eAAe,CAAC,MAAM,CAAC,EAAE,CAAC;IAC7C,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAE1B,YAAY,MAAM,EAAE,kBAAkB,EAAE,YAAY,EAAE,MAAM,EAO3D;CACF;AAoGD,wBAAgB,4BAA4B,CAAC,GAAG,EAAE,eAAe,GAAG,OAAO,CAI1E;AAED,qGAAqG;AACrG,wBAAgB,8BAA8B,CAC5C,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,kBAAkB,EAC1B,UAAU,EAAE,oBAAoB,EAChC,UAAU,GAAE,eAAe,GAAG,IAAW,EACzC,SAAS,SAAI,GACZ;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,kBAAkB,CAAC;IAAC,OAAO,EAAE,eAAe,EAAE,CAAA;CAAE,CAgB7E;AAED,wBAAgB,aAAa,CAC3B,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,oBAAoB,EAChC,UAAU,GAAE,eAAe,GAAG,IAAW,GACxC,kBAAkB,CAqJpB;AAED,iHAAiH;AACjH,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,eAAe,EAAE,EACvB,UAAU,EAAE,oBAAoB,EAChC,UAAU,GAAE,eAAe,GAAG,IAAW,GACxC,MAAM,CAwFR;AAED,wBAAsB,YAAY,CAChC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,eAAe,EAAE,EACxC,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,eAAe,CAAA;CAAE,EAAE,MAAM,CAAC,EAAE,WAAW,EAC5F,QAAQ,CAAC,EAAE,oBAAoB,GAC9B,OAAO,CAAC,MAAM,CAAC,CAkBjB"}
1
+ {"version":3,"file":"verify.d.ts","sourceRoot":"","sources":["../../src/phases/verify.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACzE,OAAO,KAAK,EAAE,eAAe,EAAE,oBAAoB,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAW9G,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAEjE,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,eAAe,GAAG,MAAM,CAYlE;AAED,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,kBAAkB,GAAG,MAAM,GAAG,IAAI,CAOpF;AAED,wFAAwF;AACxF,qBAAa,qBAAsB,SAAQ,KAAK;IAC9C,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,QAAQ,EAAE,eAAe,CAAC,MAAM,CAAC,EAAE,CAAC;IAC7C,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAE1B,YAAY,MAAM,EAAE,kBAAkB,EAAE,YAAY,EAAE,MAAM,EAO3D;CACF;AAqID,wBAAgB,4BAA4B,CAAC,GAAG,EAAE,eAAe,GAAG,OAAO,CAI1E;AAED,qGAAqG;AACrG,wBAAgB,8BAA8B,CAC5C,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,kBAAkB,EAC1B,UAAU,EAAE,oBAAoB,EAChC,UAAU,GAAE,eAAe,GAAG,IAAW,EACzC,SAAS,SAAI,GACZ;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,kBAAkB,CAAC;IAAC,OAAO,EAAE,eAAe,EAAE,CAAA;CAAE,CAgB7E;AAED,wBAAgB,aAAa,CAC3B,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,oBAAoB,EAChC,UAAU,GAAE,eAAe,GAAG,IAAW,GACxC,kBAAkB,CAgKpB;AAED,iHAAiH;AACjH,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,eAAe,EAAE,EACvB,UAAU,EAAE,oBAAoB,EAChC,UAAU,GAAE,eAAe,GAAG,IAAW,GACxC,MAAM,CAwFR;AAED,wBAAsB,YAAY,CAChC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,eAAe,EAAE,EACxC,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,eAAe,CAAA;CAAE,EAAE,MAAM,CAAC,EAAE,WAAW,EAC5F,QAAQ,CAAC,EAAE,oBAAoB,GAC9B,OAAO,CAAC,MAAM,CAAC,CAkBjB"}
@@ -156,7 +156,7 @@ function formatProviderEvaluation(report) {
156
156
  import fs2 from "fs";
157
157
 
158
158
  // src/constants.ts
159
- var VERSION = "8.0.6";
159
+ var VERSION = "8.0.8";
160
160
  var COMPACT_SYSTEM_PREFIX = "You are an expert conversation summarizer for a coding agent. " + "Produce structured markdown summaries. " + "Follow output format exactly. " + "Use EXACT names \u2014 never paraphrase code identifiers. " + "Trust deterministic extraction data over intuition.";
161
161
  var PROFILES = {
162
162
  light: {
@@ -362,6 +362,27 @@ var EXPLORER_SYSTEM_PROMPT = `You are a conversation analyst. You have determini
362
362
  ` + `After exploration, output ONLY a JSON object (no markdown):
363
363
  ` + '{"boundaries":[{"afterIndex":N,"topic":"...","priority":"critical|high|normal|low","confidence":0.0-1.0}],"mainGoal":"...","sessionType":"implementation|review|debugging|discussion","enrichedConstraints":[...],"crossReferences":[...],"statusAssessment":{"done":[...],"inProgress":[...],"blocked":[...]},"criticalContext":[...],"keyDecisions":[...]}';
364
364
 
365
+ // src/utils/lru.ts
366
+ function lruGet(m, key) {
367
+ if (!m.has(key))
368
+ return;
369
+ const v = m.get(key);
370
+ m.delete(key);
371
+ m.set(key, v);
372
+ return v;
373
+ }
374
+ function lruSet(m, key, value, max) {
375
+ if (m.has(key))
376
+ m.delete(key);
377
+ m.set(key, value);
378
+ while (m.size > max) {
379
+ const oldest = m.keys().next().value;
380
+ if (oldest === undefined)
381
+ break;
382
+ m.delete(oldest);
383
+ }
384
+ }
385
+
365
386
  // src/utils/tokens.ts
366
387
  class TokenCalibrationStore {
367
388
  maxEntries;
@@ -376,35 +397,19 @@ class TokenCalibrationStore {
376
397
  if (!provider)
377
398
  return 1;
378
399
  const exactKey = calibrationKey(provider, model);
379
- const exact = this.factors.get(exactKey);
380
- if (exact !== undefined) {
381
- this.factors.delete(exactKey);
382
- this.factors.set(exactKey, exact);
400
+ const exact = lruGet(this.factors, exactKey);
401
+ if (exact !== undefined)
383
402
  return exact;
384
- }
385
- const providerKey = calibrationKey(provider);
386
- const fallback = this.factors.get(providerKey);
387
- if (fallback !== undefined) {
388
- this.factors.delete(providerKey);
389
- this.factors.set(providerKey, fallback);
390
- }
391
- return fallback ?? 1;
403
+ return lruGet(this.factors, calibrationKey(provider)) ?? 1;
392
404
  }
393
405
  calibrate(estimated, actual, provider, model) {
394
406
  if (actual <= 0 || estimated <= 0 || !provider)
395
407
  return;
396
408
  const key = calibrationKey(provider, model);
397
- const prev = this.factors.get(key) ?? 1;
409
+ const prev = lruGet(this.factors, key) ?? 1;
398
410
  const target = prev * actual / estimated;
399
411
  const clamped = Math.max(TUNING.CALIBRATION_CLAMP_MIN, Math.min(TUNING.CALIBRATION_CLAMP_MAX, target));
400
- this.factors.delete(key);
401
- this.factors.set(key, prev * TUNING.EMA_PREV + clamped * TUNING.EMA_SAMPLE);
402
- while (this.factors.size > Math.max(1, this.maxEntries)) {
403
- const oldest = this.factors.keys().next().value;
404
- if (oldest === undefined)
405
- break;
406
- this.factors.delete(oldest);
407
- }
412
+ lruSet(this.factors, key, prev * TUNING.EMA_PREV + clamped * TUNING.EMA_SAMPLE, Math.max(1, this.maxEntries));
408
413
  }
409
414
  size() {
410
415
  return this.factors.size;
@@ -492,6 +497,92 @@ function extractFileRefs(summary) {
492
497
  return candidates.filter(isLikelyFileRef);
493
498
  }
494
499
 
500
+ // src/domain/summary-schema.ts
501
+ function classifyHeading(raw) {
502
+ const text = raw.replace(/^#+\s*/, "").replace(/[:\s]+$/, "").trim().toLowerCase();
503
+ if (!text)
504
+ return "unknown";
505
+ if (text === "goal" || text === "goals" || text === "objective" || text === "objectives")
506
+ return "goal";
507
+ if (text.startsWith("constraint") || text.includes("preference"))
508
+ return "constraints";
509
+ if (text === "progress" || text === "status")
510
+ return "progress";
511
+ if (text.includes("key decision") || text === "decisions")
512
+ return "decisions";
513
+ if (text.includes("file") && text.includes("modif"))
514
+ return "files-modified";
515
+ if (text.includes("file") && (text.includes("read") || text.includes("viewed")))
516
+ return "files-read";
517
+ if (text.includes("next step") || text === "next actions")
518
+ return "next-steps";
519
+ if (text.includes("critical context") || text === "important context")
520
+ return "critical-context";
521
+ if (text === "topics" || text.includes("topics covered"))
522
+ return "topics";
523
+ if (text.includes("open loop") || text.includes("unresolved"))
524
+ return "open-loops";
525
+ if (text.includes("changes since") || text === "changes")
526
+ return "changes";
527
+ if (text.includes("verification"))
528
+ return "verification-note";
529
+ return "unknown";
530
+ }
531
+
532
+ // src/domain/summary-parse.ts
533
+ var HEADING_RE = /^(#{1,3})\s+(.+?)\s*$/;
534
+ function summaryEvidenceLine(value, maxLength) {
535
+ return value.replace(/[\u0000-\u0008\u000B\u000C\u000E-\u001F\u007F]/g, " ").replace(/\s+/g, " ").trim().replace(/^(?:(?:#{1,6}|[-*+]|>)\s+)+/, "").slice(0, maxLength).trim();
536
+ }
537
+ function mergeBodies(first, second) {
538
+ const seen = new Set;
539
+ return [first, second].filter(Boolean).flatMap((body) => body.split(`
540
+ `)).filter((line) => seen.has(line) ? false : (seen.add(line), true)).join(`
541
+ `).trim();
542
+ }
543
+ function parseSummary(markdown) {
544
+ const sections = [];
545
+ const lines = markdown.split(`
546
+ `);
547
+ let currentHeading = "";
548
+ let currentKind = "unknown";
549
+ let bodyLines = [];
550
+ let started = false;
551
+ const flush = () => {
552
+ if (!started)
553
+ return;
554
+ const body = bodyLines.join(`
555
+ `).trim();
556
+ const existing = currentKind === "unknown" ? undefined : sections.find((s) => s.kind === currentKind);
557
+ if (existing)
558
+ existing.body = mergeBodies(existing.body, body);
559
+ else
560
+ sections.push({ kind: currentKind, heading: currentHeading.trim(), body });
561
+ };
562
+ for (const line of lines) {
563
+ const m = line.match(HEADING_RE);
564
+ if (m) {
565
+ const kind = classifyHeading(m[2]);
566
+ if (m[1].length <= 2 || kind !== "unknown") {
567
+ flush();
568
+ currentHeading = "## " + m[2].trim();
569
+ currentKind = kind;
570
+ bodyLines = [];
571
+ started = true;
572
+ continue;
573
+ }
574
+ }
575
+ if (started)
576
+ bodyLines.push(line);
577
+ }
578
+ flush();
579
+ return { sections };
580
+ }
581
+ function findSection(summary, kind) {
582
+ const parsed = typeof summary === "string" ? parseSummary(summary) : summary;
583
+ return parsed.sections.find((s) => s.kind === kind);
584
+ }
585
+
495
586
  // src/utils/extraction.ts
496
587
  var CONSTRAINT_PATTERNS = [
497
588
  { re: /\b(?:must|need|require|has to|important)\b.*\b(?:be|use|have|include|support)\b/i, cat: "requirement", conf: TUNING.CONFIDENCE_HIGH },
@@ -138,7 +138,7 @@ function getLlmClient() {
138
138
  }
139
139
 
140
140
  // src/constants.ts
141
- var VERSION = "8.0.6";
141
+ var VERSION = "8.0.8";
142
142
  var COMPACT_SYSTEM_PREFIX = "You are an expert conversation summarizer for a coding agent. " + "Produce structured markdown summaries. " + "Follow output format exactly. " + "Use EXACT names \u2014 never paraphrase code identifiers. " + "Trust deterministic extraction data over intuition.";
143
143
  var PROFILES = {
144
144
  light: {
@@ -347,6 +347,27 @@ var EXPLORER_SYSTEM_PROMPT = `You are a conversation analyst. You have determini
347
347
  // src/utils/cache.ts
348
348
  import fs2 from "fs";
349
349
 
350
+ // src/utils/lru.ts
351
+ function lruGet(m, key) {
352
+ if (!m.has(key))
353
+ return;
354
+ const v = m.get(key);
355
+ m.delete(key);
356
+ m.set(key, v);
357
+ return v;
358
+ }
359
+ function lruSet(m, key, value, max) {
360
+ if (m.has(key))
361
+ m.delete(key);
362
+ m.set(key, value);
363
+ while (m.size > max) {
364
+ const oldest = m.keys().next().value;
365
+ if (oldest === undefined)
366
+ break;
367
+ m.delete(oldest);
368
+ }
369
+ }
370
+
350
371
  // src/utils/tokens.ts
351
372
  class TokenCalibrationStore {
352
373
  maxEntries;
@@ -361,35 +382,19 @@ class TokenCalibrationStore {
361
382
  if (!provider)
362
383
  return 1;
363
384
  const exactKey = calibrationKey(provider, model);
364
- const exact = this.factors.get(exactKey);
365
- if (exact !== undefined) {
366
- this.factors.delete(exactKey);
367
- this.factors.set(exactKey, exact);
385
+ const exact = lruGet(this.factors, exactKey);
386
+ if (exact !== undefined)
368
387
  return exact;
369
- }
370
- const providerKey = calibrationKey(provider);
371
- const fallback = this.factors.get(providerKey);
372
- if (fallback !== undefined) {
373
- this.factors.delete(providerKey);
374
- this.factors.set(providerKey, fallback);
375
- }
376
- return fallback ?? 1;
388
+ return lruGet(this.factors, calibrationKey(provider)) ?? 1;
377
389
  }
378
390
  calibrate(estimated, actual, provider, model) {
379
391
  if (actual <= 0 || estimated <= 0 || !provider)
380
392
  return;
381
393
  const key = calibrationKey(provider, model);
382
- const prev = this.factors.get(key) ?? 1;
394
+ const prev = lruGet(this.factors, key) ?? 1;
383
395
  const target = prev * actual / estimated;
384
396
  const clamped = Math.max(TUNING.CALIBRATION_CLAMP_MIN, Math.min(TUNING.CALIBRATION_CLAMP_MAX, target));
385
- this.factors.delete(key);
386
- this.factors.set(key, prev * TUNING.EMA_PREV + clamped * TUNING.EMA_SAMPLE);
387
- while (this.factors.size > Math.max(1, this.maxEntries)) {
388
- const oldest = this.factors.keys().next().value;
389
- if (oldest === undefined)
390
- break;
391
- this.factors.delete(oldest);
392
- }
397
+ lruSet(this.factors, key, prev * TUNING.EMA_PREV + clamped * TUNING.EMA_SAMPLE, Math.max(1, this.maxEntries));
393
398
  }
394
399
  size() {
395
400
  return this.factors.size;
@@ -477,6 +482,92 @@ function extractFileRefs(summary) {
477
482
  return candidates.filter(isLikelyFileRef);
478
483
  }
479
484
 
485
+ // src/domain/summary-schema.ts
486
+ function classifyHeading(raw) {
487
+ const text = raw.replace(/^#+\s*/, "").replace(/[:\s]+$/, "").trim().toLowerCase();
488
+ if (!text)
489
+ return "unknown";
490
+ if (text === "goal" || text === "goals" || text === "objective" || text === "objectives")
491
+ return "goal";
492
+ if (text.startsWith("constraint") || text.includes("preference"))
493
+ return "constraints";
494
+ if (text === "progress" || text === "status")
495
+ return "progress";
496
+ if (text.includes("key decision") || text === "decisions")
497
+ return "decisions";
498
+ if (text.includes("file") && text.includes("modif"))
499
+ return "files-modified";
500
+ if (text.includes("file") && (text.includes("read") || text.includes("viewed")))
501
+ return "files-read";
502
+ if (text.includes("next step") || text === "next actions")
503
+ return "next-steps";
504
+ if (text.includes("critical context") || text === "important context")
505
+ return "critical-context";
506
+ if (text === "topics" || text.includes("topics covered"))
507
+ return "topics";
508
+ if (text.includes("open loop") || text.includes("unresolved"))
509
+ return "open-loops";
510
+ if (text.includes("changes since") || text === "changes")
511
+ return "changes";
512
+ if (text.includes("verification"))
513
+ return "verification-note";
514
+ return "unknown";
515
+ }
516
+
517
+ // src/domain/summary-parse.ts
518
+ var HEADING_RE = /^(#{1,3})\s+(.+?)\s*$/;
519
+ function summaryEvidenceLine(value, maxLength) {
520
+ return value.replace(/[\u0000-\u0008\u000B\u000C\u000E-\u001F\u007F]/g, " ").replace(/\s+/g, " ").trim().replace(/^(?:(?:#{1,6}|[-*+]|>)\s+)+/, "").slice(0, maxLength).trim();
521
+ }
522
+ function mergeBodies(first, second) {
523
+ const seen = new Set;
524
+ return [first, second].filter(Boolean).flatMap((body) => body.split(`
525
+ `)).filter((line) => seen.has(line) ? false : (seen.add(line), true)).join(`
526
+ `).trim();
527
+ }
528
+ function parseSummary(markdown) {
529
+ const sections = [];
530
+ const lines = markdown.split(`
531
+ `);
532
+ let currentHeading = "";
533
+ let currentKind = "unknown";
534
+ let bodyLines = [];
535
+ let started = false;
536
+ const flush = () => {
537
+ if (!started)
538
+ return;
539
+ const body = bodyLines.join(`
540
+ `).trim();
541
+ const existing = currentKind === "unknown" ? undefined : sections.find((s) => s.kind === currentKind);
542
+ if (existing)
543
+ existing.body = mergeBodies(existing.body, body);
544
+ else
545
+ sections.push({ kind: currentKind, heading: currentHeading.trim(), body });
546
+ };
547
+ for (const line of lines) {
548
+ const m = line.match(HEADING_RE);
549
+ if (m) {
550
+ const kind = classifyHeading(m[2]);
551
+ if (m[1].length <= 2 || kind !== "unknown") {
552
+ flush();
553
+ currentHeading = "## " + m[2].trim();
554
+ currentKind = kind;
555
+ bodyLines = [];
556
+ started = true;
557
+ continue;
558
+ }
559
+ }
560
+ if (started)
561
+ bodyLines.push(line);
562
+ }
563
+ flush();
564
+ return { sections };
565
+ }
566
+ function findSection(summary, kind) {
567
+ const parsed = typeof summary === "string" ? parseSummary(summary) : summary;
568
+ return parsed.sections.find((s) => s.kind === kind);
569
+ }
570
+
480
571
  // src/utils/extraction.ts
481
572
  var CONSTRAINT_PATTERNS = [
482
573
  { re: /\b(?:must|need|require|has to|important)\b.*\b(?:be|use|have|include|support)\b/i, cat: "requirement", conf: TUNING.CONFIDENCE_HIGH },
@@ -936,92 +1027,6 @@ function readMetricsLog(limit = 100) {
936
1027
  }
937
1028
  }
938
1029
 
939
- // src/domain/summary-schema.ts
940
- function classifyHeading(raw) {
941
- const text = raw.replace(/^#+\s*/, "").replace(/[:\s]+$/, "").trim().toLowerCase();
942
- if (!text)
943
- return "unknown";
944
- if (text === "goal" || text === "goals" || text === "objective" || text === "objectives")
945
- return "goal";
946
- if (text.startsWith("constraint") || text.includes("preference"))
947
- return "constraints";
948
- if (text === "progress" || text === "status")
949
- return "progress";
950
- if (text.includes("key decision") || text === "decisions")
951
- return "decisions";
952
- if (text.includes("file") && text.includes("modif"))
953
- return "files-modified";
954
- if (text.includes("file") && (text.includes("read") || text.includes("viewed")))
955
- return "files-read";
956
- if (text.includes("next step") || text === "next actions")
957
- return "next-steps";
958
- if (text.includes("critical context") || text === "important context")
959
- return "critical-context";
960
- if (text === "topics" || text.includes("topics covered"))
961
- return "topics";
962
- if (text.includes("open loop") || text.includes("unresolved"))
963
- return "open-loops";
964
- if (text.includes("changes since") || text === "changes")
965
- return "changes";
966
- if (text.includes("verification"))
967
- return "verification-note";
968
- return "unknown";
969
- }
970
-
971
- // src/domain/summary-parse.ts
972
- var HEADING_RE = /^(#{1,3})\s+(.+?)\s*$/;
973
- function summaryEvidenceLine(value, maxLength) {
974
- return value.replace(/[\u0000-\u0008\u000B\u000C\u000E-\u001F\u007F]/g, " ").replace(/\s+/g, " ").trim().replace(/^(?:(?:#{1,6}|[-*+]|>)\s+)+/, "").slice(0, maxLength).trim();
975
- }
976
- function mergeBodies(first, second) {
977
- const seen = new Set;
978
- return [first, second].filter(Boolean).flatMap((body) => body.split(`
979
- `)).filter((line) => seen.has(line) ? false : (seen.add(line), true)).join(`
980
- `).trim();
981
- }
982
- function parseSummary(markdown) {
983
- const sections = [];
984
- const lines = markdown.split(`
985
- `);
986
- let currentHeading = "";
987
- let currentKind = "unknown";
988
- let bodyLines = [];
989
- let started = false;
990
- const flush = () => {
991
- if (!started)
992
- return;
993
- const body = bodyLines.join(`
994
- `).trim();
995
- const existing = currentKind === "unknown" ? undefined : sections.find((s) => s.kind === currentKind);
996
- if (existing)
997
- existing.body = mergeBodies(existing.body, body);
998
- else
999
- sections.push({ kind: currentKind, heading: currentHeading.trim(), body });
1000
- };
1001
- for (const line of lines) {
1002
- const m = line.match(HEADING_RE);
1003
- if (m) {
1004
- const kind = classifyHeading(m[2]);
1005
- if (m[1].length <= 2 || kind !== "unknown") {
1006
- flush();
1007
- currentHeading = "## " + m[2].trim();
1008
- currentKind = kind;
1009
- bodyLines = [];
1010
- started = true;
1011
- continue;
1012
- }
1013
- }
1014
- if (started)
1015
- bodyLines.push(line);
1016
- }
1017
- flush();
1018
- return { sections };
1019
- }
1020
- function findSection(summary, kind) {
1021
- const parsed = typeof summary === "string" ? parseSummary(summary) : summary;
1022
- return parsed.sections.find((s) => s.kind === kind);
1023
- }
1024
-
1025
1030
  // src/phases/verify.ts
1026
1031
  var NEGATION_MARKERS = new Set([
1027
1032
  "no",
@@ -1050,6 +1055,17 @@ var CONDITION_MARKERS = new Set([
1050
1055
  "gerekli",
1051
1056
  "gerektirir"
1052
1057
  ]);
1058
+ var POLARITY_INVERTING_GUARDS = new Set([
1059
+ "skip",
1060
+ "skipp",
1061
+ "forget",
1062
+ "forgett",
1063
+ "omit",
1064
+ "omitt",
1065
+ "neglect",
1066
+ "fail",
1067
+ "avoid"
1068
+ ]);
1053
1069
  var SEMANTIC_STOP = new Set([
1054
1070
  "the",
1055
1071
  "and",
@@ -1099,6 +1115,24 @@ function evidenceFragments(text) {
1099
1115
  function hasNearbyMarker(tokens, anchor, markers) {
1100
1116
  return tokens.some((token, index) => token === anchor && tokens.slice(Math.max(0, index - 2), index + 3).some((near) => markers.has(near)));
1101
1117
  }
1118
+ function hasEffectiveTargetNegation(tokens, anchor) {
1119
+ return tokens.some((token, anchorIndex) => {
1120
+ if (token !== anchor)
1121
+ return false;
1122
+ const nearbyStart = Math.max(0, anchorIndex - 2);
1123
+ const nearbyNegations = tokens.slice(nearbyStart, anchorIndex + 3).map((near, offset) => NEGATION_MARKERS.has(near) ? nearbyStart + offset : -1).filter((index) => index >= 0);
1124
+ const governingStart = Math.max(0, anchorIndex - 3);
1125
+ const preceding = tokens.slice(governingStart, anchorIndex);
1126
+ const nearbyGuards = preceding.map((near, offset) => POLARITY_INVERTING_GUARDS.has(near) ? governingStart + offset : -1).filter((index) => index >= 0);
1127
+ const governingIndex = preceding.findIndex((near, offset) => NEGATION_MARKERS.has(near) && POLARITY_INVERTING_GUARDS.has(preceding[offset + 1] ?? ""));
1128
+ if (governingIndex < 0)
1129
+ return nearbyNegations.length > 0 || nearbyGuards.length > 0;
1130
+ const absoluteGoverningIndex = governingStart + governingIndex;
1131
+ const guardIndex = absoluteGoverningIndex + 1;
1132
+ const nested = tokens.slice(guardIndex + 1, anchorIndex).some((inner) => NEGATION_MARKERS.has(inner) || POLARITY_INVERTING_GUARDS.has(inner));
1133
+ return nested || nearbyNegations.some((index) => index !== absoluteGoverningIndex && index !== guardIndex) || nearbyGuards.some((index) => index !== guardIndex);
1134
+ });
1135
+ }
1102
1136
  function semanticShape(source) {
1103
1137
  const sourceTokens = semanticTokens(source);
1104
1138
  const concepts = Array.from(new Set(sourceTokens.filter((token) => !/^\d+$/.test(token) && !SEMANTIC_STOP.has(token) && !NEGATION_MARKERS.has(token) && !CONDITION_MARKERS.has(token))));
@@ -1117,11 +1151,14 @@ function hasSemanticEvidence(source, target) {
1117
1151
  const overlap = concepts.filter((concept) => tokens.includes(concept)).length;
1118
1152
  if (overlap < required)
1119
1153
  return false;
1120
- if (negative && !hasNearbyMarker(tokens, anchor, NEGATION_MARKERS)) {
1154
+ const targetNegative = hasEffectiveTargetNegation(tokens, anchor);
1155
+ if (negative && !targetNegative) {
1121
1156
  const conditionalRestatement = sourceTokens.includes("without") && tokens.some((token) => CONDITION_MARKERS.has(token)) && overlap >= Math.min(2, concepts.length);
1122
1157
  if (!conditionalRestatement)
1123
1158
  return false;
1124
1159
  }
1160
+ if (!negative && targetNegative)
1161
+ return false;
1125
1162
  if (conditional && !negative && !tokens.some((token) => CONDITION_MARKERS.has(token)))
1126
1163
  return false;
1127
1164
  return true;
@@ -1139,10 +1176,13 @@ function hasSemanticContradiction(source, target) {
1139
1176
  const overlap = concepts.filter((concept) => tokens.includes(concept)).length;
1140
1177
  if (overlap < required)
1141
1178
  return false;
1142
- if (negative && !hasNearbyMarker(tokens, anchor, NEGATION_MARKERS)) {
1179
+ const targetNegative = hasEffectiveTargetNegation(tokens, anchor);
1180
+ if (negative && !targetNegative) {
1143
1181
  const validConditional = sourceTokens.includes("without") && tokens.some((token) => CONDITION_MARKERS.has(token)) && overlap >= Math.min(2, concepts.length);
1144
1182
  return !validConditional;
1145
1183
  }
1184
+ if (!negative && targetNegative)
1185
+ return true;
1146
1186
  return conditional && !negative && !tokens.some((token) => CONDITION_MARKERS.has(token));
1147
1187
  });
1148
1188
  }
@@ -1187,9 +1227,11 @@ function verifySummary(summary, extraction, continuity = null) {
1187
1227
  }
1188
1228
  }
1189
1229
  const modifiedPaths = extraction.modifiedFiles.map((file) => file.path);
1230
+ const listedModifiedPaths = new Set((findSection(parsed, "files-modified")?.body ?? "").split(`
1231
+ `).map((line) => line.replace(/^\s*(?:[-*+]|\d+[.)])\s+/, "").replace(/^\[[ x]\]\s+/i, "").trim()).map((line) => line.startsWith("`") && line.endsWith("`") ? line.slice(1, -1) : line).filter(Boolean).map(normalizePath));
1190
1232
  for (const file of extraction.modifiedFiles) {
1191
1233
  const needles = buildUniquePathNeedles(file.path, modifiedPaths);
1192
- if (!needles.some((needle) => lower.includes(needle))) {
1234
+ if (!listedModifiedPaths.has(normalizePath(file.path)) && !needles.some((needle) => lower.includes(needle))) {
1193
1235
  gaps.push({ kind: "missing-file", path: file.path });
1194
1236
  score -= 5;
1195
1237
  }