pi-smart-compact 9.6.1 → 9.7.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 (44) hide show
  1. package/ARCHITECTURE.md +21 -9
  2. package/CHANGELOG.md +26 -0
  3. package/README.md +33 -10
  4. package/dist/app/mode-policy.d.ts +3 -1
  5. package/dist/app/mode-policy.d.ts.map +1 -1
  6. package/dist/app/preflight.d.ts.map +1 -1
  7. package/dist/app/register-context-tools.d.ts.map +1 -1
  8. package/dist/app/register-smart-compact-command.d.ts.map +1 -1
  9. package/dist/app/register-smart-compact-tool.d.ts.map +1 -1
  10. package/dist/app/run-smart-compact.d.ts.map +1 -1
  11. package/dist/app/smart-compact-input.d.ts +1 -1
  12. package/dist/app/smart-compact-input.d.ts.map +1 -1
  13. package/dist/app/steps/extract.d.ts.map +1 -1
  14. package/dist/app/steps/prepare.d.ts.map +1 -1
  15. package/dist/app/steps/state.d.ts.map +1 -1
  16. package/dist/app/steps/synthesize.d.ts.map +1 -1
  17. package/dist/app/steps/window.d.ts.map +1 -1
  18. package/dist/constants.d.ts +9 -3
  19. package/dist/constants.d.ts.map +1 -1
  20. package/dist/domain/provider-evaluation.d.ts.map +1 -1
  21. package/dist/domain/telemetry.d.ts.map +1 -1
  22. package/dist/index.d.ts.map +1 -1
  23. package/dist/index.js +1978 -1831
  24. package/dist/infra/ai-messages.d.ts +6 -2
  25. package/dist/infra/ai-messages.d.ts.map +1 -1
  26. package/dist/infra/context-graph.d.ts +7 -0
  27. package/dist/infra/context-graph.d.ts.map +1 -1
  28. package/dist/phases/synthesize.d.ts.map +1 -1
  29. package/dist/phases/verify.d.ts.map +1 -1
  30. package/dist/provider-eval.js +252 -27
  31. package/dist/provider-scenario-eval.js +262 -35
  32. package/dist/telemetry-report.js +31 -29
  33. package/dist/types.d.ts +5 -0
  34. package/dist/types.d.ts.map +1 -1
  35. package/dist/ui/error-format.d.ts +3 -1
  36. package/dist/ui/error-format.d.ts.map +1 -1
  37. package/dist/ui/metrics-report.d.ts.map +1 -1
  38. package/dist/ui/settings-complex.d.ts.map +1 -1
  39. package/dist/utils/cache.d.ts.map +1 -1
  40. package/dist/utils/config.d.ts.map +1 -1
  41. package/dist/utils/helpers.d.ts.map +1 -1
  42. package/dist/utils/logger.d.ts.map +1 -1
  43. package/dist/utils/session-log.d.ts.map +1 -1
  44. package/package.json +2 -2
@@ -15,9 +15,13 @@
15
15
  * conversation buffer in native `Message[]` directly (see `phases/explore.ts`),
16
16
  * which is the preferred pattern for any new code that talks to a provider.
17
17
  */
18
- import type { Message } from "@earendil-works/pi-ai";
19
- import type { LlmMessage } from "../types.ts";
18
+ import { type Message } from "@earendil-works/pi-ai";
19
+ import type { LlmMessage, SessionMessageEntry } from "../types.ts";
20
20
  import type { SecretScrubber } from "../domain/scrub.ts";
21
+ /** Preserve the host's context projection and original entry IDs, including custom and branch summaries. */
22
+ export declare function contextMessageEntries(entries: readonly unknown[]): SessionMessageEntry[];
23
+ /** Text transcript without the host summarizer's implicit 2,000-character tool-result cap. */
24
+ export declare function serializeConversationText(messages: LlmMessage[]): string;
21
25
  /**
22
26
  * Upcast a raw branch entry's `message` to a `Message` for `convertToLlm`.
23
27
  *
@@ -1 +1 @@
1
- {"version":3,"file":"ai-messages.d.ts","sourceRoot":"","sources":["../../src/infra/ai-messages.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AACrD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAEzD;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAEzD;AAED;;;;;;;;GAQG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,UAAU,EAAE,GAAG,OAAO,EAAE,CAIpE;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,UAAU,EAAE,EAAE,QAAQ,EAAE,cAAc,GAAG,UAAU,EAAE,CAE3F"}
1
+ {"version":3,"file":"ai-messages.d.ts","sourceRoot":"","sources":["../../src/infra/ai-messages.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EAAe,KAAK,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAClE,OAAO,KAAK,EAAE,UAAU,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAEnE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAEzD,4GAA4G;AAC5G,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,SAAS,OAAO,EAAE,GAAG,mBAAmB,EAAE,CAKxF;AAED,8FAA8F;AAC9F,wBAAgB,yBAAyB,CAAC,QAAQ,EAAE,UAAU,EAAE,GAAG,MAAM,CAKxE;AAED;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAEzD;AAED;;;;;;;;GAQG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,UAAU,EAAE,GAAG,OAAO,EAAE,CAIpE;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,UAAU,EAAE,EAAE,QAAQ,EAAE,cAAc,GAAG,UAAU,EAAE,CAE3F"}
@@ -54,4 +54,11 @@ export declare function saveContextMemory(scope: ContextGraphScope, memory: Omit
54
54
  export declare function recallContext(scope: ContextGraphScope, query: string, options?: ContextRecallOptions): ContextRecallResult[];
55
55
  export declare function formatRecallResults(results: ContextRecallResult[], maxChars?: number): string;
56
56
  export declare function getContextGraphStats(projectId: string): ContextGraphStats;
57
+ /**
58
+ * Permanently forget all graph memory for a project (#63): FTS copies,
59
+ * edges, and nodes in one transaction. Drains any queued index writes
60
+ * first so a scheduled compaction cannot resurrect the memory afterwards.
61
+ * Compaction state files (restore data) and backups are left intact.
62
+ */
63
+ export declare function forgetProjectGraph(projectId: string): boolean;
57
64
  //# sourceMappingURL=context-graph.d.ts.map
@@ -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;AAcvE,MAAM,MAAM,iBAAiB,GACzB,MAAM,GACN,UAAU,GACV,YAAY,GACZ,OAAO,GACP,MAAM,GACN,aAAa,GACb,UAAU,GACV,OAAO,GACP,MAAM,GACN,YAAY,GACZ,SAAS,GACT,WAAW,GACX,SAAS,CAAC;AAEd,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,CACX,iBAAiB,EACf,UAAU,GACV,YAAY,GACZ,YAAY,GACZ,SAAS,GACT,WAAW,GACX,SAAS,CACZ,CAAC;IACF,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;AA0jBD,qFAAqF;AACrF,wBAAgB,oBAAoB,CAClC,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,eAAe,GACrB,OAAO,CA2MT;AA0CD;;;;GAIG;AACH,wBAAgB,4BAA4B,CAC1C,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,eAAe,GACrB,OAAO,CAAC,OAAO,CAAC,CAuBlB;AAED,mDAAmD;AACnD,wBAAgB,2BAA2B,IAAI,IAAI,CAElD;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,CAkBR;AAED,wDAAwD;AACxD,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,iBAAiB,EACxB,MAAM,EAAE,IAAI,CAAC,kBAAkB,EAAE,IAAI,CAAC,GACrC,kBAAkB,CA+EpB;AAiID,kGAAkG;AAClG,wBAAgB,aAAa,CAC3B,KAAK,EAAE,iBAAiB,EACxB,KAAK,EAAE,MAAM,EACb,OAAO,GAAE,oBAAyB,GACjC,mBAAmB,EAAE,CA0GvB;AAED,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,mBAAmB,EAAE,EAC9B,QAAQ,SAAQ,GACf,MAAM,CA8CR;AAED,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,MAAM,GAAG,iBAAiB,CA2BzE"}
1
+ {"version":3,"file":"context-graph.d.ts","sourceRoot":"","sources":["../../src/infra/context-graph.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"synthesize.d.ts","sourceRoot":"","sources":["../../src/phases/synthesize.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACzE,OAAO,KAAK,EACX,UAAU,EACV,QAAQ,EACR,YAAY,EACZ,oBAAoB,EACpB,iBAAiB,EACjB,aAAa,EACb,eAAe,EACf,MAAM,aAAa,CAAC;AAYrB,OAAO,EAGN,KAAK,cAAc,EACnB,MAAM,oBAAoB,CAAC;AAU5B,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AA0BjE,oFAAoF;AACpF,qBAAa,uBAAwB,SAAQ,KAAK;IACjD,QAAQ,CAAC,IAAI,6BAA6B;IAE1C,YAAY,MAAM,EAAE,MAAM,EAEzB;CACD;AAoRD,wBAAgB,gBAAgB,CAC/B,IAAI,EAAE,UAAU,EAAE,EAClB,UAAU,EAAE,OAAO,aAAa,EAAE,aAAa,EAAE,EACjD,EAAE,EAAE,aAAa,EACjB,SAAS,GAAE,cAAqC,EAChD,KAAK,CAAC,EAAE,MAAM,GACZ,QAAQ,EAAE,CAwGZ;AAED,wBAAsB,iBAAiB,CACtC,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,oBAAoB,EAChC,MAAM,EAAE,iBAAiB,GAAG,IAAI,EAChC,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,EACjB,IAAI,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,eAAe,CAAA;CAAE,EACnD,YAAY,EAAE,MAAM,EACpB,MAAM,CAAC,EAAE,WAAW,EACpB,QAAQ,CAAC,EAAE,oBAAoB,EAC/B,KAAK,CAAC,EAAE,MAAM,GACZ,OAAO,CAAC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,CAAC,CAAA;CAAE,CAAC,CA2D3C;AAED,wBAAsB,cAAc,CACnC,KAAK,EAAE,QAAQ,EAAE,EACjB,UAAU,EAAE,oBAAoB,EAChC,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,EACjB,IAAI,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,eAAe,CAAA;CAAE,EACnD,MAAM,CAAC,EAAE,WAAW,EACpB,QAAQ,CAAC,EAAE,oBAAoB,EAC/B,eAAe,CAAC,EAAE,MAAM,EACxB,UAAU,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,YAAY,EAAE,CAAC,CAyKzB;AA6BD,wBAAsB,WAAW,CAChC,SAAS,EAAE,YAAY,EAAE,EACzB,UAAU,EAAE,oBAAoB,EAChC,MAAM,EAAE,iBAAiB,GAAG,IAAI,EAChC,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,EACjB,IAAI,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,eAAe,CAAA;CAAE,EACnD,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,EACnB,MAAM,CAAC,EAAE,WAAW,EACpB,QAAQ,CAAC,EAAE,oBAAoB,EAC/B,KAAK,CAAC,EAAE,MAAM,EACd,UAAU,GAAE,eAAe,GAAG,IAAW,GACvC,OAAO,CAAC,MAAM,CAAC,CAmDjB;AAED,wBAAgB,gBAAgB,CAC/B,SAAS,EAAE,YAAY,EAAE,EACzB,UAAU,EAAE,oBAAoB,EAChC,QAAQ,GAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAO,EAChD,YAAY,GAAE,MAAc,EAC5B,UAAU,GAAE,eAAe,GAAG,IAAW,GACvC,MAAM,CAwIR;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,EAAE,EAAE,QAAQ,GAAG,YAAY,CAiB7D"}
1
+ {"version":3,"file":"synthesize.d.ts","sourceRoot":"","sources":["../../src/phases/synthesize.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACzE,OAAO,KAAK,EACX,UAAU,EACV,QAAQ,EACR,YAAY,EACZ,oBAAoB,EACpB,iBAAiB,EACjB,aAAa,EACb,eAAe,EACf,MAAM,aAAa,CAAC;AAYrB,OAAO,EAGN,KAAK,cAAc,EACnB,MAAM,oBAAoB,CAAC;AAW5B,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AA0BjE,oFAAoF;AACpF,qBAAa,uBAAwB,SAAQ,KAAK;IACjD,QAAQ,CAAC,IAAI,6BAA6B;IAE1C,YAAY,MAAM,EAAE,MAAM,EAEzB;CACD;AAoRD,wBAAgB,gBAAgB,CAC/B,IAAI,EAAE,UAAU,EAAE,EAClB,UAAU,EAAE,OAAO,aAAa,EAAE,aAAa,EAAE,EACjD,EAAE,EAAE,aAAa,EACjB,SAAS,GAAE,cAAqC,EAChD,KAAK,CAAC,EAAE,MAAM,GACZ,QAAQ,EAAE,CAwGZ;AAED,wBAAsB,iBAAiB,CACtC,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,oBAAoB,EAChC,MAAM,EAAE,iBAAiB,GAAG,IAAI,EAChC,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,EACjB,IAAI,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,eAAe,CAAA;CAAE,EACnD,YAAY,EAAE,MAAM,EACpB,MAAM,CAAC,EAAE,WAAW,EACpB,QAAQ,CAAC,EAAE,oBAAoB,EAC/B,KAAK,CAAC,EAAE,MAAM,GACZ,OAAO,CAAC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,CAAC,CAAA;CAAE,CAAC,CA2D3C;AAED,wBAAsB,cAAc,CACnC,KAAK,EAAE,QAAQ,EAAE,EACjB,UAAU,EAAE,oBAAoB,EAChC,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,EACjB,IAAI,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,eAAe,CAAA;CAAE,EACnD,MAAM,CAAC,EAAE,WAAW,EACpB,QAAQ,CAAC,EAAE,oBAAoB,EAC/B,eAAe,CAAC,EAAE,MAAM,EACxB,UAAU,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,YAAY,EAAE,CAAC,CA0MzB;AA6BD,wBAAsB,WAAW,CAChC,SAAS,EAAE,YAAY,EAAE,EACzB,UAAU,EAAE,oBAAoB,EAChC,MAAM,EAAE,iBAAiB,GAAG,IAAI,EAChC,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,EACjB,IAAI,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,eAAe,CAAA;CAAE,EACnD,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,EACnB,MAAM,CAAC,EAAE,WAAW,EACpB,QAAQ,CAAC,EAAE,oBAAoB,EAC/B,KAAK,CAAC,EAAE,MAAM,EACd,UAAU,GAAE,eAAe,GAAG,IAAW,GACvC,OAAO,CAAC,MAAM,CAAC,CAmDjB;AAED,wBAAgB,gBAAgB,CAC/B,SAAS,EAAE,YAAY,EAAE,EACzB,UAAU,EAAE,oBAAoB,EAChC,QAAQ,GAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAO,EAChD,YAAY,GAAE,MAAc,EAC5B,UAAU,GAAE,eAAe,GAAG,IAAW,GACvC,MAAM,CAwIR;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,EAAE,EAAE,QAAQ,GAAG,YAAY,CAiB7D"}
@@ -1 +1 @@
1
- {"version":3,"file":"verify.d.ts","sourceRoot":"","sources":["../../src/phases/verify.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EACX,KAAK,EACL,GAAG,EACH,eAAe,EAEf,MAAM,uBAAuB,CAAC;AAC/B,OAAO,KAAK,EACX,eAAe,EACf,oBAAoB,EACpB,eAAe,EACf,qBAAqB,EACrB,kBAAkB,EAClB,UAAU,EACV,MAAM,aAAa,CAAC;AAoCrB,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AACjE,MAAM,WAAW,oBAAoB;IACpC,cAAc,CAAC,EAAE,SAAS,UAAU,EAAE,CAAC;IACvC,QAAQ,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC7C,mBAAmB,CAAC,EAAE,MAAM,CAAC;CAC7B;AA8SD,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,eAAe,GAAG,MAAM,CAkClE;AAED,wBAAgB,0BAA0B,CACzC,MAAM,EAAE,kBAAkB,GACxB,MAAM,GAAG,IAAI,CAcf;AAED,wFAAwF;AACxF,qBAAa,qBAAsB,SAAQ,KAAK;IAC/C,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,KAAK,EAAE,qBAAqB,CAAC;IACtC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAE1B,YACC,MAAM,EAAE,kBAAkB,EAC1B,YAAY,EAAE,MAAM,EACpB,KAAK,EAAE,qBAAqB,EAW5B;CACD;AAwUD,wBAAgB,4BAA4B,CAAC,GAAG,EAAE,eAAe,GAAG,OAAO,CAK1E;AAED,qGAAqG;AACrG,wBAAgB,8BAA8B,CAC7C,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,kBAAkB,EAC1B,UAAU,EAAE,oBAAoB,EAChC,UAAU,GAAE,eAAe,GAAG,IAAW,EACzC,QAAQ,GAAE,oBAAyB,EACnC,SAAS,SAAI,GACX;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,kBAAkB,CAAC;IAAC,OAAO,EAAE,eAAe,EAAE,CAAA;CAAE,CAyB7E;AAiYD,wBAAgB,aAAa,CAC5B,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,oBAAoB,EAChC,UAAU,GAAE,eAAe,GAAG,IAAW,EACzC,QAAQ,GAAE,oBAAyB,GACjC,kBAAkB,CA2CpB;AAED,iHAAiH;AACjH,wBAAgB,kBAAkB,CACjC,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,eAAe,EAAE,EACvB,UAAU,EAAE,oBAAoB,EAChC,UAAU,GAAE,eAAe,GAAG,IAAW,EACzC,QAAQ,GAAE,oBAAyB,GACjC,MAAM,CA4MR;AA2CD,wBAAsB,YAAY,CACjC,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,eAAe,EAAE,EACvB,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,EACjB,IAAI,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,eAAe,CAAA;CAAE,EACnD,MAAM,CAAC,EAAE,WAAW,EACpB,QAAQ,CAAC,EAAE,oBAAoB,GAC7B,OAAO,CAAC,MAAM,CAAC,CA2DjB"}
1
+ {"version":3,"file":"verify.d.ts","sourceRoot":"","sources":["../../src/phases/verify.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EACX,KAAK,EACL,GAAG,EACH,eAAe,EAEf,MAAM,uBAAuB,CAAC;AAC/B,OAAO,KAAK,EACX,eAAe,EACf,oBAAoB,EACpB,eAAe,EACf,qBAAqB,EACrB,kBAAkB,EAClB,UAAU,EACV,MAAM,aAAa,CAAC;AAoCrB,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AACjE,MAAM,WAAW,oBAAoB;IACpC,cAAc,CAAC,EAAE,SAAS,UAAU,EAAE,CAAC;IACvC,QAAQ,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC7C,mBAAmB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAiTD,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,eAAe,GAAG,MAAM,CAkClE;AAED,wBAAgB,0BAA0B,CACzC,MAAM,EAAE,kBAAkB,GACxB,MAAM,GAAG,IAAI,CAcf;AAED,wFAAwF;AACxF,qBAAa,qBAAsB,SAAQ,KAAK;IAC/C,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,KAAK,EAAE,qBAAqB,CAAC;IACtC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAE1B,YACC,MAAM,EAAE,kBAAkB,EAC1B,YAAY,EAAE,MAAM,EACpB,KAAK,EAAE,qBAAqB,EAW5B;CACD;AA4UD,wBAAgB,4BAA4B,CAAC,GAAG,EAAE,eAAe,GAAG,OAAO,CAK1E;AAED,qGAAqG;AACrG,wBAAgB,8BAA8B,CAC7C,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,kBAAkB,EAC1B,UAAU,EAAE,oBAAoB,EAChC,UAAU,GAAE,eAAe,GAAG,IAAW,EACzC,QAAQ,GAAE,oBAAyB,EACnC,SAAS,SAAI,GACX;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,kBAAkB,CAAC;IAAC,OAAO,EAAE,eAAe,EAAE,CAAA;CAAE,CAyB7E;AAkYD,wBAAgB,aAAa,CAC5B,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,oBAAoB,EAChC,UAAU,GAAE,eAAe,GAAG,IAAW,EACzC,QAAQ,GAAE,oBAAyB,GACjC,kBAAkB,CA4CpB;AAED,iHAAiH;AACjH,wBAAgB,kBAAkB,CACjC,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,eAAe,EAAE,EACvB,UAAU,EAAE,oBAAoB,EAChC,UAAU,GAAE,eAAe,GAAG,IAAW,EACzC,QAAQ,GAAE,oBAAyB,GACjC,MAAM,CA4MR;AA2CD,wBAAsB,YAAY,CACjC,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,eAAe,EAAE,EACvB,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,EACjB,IAAI,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,eAAe,CAAA;CAAE,EACnD,MAAM,CAAC,EAAE,WAAW,EACpB,QAAQ,CAAC,EAAE,oBAAoB,GAC7B,OAAO,CAAC,MAAM,CAAC,CA2DjB"}
@@ -1,6 +1,4 @@
1
1
  // @bun
2
- var __require = import.meta.require;
3
-
4
2
  // src/domain/provider-evaluation.ts
5
3
  function providerScenario(entry) {
6
4
  const context = (entry.contextPercent ?? 0) >= 90 ? "critical" : (entry.contextPercent ?? 0) >= 70 ? "pressure" : "compact";
@@ -156,7 +154,7 @@ function formatProviderEvaluation(report) {
156
154
  import fs2 from "fs";
157
155
 
158
156
  // src/constants.ts
159
- var VERSION = "9.6.1";
157
+ var VERSION = "9.7.0";
160
158
  var SETTLED_TRIGGER_COOLDOWN_MS = 10 * 60000;
161
159
  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.";
162
160
  var PROFILES = {
@@ -209,6 +207,7 @@ var DEFAULT_CONFIG = {
209
207
  maxLlmInputTokens: 0,
210
208
  codexMaxCallMs: 0,
211
209
  maxLatencyMs: 0,
210
+ pendingTtlMs: 300000,
212
211
  focusWeighting: true,
213
212
  zeroCallEnabled: true,
214
213
  contextGraphEnabled: true,
@@ -849,9 +848,12 @@ function classifyToolOperation(args, toolName) {
849
848
 
850
849
  // src/utils/logger.ts
851
850
  var DEBUG = process.env.DEBUG?.includes("smart-compact") ?? false;
851
+ function ts() {
852
+ return new Date().toISOString();
853
+ }
852
854
  function warn(msg, err) {
853
855
  const detail = err instanceof Error ? err.message : err ?? "";
854
- console.error(LOG_PREFIX + " " + msg + (detail ? ": " + detail : ""));
856
+ console.error(ts() + " " + LOG_PREFIX + " " + msg + (detail ? ": " + detail : ""));
855
857
  }
856
858
 
857
859
  // src/infra/fs.ts
@@ -1026,7 +1028,7 @@ function buildSummaryPathEvidence(paths, budgetTokens = PROFILES.balanced.summar
1026
1028
  const unique = Array.from(new Set(paths.filter(Boolean)));
1027
1029
  if (!unique.length)
1028
1030
  return new Map;
1029
- const full = unique.map((path2) => [path2, summaryPathLine(path2)]);
1031
+ const full = unique.map((path) => [path, summaryPathLine(path)]);
1030
1032
  const minimumPerLine = JSON.stringify("#" + "x".repeat(12)).length + 3;
1031
1033
  const budgetChars = Math.max(unique.length * minimumPerLine, Math.min(20000, Math.max(4000, Math.floor(budgetTokens * 2))));
1032
1034
  if (full.reduce((total, [, line]) => total + line.length + 3, 0) <= budgetChars) {
@@ -1034,21 +1036,21 @@ function buildSummaryPathEvidence(paths, budgetTokens = PROFILES.balanced.summar
1034
1036
  }
1035
1037
  const digests = new Map;
1036
1038
  const owners = new Map;
1037
- for (const path2 of unique) {
1038
- const fullDigest = createHash("sha256").update(path2).digest("base64url");
1039
+ for (const path of unique) {
1040
+ const fullDigest = createHash("sha256").update(path).digest("base64url");
1039
1041
  let digest = fullDigest.slice(0, 12);
1040
1042
  const owner = owners.get(digest);
1041
- if (owner && owner !== path2) {
1043
+ if (owner && owner !== path) {
1042
1044
  digest = fullDigest;
1043
1045
  digests.set(owner, createHash("sha256").update(owner).digest("base64url"));
1044
1046
  }
1045
- owners.set(digest, path2);
1046
- digests.set(path2, digest);
1047
+ owners.set(digest, path);
1048
+ digests.set(path, digest);
1047
1049
  }
1048
1050
  const perPath = Math.max(JSON.stringify("#" + "x".repeat(12)).length, Math.floor((budgetChars - unique.length * 3) / unique.length));
1049
- return new Map(unique.map((path2) => [
1050
- path2,
1051
- compactPathLine(path2, perPath, digests.get(path2) ?? "")
1051
+ return new Map(unique.map((path) => [
1052
+ path,
1053
+ compactPathLine(path, perPath, digests.get(path) ?? "")
1052
1054
  ]));
1053
1055
  }
1054
1056
  function mergeBodies(first, second) {
@@ -1553,27 +1555,27 @@ class SecretScrubber {
1553
1555
  findings.set("credential", (findings.get("credential") ?? 0) + 1);
1554
1556
  this.total++;
1555
1557
  };
1556
- const visit = (value2) => {
1557
- if (typeof value2 === "string") {
1558
- const result = this.scrubText(value2);
1558
+ const visit = (value) => {
1559
+ if (typeof value === "string") {
1560
+ const result = this.scrubText(value);
1559
1561
  mergeFindings(findings, result.findings);
1560
1562
  return result.value;
1561
1563
  }
1562
- if (value2 == null || typeof value2 !== "object")
1563
- return value2;
1564
- const cached = seen.get(value2);
1564
+ if (value == null || typeof value !== "object")
1565
+ return value;
1566
+ const cached = seen.get(value);
1565
1567
  if (cached !== undefined)
1566
1568
  return cached;
1567
- if (Array.isArray(value2)) {
1568
- const output2 = [];
1569
- seen.set(value2, output2);
1570
- for (const item of value2)
1571
- output2.push(visit(item));
1572
- return output2;
1569
+ if (Array.isArray(value)) {
1570
+ const output = [];
1571
+ seen.set(value, output);
1572
+ for (const item of value)
1573
+ output.push(visit(item));
1574
+ return output;
1573
1575
  }
1574
1576
  const output = {};
1575
- seen.set(value2, output);
1576
- for (const [key, item] of Object.entries(value2)) {
1577
+ seen.set(value, output);
1578
+ for (const [key, item] of Object.entries(value)) {
1577
1579
  const carriesSecret = typeof item === "string" && item.length >= 8;
1578
1580
  if (this.secretsEnabled && isSecretBearingKey(key) && carriesSecret) {
1579
1581
  output[key] = "[REDACTED:credential]";
@@ -1815,6 +1817,229 @@ var processToolSupport = new ToolSupportCache;
1815
1817
  var processTokenCalibration = new TokenCalibrationStore;
1816
1818
  var _default = createServices();
1817
1819
 
1820
+ // src/domain/telemetry.ts
1821
+ function p95(values) {
1822
+ if (!values.length)
1823
+ return 0;
1824
+ const sorted = [...values].sort((a, b) => a - b);
1825
+ return sorted[Math.max(0, Math.ceil(sorted.length * 0.95) - 1)] ?? 0;
1826
+ }
1827
+ function stats(entries, damage) {
1828
+ const evidence = entries.filter((entry) => entry.status !== "dry-run");
1829
+ const successfulRuns = evidence.filter((entry) => entry.status === "success");
1830
+ const quality = successfulRuns.filter((entry) => typeof entry.verificationScore === "number");
1831
+ const appliedRunIds = new Set(successfulRuns.filter((entry) => typeof entry.runId === "string" && entry.runId.length >= 8).map((entry) => entry.runId));
1832
+ const observedScores = new Map;
1833
+ for (const observation of damage) {
1834
+ if (!observation.runId || !appliedRunIds.has(observation.runId) || typeof observation.damageScore !== "number" || !Number.isFinite(observation.damageScore))
1835
+ continue;
1836
+ observedScores.set(observation.runId, Math.max(observedScores.get(observation.runId) ?? 0, Math.max(0, Math.min(100, observation.damageScore))));
1837
+ }
1838
+ const damaging = [...observedScores.values()].filter((score) => score > 0).length;
1839
+ return {
1840
+ runs: entries.length,
1841
+ appliedRuns: evidence.length,
1842
+ successRate: evidence.length ? successfulRuns.length / evidence.length : 1,
1843
+ avgQuality: quality.length ? quality.reduce((sum, entry) => sum + (entry.verificationScore ?? 0), 0) / quality.length : null,
1844
+ qualityCoverage: evidence.length ? quality.length / evidence.length : 0,
1845
+ p95LatencyMs: p95(evidence.map((entry) => entry.durationMs ?? entry.avgLatency).filter(Number.isFinite)),
1846
+ avgTokens: evidence.length ? evidence.reduce((sum, entry) => sum + entry.totalInput + entry.totalCacheHit + (entry.totalCacheWrite ?? 0) + entry.totalOutput, 0) / evidence.length : 0,
1847
+ fallbackRate: evidence.length ? evidence.filter((entry) => entry.method === "heuristic" || Array.isArray(entry.providerRoutes) && entry.providerRoutes.some((route) => route.successes < route.calls)).length / evidence.length : 0,
1848
+ damageRate: observedScores.size ? damaging / observedScores.size : 0,
1849
+ damageCoverage: successfulRuns.length ? observedScores.size / successfulRuns.length : 0
1850
+ };
1851
+ }
1852
+ function roundStats(value) {
1853
+ return {
1854
+ ...value,
1855
+ successRate: Math.round(value.successRate * 1000) / 1000,
1856
+ avgQuality: value.avgQuality == null ? null : Math.round(value.avgQuality * 10) / 10,
1857
+ qualityCoverage: Math.round(value.qualityCoverage * 1000) / 1000,
1858
+ p95LatencyMs: Math.round(value.p95LatencyMs),
1859
+ avgTokens: Math.round(value.avgTokens),
1860
+ fallbackRate: Math.round(value.fallbackRate * 1000) / 1000,
1861
+ damageRate: Math.round(value.damageRate * 1000) / 1000,
1862
+ damageCoverage: Math.round(value.damageCoverage * 1000) / 1000
1863
+ };
1864
+ }
1865
+ function assessCanary(entries, damageEntries, options) {
1866
+ const minCanaryRuns = Math.max(5, options.minCanaryRuns ?? 20);
1867
+ const canaryEntries = entries.filter((entry) => entry.metricsSchemaVersion === 2 && entry.version === options.version && entry.releaseChannel === "canary").slice(-Math.max(100, minCanaryRuns));
1868
+ const baselineEntries = entries.filter((entry) => entry.metricsSchemaVersion === 2 && (entry.releaseChannel ?? "stable") === "stable").slice(-(options.baselineRuns ?? Math.max(50, minCanaryRuns * 2)));
1869
+ const baseline = stats(baselineEntries, damageEntries);
1870
+ const canary = stats(canaryEntries, damageEntries);
1871
+ const triggers = [];
1872
+ const failureBaseline = 1 - baseline.successRate;
1873
+ const failureCanary = 1 - canary.successRate;
1874
+ if (canary.appliedRuns >= 3 && (failureCanary > 0.050001 || failureCanary - failureBaseline >= 0.050001)) {
1875
+ triggers.push({
1876
+ metric: "failure-rate",
1877
+ baseline: failureBaseline,
1878
+ canary: failureCanary,
1879
+ threshold: failureCanary > 0.050001 ? ">5% absolute" : "+5pp regression"
1880
+ });
1881
+ }
1882
+ if (canary.avgQuality != null && (canary.avgQuality < 85 || baseline.avgQuality != null && baseline.avgQuality - canary.avgQuality >= 5)) {
1883
+ triggers.push({
1884
+ metric: "quality",
1885
+ baseline: baseline.avgQuality ?? 0,
1886
+ canary: canary.avgQuality,
1887
+ threshold: canary.avgQuality < 85 ? "<85 absolute" : "-5 points"
1888
+ });
1889
+ }
1890
+ if (baseline.p95LatencyMs >= 1000 && canary.p95LatencyMs >= baseline.p95LatencyMs * 1.5) {
1891
+ triggers.push({ metric: "latency", baseline: baseline.p95LatencyMs, canary: canary.p95LatencyMs, threshold: "+50% p95" });
1892
+ }
1893
+ if (baseline.avgTokens >= 1000 && canary.avgTokens >= baseline.avgTokens * 1.5) {
1894
+ triggers.push({ metric: "tokens", baseline: baseline.avgTokens, canary: canary.avgTokens, threshold: "+50%" });
1895
+ }
1896
+ if (canary.fallbackRate - baseline.fallbackRate >= 0.1) {
1897
+ triggers.push({ metric: "fallback", baseline: baseline.fallbackRate, canary: canary.fallbackRate, threshold: "+10pp" });
1898
+ }
1899
+ if (canary.damageRate - baseline.damageRate >= 0.1) {
1900
+ triggers.push({ metric: "damage", baseline: baseline.damageRate, canary: canary.damageRate, threshold: "+10pp" });
1901
+ }
1902
+ const canarySampleAdequacy = Math.min(1, canary.appliedRuns / minCanaryRuns);
1903
+ const baselineSampleAdequacy = Math.min(1, baseline.appliedRuns / Math.max(20, minCanaryRuns));
1904
+ const dataConfidence = Math.round(100 * (canarySampleAdequacy * 0.25 + baselineSampleAdequacy * 0.15 + canary.qualityCoverage * canarySampleAdequacy * 0.2 + canary.damageCoverage * canarySampleAdequacy * 0.2 + baseline.damageCoverage * baselineSampleAdequacy * 0.2));
1905
+ const reasons = [];
1906
+ let decision = "hold";
1907
+ if (triggers.length && canary.appliedRuns >= 3) {
1908
+ decision = "rollback";
1909
+ reasons.push(...triggers.map((trigger) => trigger.metric + " crossed " + trigger.threshold));
1910
+ } else if (canary.appliedRuns < minCanaryRuns) {
1911
+ reasons.push("need " + (minCanaryRuns - canary.appliedRuns) + " more canary runs with applied outcomes");
1912
+ } else if (baseline.appliedRuns < Math.max(20, minCanaryRuns)) {
1913
+ reasons.push("stable baseline is too small");
1914
+ } else if (canary.qualityCoverage < 0.7) {
1915
+ reasons.push("schema-v2 quality coverage is below 70%");
1916
+ } else if (canary.damageCoverage < 0.7) {
1917
+ reasons.push("correlated canary damage-observation coverage is below 70%");
1918
+ } else if (baseline.damageCoverage < 0.7) {
1919
+ reasons.push("correlated stable damage-observation coverage is below 70%");
1920
+ } else if ((canary.avgQuality ?? 0) < 85) {
1921
+ reasons.push("absolute verifier quality is below 85");
1922
+ } else if (canary.successRate < 0.949999) {
1923
+ reasons.push("absolute success rate is below 95%");
1924
+ } else {
1925
+ decision = "promote";
1926
+ reasons.push("sample, absolute quality, reliability, latency, token, fallback, and damage gates passed");
1927
+ }
1928
+ return {
1929
+ version: options.version,
1930
+ decision,
1931
+ dataConfidence,
1932
+ baseline: roundStats(baseline),
1933
+ canary: roundStats(canary),
1934
+ triggers,
1935
+ reasons
1936
+ };
1937
+ }
1938
+ function safeMetricLabel(value, fallback) {
1939
+ if (typeof value !== "string" || !/^[\w./:@+-]{1,160}$/.test(value))
1940
+ return fallback;
1941
+ return value;
1942
+ }
1943
+ var TELEMETRY_FAILURE_KINDS = new Set([
1944
+ "cancelled",
1945
+ "timeout",
1946
+ "rate-limit",
1947
+ "authentication",
1948
+ "budget",
1949
+ "output-limit",
1950
+ "provider",
1951
+ "persistence",
1952
+ "validation",
1953
+ "verification",
1954
+ "yield",
1955
+ "internal"
1956
+ ]);
1957
+ function isTelemetryFailureKind(value) {
1958
+ return typeof value === "string" && TELEMETRY_FAILURE_KINDS.has(value);
1959
+ }
1960
+ function buildPrivacySafeTelemetry(entries, damageEntries, options) {
1961
+ const groups = new Map;
1962
+ const failures = {};
1963
+ for (const entry of entries) {
1964
+ const version = safeMetricLabel(entry.version, "legacy");
1965
+ const channel = entry.releaseChannel === "canary" ? "canary" : "stable";
1966
+ const provider = safeMetricLabel(entry.provider, "unknown");
1967
+ const rawModel = safeMetricLabel(entry.model, "unknown");
1968
+ const model = rawModel.startsWith(provider + "/") ? rawModel.slice(provider.length + 1) : rawModel;
1969
+ const key = [version, channel, provider, model].join("\x00");
1970
+ const group = groups.get(key) ?? {
1971
+ version,
1972
+ channel,
1973
+ provider,
1974
+ model,
1975
+ runs: 0,
1976
+ successes: 0,
1977
+ quality: 0,
1978
+ qualityRuns: 0,
1979
+ latency: 0,
1980
+ input: 0,
1981
+ output: 0
1982
+ };
1983
+ group.runs++;
1984
+ if (entry.status === "success" || entry.status === "dry-run")
1985
+ group.successes++;
1986
+ if (entry.metricsSchemaVersion === 2 && typeof entry.verificationScore === "number") {
1987
+ group.quality += entry.verificationScore;
1988
+ group.qualityRuns++;
1989
+ }
1990
+ group.latency += entry.avgLatency;
1991
+ group.input += entry.totalInput + entry.totalCacheHit + (entry.totalCacheWrite ?? 0);
1992
+ group.output += entry.totalOutput;
1993
+ groups.set(key, group);
1994
+ if (isTelemetryFailureKind(entry.failureKind)) {
1995
+ failures[entry.failureKind] = (failures[entry.failureKind] ?? 0) + 1;
1996
+ }
1997
+ }
1998
+ const aggregates = [...groups.values()].map((group) => ({
1999
+ version: group.version,
2000
+ channel: group.channel,
2001
+ provider: group.provider,
2002
+ model: group.model,
2003
+ runs: group.runs,
2004
+ successes: group.successes,
2005
+ avgQuality: group.qualityRuns ? Math.round(group.quality / group.qualityRuns * 10) / 10 : null,
2006
+ avgLatencyMs: group.runs ? Math.round(group.latency / group.runs) : 0,
2007
+ inputTokens: group.input,
2008
+ outputTokens: group.output
2009
+ })).sort((a, b) => b.runs - a.runs || a.version.localeCompare(b.version));
2010
+ return {
2011
+ generatedAt: new Date().toISOString(),
2012
+ totalRuns: entries.length,
2013
+ aggregates,
2014
+ failures,
2015
+ canary: assessCanary(entries, damageEntries, options),
2016
+ privacy: "aggregate-only; no session ids, project ids, prompts, summaries, paths, or error text"
2017
+ };
2018
+ }
2019
+ function formatPrivacySafeTelemetry(report) {
2020
+ const lines = [
2021
+ "# Smart Compact Telemetry",
2022
+ "",
2023
+ "Privacy: " + report.privacy + ".",
2024
+ "",
2025
+ "| Version | Channel | Provider/model | Runs | Success | Quality | Latency | Input | Output |",
2026
+ "|---|---|---|---:|---:|---:|---:|---:|---:|"
2027
+ ];
2028
+ for (const item of report.aggregates) {
2029
+ lines.push("| " + item.version + " | " + item.channel + " | " + item.provider + "/" + item.model + " | " + item.runs + " | " + item.successes + "/" + item.runs + " | " + (item.avgQuality == null ? "n/a" : item.avgQuality.toFixed(1)) + " | " + item.avgLatencyMs + "ms | " + item.inputTokens + " | " + item.outputTokens + " |");
2030
+ }
2031
+ lines.push("", "## Canary: " + report.canary.decision.toUpperCase() + " (data confidence " + report.canary.dataConfidence + "%)", "");
2032
+ const baseline = report.canary.baseline;
2033
+ const canary = report.canary.canary;
2034
+ lines.push("| Gate | Stable baseline | Canary |", "|---|---:|---:|", "| Runs (total/applied) | " + baseline.runs + "/" + baseline.appliedRuns + " | " + canary.runs + "/" + canary.appliedRuns + " |", "| Success | " + Math.round(baseline.successRate * 100) + "% | " + Math.round(canary.successRate * 100) + "% |", "| Verify quality | " + (baseline.avgQuality ?? "n/a") + " | " + (canary.avgQuality ?? "n/a") + " |", "| p95 duration | " + baseline.p95LatencyMs + "ms | " + canary.p95LatencyMs + "ms |", "| Avg tokens | " + baseline.avgTokens + " | " + canary.avgTokens + " |", "| Fallback | " + Math.round(baseline.fallbackRate * 100) + "% | " + Math.round(canary.fallbackRate * 100) + "% |", "| Damage | " + Math.round(baseline.damageRate * 100) + "% | " + Math.round(canary.damageRate * 100) + "% |", "| Damage observed | " + Math.round(baseline.damageCoverage * 100) + "% | " + Math.round(canary.damageCoverage * 100) + "% |", "");
2035
+ for (const reason of report.canary.reasons)
2036
+ lines.push("- " + reason);
2037
+ const failureText = Object.entries(report.failures).map(([kind, count]) => kind + "=" + count).join(", ");
2038
+ lines.push("", "Failures: " + (failureText || "none classified"));
2039
+ return lines.join(`
2040
+ `);
2041
+ }
2042
+
1818
2043
  // src/utils/cache.ts
1819
2044
  var INTERNAL_PHASES = new Set([
1820
2045
  "explore-retry",