pi-smart-compact 7.13.0 → 7.13.1

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 (86) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/README.md +59 -8
  3. package/SECURITY.md +28 -0
  4. package/SUPPORT.md +17 -0
  5. package/dist/app/explore-wrap.d.ts +8 -0
  6. package/dist/app/explore-wrap.d.ts.map +1 -0
  7. package/dist/app/run-context.d.ts +196 -0
  8. package/dist/app/run-context.d.ts.map +1 -0
  9. package/dist/app/run-smart-compact.d.ts +69 -0
  10. package/dist/app/run-smart-compact.d.ts.map +1 -0
  11. package/dist/app/steps/extract.d.ts +21 -0
  12. package/dist/app/steps/extract.d.ts.map +1 -0
  13. package/dist/app/steps/metrics.d.ts +33 -0
  14. package/dist/app/steps/metrics.d.ts.map +1 -0
  15. package/dist/app/steps/persist.d.ts +47 -0
  16. package/dist/app/steps/persist.d.ts.map +1 -0
  17. package/dist/app/steps/prepare.d.ts +12 -0
  18. package/dist/app/steps/prepare.d.ts.map +1 -0
  19. package/dist/app/steps/recover.d.ts +13 -0
  20. package/dist/app/steps/recover.d.ts.map +1 -0
  21. package/dist/app/steps/state.d.ts +13 -0
  22. package/dist/app/steps/state.d.ts.map +1 -0
  23. package/dist/app/steps/synthesize.d.ts +22 -0
  24. package/dist/app/steps/synthesize.d.ts.map +1 -0
  25. package/dist/app/steps/tier.d.ts +12 -0
  26. package/dist/app/steps/tier.d.ts.map +1 -0
  27. package/dist/app/steps/verify.d.ts +19 -0
  28. package/dist/app/steps/verify.d.ts.map +1 -0
  29. package/dist/app/steps/window.d.ts +18 -0
  30. package/dist/app/steps/window.d.ts.map +1 -0
  31. package/dist/constants.d.ts +11 -1
  32. package/dist/constants.d.ts.map +1 -1
  33. package/dist/domain/summary-parse.d.ts +50 -0
  34. package/dist/domain/summary-parse.d.ts.map +1 -0
  35. package/dist/domain/summary-schema.d.ts +49 -0
  36. package/dist/domain/summary-schema.d.ts.map +1 -0
  37. package/dist/index.d.ts.map +1 -1
  38. package/dist/index.js +4647 -3564
  39. package/dist/infra/clock.d.ts +13 -0
  40. package/dist/infra/clock.d.ts.map +1 -0
  41. package/dist/infra/fs.d.ts +57 -0
  42. package/dist/infra/fs.d.ts.map +1 -0
  43. package/dist/infra/git.d.ts +17 -0
  44. package/dist/infra/git.d.ts.map +1 -0
  45. package/dist/infra/llm-client.d.ts +42 -0
  46. package/dist/infra/llm-client.d.ts.map +1 -0
  47. package/dist/infra/llm-retry.d.ts +46 -0
  48. package/dist/infra/llm-retry.d.ts.map +1 -0
  49. package/dist/infra/paths.d.ts +46 -0
  50. package/dist/infra/paths.d.ts.map +1 -0
  51. package/dist/infra/services.d.ts +111 -0
  52. package/dist/infra/services.d.ts.map +1 -0
  53. package/dist/phases/explore.d.ts +15 -3
  54. package/dist/phases/explore.d.ts.map +1 -1
  55. package/dist/phases/synthesize.d.ts +4 -3
  56. package/dist/phases/synthesize.d.ts.map +1 -1
  57. package/dist/phases/verify.d.ts +18 -2
  58. package/dist/phases/verify.d.ts.map +1 -1
  59. package/dist/types.d.ts +42 -3
  60. package/dist/types.d.ts.map +1 -1
  61. package/dist/ui/overlays.d.ts +2 -1
  62. package/dist/ui/overlays.d.ts.map +1 -1
  63. package/dist/utils/cache.d.ts +41 -13
  64. package/dist/utils/cache.d.ts.map +1 -1
  65. package/dist/utils/damage.d.ts.map +1 -1
  66. package/dist/utils/extraction.d.ts +11 -1
  67. package/dist/utils/extraction.d.ts.map +1 -1
  68. package/dist/utils/fingerprint.d.ts +7 -0
  69. package/dist/utils/fingerprint.d.ts.map +1 -1
  70. package/dist/utils/helpers.d.ts +2 -0
  71. package/dist/utils/helpers.d.ts.map +1 -1
  72. package/dist/utils/id-fingerprint.d.ts +52 -0
  73. package/dist/utils/id-fingerprint.d.ts.map +1 -0
  74. package/dist/utils/pruning.d.ts +17 -1
  75. package/dist/utils/pruning.d.ts.map +1 -1
  76. package/dist/utils/session-log.d.ts.map +1 -1
  77. package/dist/utils/state.d.ts +18 -1
  78. package/dist/utils/state.d.ts.map +1 -1
  79. package/dist/utils/tokens.d.ts +30 -2
  80. package/dist/utils/tokens.d.ts.map +1 -1
  81. package/dist/utils/type-guards.d.ts +22 -0
  82. package/dist/utils/type-guards.d.ts.map +1 -1
  83. package/docs/RELEASE.md +40 -0
  84. package/package.json +14 -3
  85. package/dist/core.d.ts +0 -31
  86. package/dist/core.d.ts.map +0 -1
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Step 6: synthesize the conversation summary.
3
+ *
4
+ * Two paths converge here:
5
+ *
6
+ * Single-pass: short conversations fit in one LLM call. The full convText
7
+ * gets sent with the deterministic extraction context and we get a single
8
+ * markdown summary back. We always check the result starts with "##" so a
9
+ * model that refuses or returns junk falls back to the heuristic assembler
10
+ * without polluting the conversation history.
11
+ *
12
+ * EESV: long conversations are explored, chunked, summarized in parallel
13
+ * batches, then assembled. The Explore phase is gated by `shouldExplore` so
14
+ * trivially small sessions don't pay 3-8 extra LLM calls.
15
+ *
16
+ * Concurrency is provider-derived (`providerCaps.concurrencyLimit`). Wave
17
+ * scheduling matters because some providers (Kimi, Minimax) throttle hard
18
+ * once you exceed 2-3 concurrent calls.
19
+ */
20
+ import type { ExtractedRc, SynthesizedRc } from "../run-context.ts";
21
+ export declare function summarizeConversation(rc: ExtractedRc): Promise<SynthesizedRc>;
22
+ //# sourceMappingURL=synthesize.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"synthesize.d.ts","sourceRoot":"","sources":["../../../src/app/steps/synthesize.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAUH,OAAO,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAGpE,wBAAsB,qBAAqB,CAAC,EAAE,EAAE,WAAW,GAAG,OAAO,CAAC,aAAa,CAAC,CA6MnF"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Step 4: select compaction tier.
3
+ *
4
+ * Stage: `RecoveredRc` → `TieredRc | null`.
5
+ *
6
+ * Returns `null` for tier="none" so the orchestrator can short-circuit. Only
7
+ * "light" and "full" tiers reach later stages, which is enforced statically
8
+ * by the `ActiveTier` type on `TieredRc.tier`.
9
+ */
10
+ import type { RecoveredRc, TieredRc } from "../run-context.ts";
11
+ export declare function selectTier(rc: RecoveredRc): TieredRc | null;
12
+ //# sourceMappingURL=tier.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tier.d.ts","sourceRoot":"","sources":["../../../src/app/steps/tier.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAc,MAAM,mBAAmB,CAAC;AAK3E,wBAAgB,UAAU,CAAC,EAAE,EAAE,WAAW,GAAG,QAAQ,GAAG,IAAI,CAiB3D"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Step 7: verify and optionally patch the summary.
3
+ *
4
+ * Stage: `SynthesizedRc` → `VerifiedRc`.
5
+ *
6
+ * Two-stage patch policy:
7
+ *
8
+ * 1. Run deterministic verification. If the score is comfortably high we
9
+ * accept the summary as-is — no LLM patch cost, no extra latency.
10
+ * 2. If the score is < 85, apply the deterministic patcher first. It is
11
+ * free, idempotent, and almost always recovers missing sections / file
12
+ * lists that the LLM elided.
13
+ * 3. Re-verify. Only if the deterministic patch couldn't bring us above 75
14
+ * do we burn an LLM call on `patchSummary`. This keeps cost predictable
15
+ * while still preserving the safety net for catastrophic LLM output.
16
+ */
17
+ import type { SynthesizedRc, VerifiedRc } from "../run-context.ts";
18
+ export declare function verifyAndPatch(rc: SynthesizedRc): Promise<VerifiedRc>;
19
+ //# sourceMappingURL=verify.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verify.d.ts","sourceRoot":"","sources":["../../../src/app/steps/verify.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAMnE,wBAAsB,cAAc,CAAC,EAAE,EAAE,aAAa,GAAG,OAAO,CAAC,UAAU,CAAC,CAsD3E"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Step 2: pick the compaction window.
3
+ *
4
+ * Stage: `PreparedRc` → `WindowedRc | null`.
5
+ *
6
+ * The window is the prefix of branch messages we will summarize. Walks back
7
+ * from the tail accumulating tokens up to `keepRecentTokens`, then anchors:
8
+ *
9
+ * - `smartKeepBoundary` respects the latest on-branch anchor and avoids
10
+ * splitting topical groups.
11
+ * - `guardToolCallBoundary` rejects boundaries that would orphan a
12
+ * `toolResult` from its `toolCall`.
13
+ *
14
+ * Returns `null` when the conversation is too small to compact.
15
+ */
16
+ import type { PreparedRc, WindowedRc } from "../run-context.ts";
17
+ export declare function resolveCompactionWindow(rc: PreparedRc): WindowedRc | null;
18
+ //# sourceMappingURL=window.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"window.d.ts","sourceRoot":"","sources":["../../../src/app/steps/window.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAOhE,wBAAgB,uBAAuB,CAAC,EAAE,EAAE,UAAU,GAAG,UAAU,GAAG,IAAI,CAkDzE"}
@@ -2,7 +2,7 @@
2
2
  * Constants, prompts, and profile defaults.
3
3
  */
4
4
  import type { CompressionProfile, ProfileConfig } from "./types.ts";
5
- export declare const VERSION = "7.13.0";
5
+ export declare const VERSION = "7.13.1";
6
6
  export declare const CHARS_PER_TOKEN = 3.8;
7
7
  export declare const COMPACT_SYSTEM_PREFIX: string;
8
8
  export declare const PROFILES: Record<CompressionProfile, ProfileConfig>;
@@ -41,6 +41,16 @@ export declare const SECTION_CHANGES = "## Changes Since Last Compaction";
41
41
  export declare const LOG_PREFIX = "[smart-compact]";
42
42
  export declare const MIN_TOKEN_THRESHOLD = 5000;
43
43
  export declare const MAX_EXPLORATION_ROUNDS = 8;
44
+ export declare const BACKUP_MAX_FILES = 20;
45
+ export declare const BACKUP_MAX_AGE_MS: number;
46
+ export declare const SUMMARY_SNIPPET_LEN = 100;
47
+ export declare const SHORT_SUMMARY_LEN = 60;
48
+ export declare const ERROR_FUZZY_MATCH_LEN = 30;
49
+ export declare const DAMAGE_RECENT_MSG_WINDOW = 15;
50
+ export declare const MAX_TOOL_OUTPUT_CHARS = 800;
51
+ export declare const METRICS_BUFFER_MAX = 200;
52
+ export declare const DAMAGE_LOOKBACK_MSGS = 15;
53
+ export declare const VERIFICATION_GAP_SNIPPET_LEN = 80;
44
54
  export declare const CONFIG_KEY = "smartCompact";
45
55
  export declare const CONFIG_KEY_ALT = "semanticCompact";
46
56
  export declare const EXPLORER_SYSTEM_PROMPT: string;
@@ -1 +1 @@
1
- {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEpE,eAAO,MAAM,OAAO,WAAW,CAAC;AAChC,eAAO,MAAM,eAAe,MAAM,CAAC;AAEnC,eAAO,MAAM,qBAAqB,QAKqB,CAAC;AAExD,eAAO,MAAM,QAAQ,EAAE,MAAM,CAAC,kBAAkB,EAAE,aAAa,CAyB9D,CAAC;AAEF,eAAO,MAAM,cAAc;aACF,kBAAkB;;kBAEnB,MAAM,GAAG,IAAI;uBACR,MAAM,GAAG,IAAI;;;;;;CAMzC,CAAC;AAEF,eAAO,MAAM,QAAQ,QAA+E,CAAC;AACrG,eAAO,MAAM,QAAQ,QAAuH,CAAC;AAC7I,eAAO,MAAM,SAAS,QAAmG,CAAC;AAI1H,eAAO,MAAM,kBAAkB,QAgB+C,CAAC;AAE/E,eAAO,MAAM,kBAAkB,yHACyF,CAAC;AAEzH,eAAO,MAAM,mBAAmB,QAWoB,CAAC;AAErD,eAAO,MAAM,mBAAmB,8DAA8D,CAAC;AAE/F,eAAO,MAAM,sBAAsB,QAoB2B,CAAC;AAE/D,eAAO,MAAM,sBAAsB,8OAC0M,CAAC;AAI9O,eAAO,MAAM,yBAAyB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAK5D,CAAC;AAGF,eAAO,MAAM,YAAY,YAAY,CAAC;AACtC,eAAO,MAAM,mBAAmB,iCAAiC,CAAC;AAClE,eAAO,MAAM,gBAAgB,gBAAgB,CAAC;AAC9C,eAAO,MAAM,iBAAiB,qBAAqB,CAAC;AACpD,eAAO,MAAM,sBAAsB,sBAAsB,CAAC;AAC1D,eAAO,MAAM,kBAAkB,kBAAkB,CAAC;AAClD,eAAO,MAAM,kBAAkB,kBAAkB,CAAC;AAClD,eAAO,MAAM,wBAAwB,wBAAwB,CAAC;AAC9D,eAAO,MAAM,cAAc,sBAAsB,CAAC;AAClD,eAAO,MAAM,kBAAkB,kBAAkB,CAAC;AAClD,eAAO,MAAM,eAAe,qCAAqC,CAAC;AAGlE,eAAO,MAAM,UAAU,oBAAoB,CAAC;AAG5C,eAAO,MAAM,mBAAmB,OAAO,CAAC;AACxC,eAAO,MAAM,sBAAsB,IAAI,CAAC;AAGxC,eAAO,MAAM,UAAU,iBAAiB,CAAC;AACzC,eAAO,MAAM,cAAc,oBAAoB,CAAC;AAEhD,eAAO,MAAM,sBAAsB,QAU6T,CAAC"}
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEpE,eAAO,MAAM,OAAO,WAAW,CAAC;AAChC,eAAO,MAAM,eAAe,MAAM,CAAC;AAEnC,eAAO,MAAM,qBAAqB,QAKqB,CAAC;AAExD,eAAO,MAAM,QAAQ,EAAE,MAAM,CAAC,kBAAkB,EAAE,aAAa,CAyB9D,CAAC;AAEF,eAAO,MAAM,cAAc;aACF,kBAAkB;;kBAEnB,MAAM,GAAG,IAAI;uBACR,MAAM,GAAG,IAAI;;;;;;CAMzC,CAAC;AAEF,eAAO,MAAM,QAAQ,QAA+E,CAAC;AACrG,eAAO,MAAM,QAAQ,QAAuH,CAAC;AAC7I,eAAO,MAAM,SAAS,QAAmG,CAAC;AAI1H,eAAO,MAAM,kBAAkB,QAgB+C,CAAC;AAE/E,eAAO,MAAM,kBAAkB,yHACyF,CAAC;AAEzH,eAAO,MAAM,mBAAmB,QAWoB,CAAC;AAErD,eAAO,MAAM,mBAAmB,8DAA8D,CAAC;AAE/F,eAAO,MAAM,sBAAsB,QAoB2B,CAAC;AAE/D,eAAO,MAAM,sBAAsB,8OAC0M,CAAC;AAI9O,eAAO,MAAM,yBAAyB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAK5D,CAAC;AAGF,eAAO,MAAM,YAAY,YAAY,CAAC;AACtC,eAAO,MAAM,mBAAmB,iCAAiC,CAAC;AAClE,eAAO,MAAM,gBAAgB,gBAAgB,CAAC;AAC9C,eAAO,MAAM,iBAAiB,qBAAqB,CAAC;AACpD,eAAO,MAAM,sBAAsB,sBAAsB,CAAC;AAC1D,eAAO,MAAM,kBAAkB,kBAAkB,CAAC;AAClD,eAAO,MAAM,kBAAkB,kBAAkB,CAAC;AAClD,eAAO,MAAM,wBAAwB,wBAAwB,CAAC;AAC9D,eAAO,MAAM,cAAc,sBAAsB,CAAC;AAClD,eAAO,MAAM,kBAAkB,kBAAkB,CAAC;AAClD,eAAO,MAAM,eAAe,qCAAqC,CAAC;AAGlE,eAAO,MAAM,UAAU,oBAAoB,CAAC;AAG5C,eAAO,MAAM,mBAAmB,OAAO,CAAC;AACxC,eAAO,MAAM,sBAAsB,IAAI,CAAC;AAQxC,eAAO,MAAM,gBAAgB,KAAK,CAAC;AACnC,eAAO,MAAM,iBAAiB,QAA2B,CAAC;AAO1D,eAAO,MAAM,mBAAmB,MAAM,CAAC;AACvC,eAAO,MAAM,iBAAiB,KAAK,CAAC;AACpC,eAAO,MAAM,qBAAqB,KAAK,CAAC;AACxC,eAAO,MAAM,wBAAwB,KAAK,CAAC;AAG3C,eAAO,MAAM,qBAAqB,MAAM,CAAC;AAOzC,eAAO,MAAM,kBAAkB,MAAM,CAAC;AAGtC,eAAO,MAAM,oBAAoB,KAAK,CAAC;AAGvC,eAAO,MAAM,4BAA4B,KAAK,CAAC;AAG/C,eAAO,MAAM,UAAU,iBAAiB,CAAC;AACzC,eAAO,MAAM,cAAc,oBAAoB,CAAC;AAEhD,eAAO,MAAM,sBAAsB,QAU6T,CAAC"}
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Markdown ↔ CanonicalSummary parser.
3
+ *
4
+ * The synthesis phase produces markdown because LLMs and humans both read it
5
+ * well. Verification, patching, and delta-injection used to operate by
6
+ * lowercasing the markdown and substring-scanning for headings, which gave
7
+ * us a long tail of regex fragility: `## Goal` matched but `### Goal` did not,
8
+ * `Files Modified` matched but `Files modified` had to be lowercased first,
9
+ * etc.
10
+ *
11
+ * This module performs one structural parse up front: every `^#{1,3} ` line
12
+ * becomes a section, and the text between headings becomes its body. After
13
+ * that, the rest of the code can ask `findSection(summary, "goal")` and let
14
+ * the classifier handle aliases.
15
+ *
16
+ * The parser is intentionally tolerant — it accepts H1/H2/H3 and trims
17
+ * surrounding whitespace — because we expect occasional formatting drift from
18
+ * smaller LLMs.
19
+ */
20
+ import { CanonicalSummary, Section, SectionKind } from "./summary-schema.ts";
21
+ export declare function parseSummary(markdown: string): CanonicalSummary;
22
+ /** Find the first section matching the requested kind. */
23
+ export declare function findSection(summary: CanonicalSummary | string, kind: SectionKind): Section | undefined;
24
+ export declare function hasSection(summary: CanonicalSummary | string, kind: SectionKind): boolean;
25
+ /** Stringify the canonical form back to markdown.
26
+ *
27
+ * `opts.canonicalHeadings` rewrites recognized headings to their canonical
28
+ * form. Patch routines turn this on so downstream verification cannot miss a
29
+ * section because the LLM emitted `### Goal` instead of `## Goal`.
30
+ */
31
+ export declare function renderSummary(summary: CanonicalSummary, opts?: {
32
+ canonicalHeadings?: boolean;
33
+ }): string;
34
+ /**
35
+ * Insert or replace a section. If a section with the same `kind` exists, its
36
+ * heading is replaced with the canonical one and the body is overwritten. If
37
+ * not, the section is appended.
38
+ *
39
+ * `before` hints at which section *kind* the new entry should precede; when
40
+ * absent the section is appended. This is how the synthesis pipeline keeps
41
+ * `Open Loops` ahead of `Next Steps` deterministically.
42
+ */
43
+ export declare function upsertSection(summary: CanonicalSummary, kind: SectionKind, body: string, before?: SectionKind): CanonicalSummary;
44
+ /**
45
+ * Append text to an existing section body. If the section is missing, it is
46
+ * created with the provided body. This is the structural equivalent of the
47
+ * old `findOrCreateSectionInsert` helper in `verify.ts`.
48
+ */
49
+ export declare function appendToSection(summary: CanonicalSummary, kind: SectionKind, text: string, fallbackBody?: string): CanonicalSummary;
50
+ //# sourceMappingURL=summary-parse.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"summary-parse.d.ts","sourceRoot":"","sources":["../../src/domain/summary-parse.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,EAAE,gBAAgB,EAAE,OAAO,EAAE,WAAW,EAAqC,MAAM,qBAAqB,CAAC;AAmBhH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,gBAAgB,CAiC/D;AAED,0DAA0D;AAC1D,wBAAgB,WAAW,CAAC,OAAO,EAAE,gBAAgB,GAAG,MAAM,EAAE,IAAI,EAAE,WAAW,GAAG,OAAO,GAAG,SAAS,CAGtG;AAED,wBAAgB,UAAU,CAAC,OAAO,EAAE,gBAAgB,GAAG,MAAM,EAAE,IAAI,EAAE,WAAW,GAAG,OAAO,CAEzF;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,gBAAgB,EAAE,IAAI,GAAE;IAAE,iBAAiB,CAAC,EAAE,OAAO,CAAA;CAAO,GAAG,MAAM,CAS3G;AAED;;;;;;;;GAQG;AACH,wBAAgB,aAAa,CAC3B,OAAO,EAAE,gBAAgB,EACzB,IAAI,EAAE,WAAW,EACjB,IAAI,EAAE,MAAM,EACZ,MAAM,CAAC,EAAE,WAAW,GACnB,gBAAgB,CAkBlB;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAC7B,OAAO,EAAE,gBAAgB,EACzB,IAAI,EAAE,WAAW,EACjB,IAAI,EAAE,MAAM,EACZ,YAAY,SAAK,GAChB,gBAAgB,CAWlB"}
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Canonical summary schema.
3
+ *
4
+ * The summary that smart-compact produces is consumed by humans (in the result
5
+ * screen and `Pending Compaction` banner) but also re-parsed downstream by the
6
+ * verification phase and by the delta extractor. Originally everything spoke
7
+ * Markdown, and verification ran on string `lower.includes("## goal")`-style
8
+ * checks. That meant:
9
+ *
10
+ * - A model that emitted `### Goal` or `## Goals` slipped past the check and
11
+ * triggered a false `Missing section` gap.
12
+ * - Reordering / renaming sections by an aggressive provider caused phantom
13
+ * gaps that triggered an LLM patch call — burning tokens just to restore
14
+ * text the summary already contained.
15
+ * - Adding new sections required touching three modules (synthesize prompts,
16
+ * verify regexes, delta injectors).
17
+ *
18
+ * The fix is a tiny canonical representation: a discriminated `Section` array
19
+ * with a `kind` tag. Markdown stays the human/LLM interface, but everything we
20
+ * actually *check* runs on the parsed `CanonicalSummary`. Verification asks
21
+ * "does a section with kind=goal exist?", not "does the lowercased string
22
+ * contain '## goal'".
23
+ *
24
+ * We do not try to parse the body of every section into structured fields
25
+ * here. Body text remains free-form so the LLM can express nuance. Specific
26
+ * sections (`progress`, `files-modified`, etc.) have their bodies inspected
27
+ * by helpers in `summary-parse.ts` when the verification logic needs to look
28
+ * deeper.
29
+ */
30
+ export type SectionKind = "goal" | "constraints" | "progress" | "decisions" | "files-modified" | "files-read" | "next-steps" | "critical-context" | "topics" | "open-loops" | "changes" | "verification-note" | "unknown";
31
+ export interface Section {
32
+ kind: SectionKind;
33
+ /** Original heading as parsed from the markdown (preserves the user-facing label). */
34
+ heading: string;
35
+ /** Body of the section, leading/trailing whitespace trimmed. */
36
+ body: string;
37
+ }
38
+ export interface CanonicalSummary {
39
+ sections: Section[];
40
+ }
41
+ /**
42
+ * Map a free-form heading text to a known `SectionKind`. We match generously
43
+ * because LLMs reshape capitalization and punctuation: `## Goal`, `# Goal`,
44
+ * `Goals:`, `## GOAL` should all resolve to `goal`.
45
+ */
46
+ export declare function classifyHeading(raw: string): SectionKind;
47
+ /** Canonical heading text used when synthesizing a missing section. */
48
+ export declare function canonicalHeading(kind: SectionKind): string;
49
+ //# sourceMappingURL=summary-schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"summary-schema.d.ts","sourceRoot":"","sources":["../../src/domain/summary-schema.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAQH,MAAM,MAAM,WAAW,GACnB,MAAM,GACN,aAAa,GACb,UAAU,GACV,WAAW,GACX,gBAAgB,GAChB,YAAY,GACZ,YAAY,GACZ,kBAAkB,GAClB,QAAQ,GACR,YAAY,GACZ,SAAS,GACT,mBAAmB,GACnB,SAAS,CAAC;AAEd,MAAM,WAAW,OAAO;IACtB,IAAI,EAAE,WAAW,CAAC;IAClB,sFAAsF;IACtF,OAAO,EAAE,MAAM,CAAC;IAChB,gEAAgE;IAChE,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,OAAO,EAAE,CAAC;CACrB;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,WAAW,CAgBxD;AAED,uEAAuE;AACvE,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,WAAW,GAAG,MAAM,CAiB1D"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,YAAY,EAA2B,MAAM,iCAAiC,CAAC;AA0C7F,MAAM,CAAC,OAAO,UAAU,qBAAqB,CAAC,EAAE,EAAE,YAAY,QAwM7D"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,YAAY,EAA2B,MAAM,iCAAiC,CAAC;AA0C7F,MAAM,CAAC,OAAO,UAAU,qBAAqB,CAAC,EAAE,EAAE,YAAY,QA8N7D"}