openplanr 1.2.6 → 1.2.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 (149) hide show
  1. package/README.md +54 -1
  2. package/dist/ai/prompts/prompt-builder.d.ts +48 -0
  3. package/dist/ai/prompts/prompt-builder.d.ts.map +1 -1
  4. package/dist/ai/prompts/prompt-builder.js +57 -1
  5. package/dist/ai/prompts/prompt-builder.js.map +1 -1
  6. package/dist/ai/prompts/system-prompts.d.ts +23 -0
  7. package/dist/ai/prompts/system-prompts.d.ts.map +1 -1
  8. package/dist/ai/prompts/system-prompts.js +98 -0
  9. package/dist/ai/prompts/system-prompts.js.map +1 -1
  10. package/dist/ai/schemas/ai-response-schemas.d.ts +68 -0
  11. package/dist/ai/schemas/ai-response-schemas.d.ts.map +1 -1
  12. package/dist/ai/schemas/ai-response-schemas.js +81 -0
  13. package/dist/ai/schemas/ai-response-schemas.js.map +1 -1
  14. package/dist/ai/types.d.ts +2 -0
  15. package/dist/ai/types.d.ts.map +1 -1
  16. package/dist/ai/types.js +2 -0
  17. package/dist/ai/types.js.map +1 -1
  18. package/dist/cli/commands/context.d.ts +6 -0
  19. package/dist/cli/commands/context.d.ts.map +1 -0
  20. package/dist/cli/commands/context.js +45 -0
  21. package/dist/cli/commands/context.js.map +1 -0
  22. package/dist/cli/commands/export.d.ts.map +1 -1
  23. package/dist/cli/commands/export.js +8 -0
  24. package/dist/cli/commands/export.js.map +1 -1
  25. package/dist/cli/commands/report-linter.d.ts +6 -0
  26. package/dist/cli/commands/report-linter.d.ts.map +1 -0
  27. package/dist/cli/commands/report-linter.js +61 -0
  28. package/dist/cli/commands/report-linter.js.map +1 -0
  29. package/dist/cli/commands/report.d.ts +6 -0
  30. package/dist/cli/commands/report.d.ts.map +1 -0
  31. package/dist/cli/commands/report.js +150 -0
  32. package/dist/cli/commands/report.js.map +1 -0
  33. package/dist/cli/commands/revise.d.ts +23 -0
  34. package/dist/cli/commands/revise.d.ts.map +1 -0
  35. package/dist/cli/commands/revise.js +502 -0
  36. package/dist/cli/commands/revise.js.map +1 -0
  37. package/dist/cli/commands/story.d.ts.map +1 -1
  38. package/dist/cli/commands/story.js +31 -0
  39. package/dist/cli/commands/story.js.map +1 -1
  40. package/dist/cli/commands/voice.d.ts +6 -0
  41. package/dist/cli/commands/voice.d.ts.map +1 -0
  42. package/dist/cli/commands/voice.js +64 -0
  43. package/dist/cli/commands/voice.js.map +1 -0
  44. package/dist/cli/index.js +10 -0
  45. package/dist/cli/index.js.map +1 -1
  46. package/dist/models/schema.d.ts +63 -0
  47. package/dist/models/schema.d.ts.map +1 -1
  48. package/dist/models/schema.js +31 -0
  49. package/dist/models/schema.js.map +1 -1
  50. package/dist/models/types.d.ts +280 -0
  51. package/dist/models/types.d.ts.map +1 -1
  52. package/dist/services/atomic-write-service.d.ts +41 -0
  53. package/dist/services/atomic-write-service.d.ts.map +1 -0
  54. package/dist/services/atomic-write-service.js +87 -0
  55. package/dist/services/atomic-write-service.js.map +1 -0
  56. package/dist/services/audit-log-service.d.ts +50 -0
  57. package/dist/services/audit-log-service.d.ts.map +1 -0
  58. package/dist/services/audit-log-service.js +213 -0
  59. package/dist/services/audit-log-service.js.map +1 -0
  60. package/dist/services/cascade-service.d.ts +62 -0
  61. package/dist/services/cascade-service.d.ts.map +1 -0
  62. package/dist/services/cascade-service.js +189 -0
  63. package/dist/services/cascade-service.js.map +1 -0
  64. package/dist/services/context-pack-service.d.ts +12 -0
  65. package/dist/services/context-pack-service.d.ts.map +1 -0
  66. package/dist/services/context-pack-service.js +155 -0
  67. package/dist/services/context-pack-service.js.map +1 -0
  68. package/dist/services/diff-service.d.ts +18 -0
  69. package/dist/services/diff-service.d.ts.map +1 -0
  70. package/dist/services/diff-service.js +35 -0
  71. package/dist/services/diff-service.js.map +1 -0
  72. package/dist/services/distribution-service.d.ts +18 -0
  73. package/dist/services/distribution-service.d.ts.map +1 -0
  74. package/dist/services/distribution-service.js +104 -0
  75. package/dist/services/distribution-service.js.map +1 -0
  76. package/dist/services/evidence-service.d.ts +17 -0
  77. package/dist/services/evidence-service.d.ts.map +1 -0
  78. package/dist/services/evidence-service.js +85 -0
  79. package/dist/services/evidence-service.js.map +1 -0
  80. package/dist/services/evidence-verifier.d.ts +71 -0
  81. package/dist/services/evidence-verifier.d.ts.map +1 -0
  82. package/dist/services/evidence-verifier.js +171 -0
  83. package/dist/services/evidence-verifier.js.map +1 -0
  84. package/dist/services/git-service.d.ts +60 -0
  85. package/dist/services/git-service.d.ts.map +1 -0
  86. package/dist/services/git-service.js +137 -0
  87. package/dist/services/git-service.js.map +1 -0
  88. package/dist/services/github-service.d.ts +28 -1
  89. package/dist/services/github-service.d.ts.map +1 -1
  90. package/dist/services/github-service.js +95 -0
  91. package/dist/services/github-service.js.map +1 -1
  92. package/dist/services/graph-integrity.d.ts +36 -0
  93. package/dist/services/graph-integrity.d.ts.map +1 -0
  94. package/dist/services/graph-integrity.js +54 -0
  95. package/dist/services/graph-integrity.js.map +1 -0
  96. package/dist/services/prompt-service.d.ts +18 -0
  97. package/dist/services/prompt-service.d.ts.map +1 -1
  98. package/dist/services/prompt-service.js +47 -0
  99. package/dist/services/prompt-service.js.map +1 -1
  100. package/dist/services/report-linter-service.d.ts +10 -0
  101. package/dist/services/report-linter-service.d.ts.map +1 -0
  102. package/dist/services/report-linter-service.js +95 -0
  103. package/dist/services/report-linter-service.js.map +1 -0
  104. package/dist/services/report-service.d.ts +37 -0
  105. package/dist/services/report-service.d.ts.map +1 -0
  106. package/dist/services/report-service.js +173 -0
  107. package/dist/services/report-service.js.map +1 -0
  108. package/dist/services/revise-cache-service.d.ts +46 -0
  109. package/dist/services/revise-cache-service.d.ts.map +1 -0
  110. package/dist/services/revise-cache-service.js +88 -0
  111. package/dist/services/revise-cache-service.js.map +1 -0
  112. package/dist/services/revise-service.d.ts +108 -0
  113. package/dist/services/revise-service.d.ts.map +1 -0
  114. package/dist/services/revise-service.js +249 -0
  115. package/dist/services/revise-service.js.map +1 -0
  116. package/dist/services/standup-parser.d.ts +21 -0
  117. package/dist/services/standup-parser.d.ts.map +1 -0
  118. package/dist/services/standup-parser.js +104 -0
  119. package/dist/services/standup-parser.js.map +1 -0
  120. package/dist/services/story-standup-service.d.ts +7 -0
  121. package/dist/services/story-standup-service.d.ts.map +1 -0
  122. package/dist/services/story-standup-service.js +27 -0
  123. package/dist/services/story-standup-service.js.map +1 -0
  124. package/dist/services/template-sections.d.ts +28 -0
  125. package/dist/services/template-sections.d.ts.map +1 -0
  126. package/dist/services/template-sections.js +55 -0
  127. package/dist/services/template-sections.js.map +1 -0
  128. package/dist/services/template-service.d.ts.map +1 -1
  129. package/dist/services/template-service.js +1 -0
  130. package/dist/services/template-service.js.map +1 -1
  131. package/dist/services/voice-service.d.ts +12 -0
  132. package/dist/services/voice-service.d.ts.map +1 -0
  133. package/dist/services/voice-service.js +42 -0
  134. package/dist/services/voice-service.js.map +1 -0
  135. package/dist/templates/export/planning-report.html.hbs +10 -0
  136. package/dist/templates/export/planning-report.md.hbs +11 -0
  137. package/dist/templates/linter/linter-config.json.hbs +13 -0
  138. package/dist/templates/reports/executive.md.hbs +28 -0
  139. package/dist/templates/reports/release-notes.md.hbs +37 -0
  140. package/dist/templates/reports/retrospective.md.hbs +36 -0
  141. package/dist/templates/reports/sprint.md.hbs +91 -0
  142. package/dist/templates/reports/standup.md.hbs +27 -0
  143. package/dist/templates/reports/weekly.md.hbs +42 -0
  144. package/dist/templates/voice/standup.md.hbs +20 -0
  145. package/dist/utils/diff.d.ts +26 -0
  146. package/dist/utils/diff.d.ts.map +1 -0
  147. package/dist/utils/diff.js +143 -0
  148. package/dist/utils/diff.js.map +1 -0
  149. package/package.json +1 -1
@@ -222,6 +222,16 @@
222
222
  {{/each}}
223
223
  {{/if}}
224
224
 
225
+ {{#if evidence.length}}
226
+ <h2>Evidence index</h2>
227
+ <p class="subtitle">Flat references for traceability (stories and tasks in this export).</p>
228
+ <ul>
229
+ {{#each evidence}}
230
+ <li><span class="badge badge-pending">{{this.kind}}</span> {{this.label}}{{#if this.detail}} — <em>{{this.detail}}</em>{{/if}}</li>
231
+ {{/each}}
232
+ </ul>
233
+ {{/if}}
234
+
225
235
  <footer>
226
236
  Exported by <code>planr export</code> on {{date}}.
227
237
  </footer>
@@ -134,6 +134,17 @@
134
134
  {{{this.body}}}
135
135
 
136
136
  {{/each}}
137
+ {{/if}}
138
+
139
+ {{#if evidence.length}}
140
+ ## Evidence index
141
+
142
+ Flat references for traceability (stories and tasks in this export):
143
+
144
+ {{#each evidence}}
145
+ - **{{this.kind}}** — {{this.label}}{{#if this.detail}} — _{{this.detail}}_{{/if}}
146
+ {{/each}}
147
+
137
148
  {{/if}}
138
149
  ---
139
150
 
@@ -0,0 +1,13 @@
1
+ {
2
+ "rules": [
3
+ { "id": "evidence-density", "enabled": true, "minEvidenceLinks": 1 },
4
+ { "id": "weekly-structure", "enabled": true, "requireSections": ["Wins", "Risks", "Ask"] }
5
+ ],
6
+ "vaguePhrases": [
7
+ {
8
+ "pattern": "\\\\b(fixed bugs|almost done|making progress)\\\\b",
9
+ "alternatives": ["Closed #12 and #15 (see PR 44)", "Completed 3 of 5 stories"],
10
+ "hint": "Use countable outcomes and links."
11
+ }
12
+ ]
13
+ }
@@ -0,0 +1,28 @@
1
+ # Executive summary — {{projectName}}
2
+
3
+ > {{generatedAt}}
4
+
5
+ ## Outcome
6
+
7
+ - **Active epics:** {{length artifacts.epics}}
8
+ - **Stories:** {{length artifacts.stories}} total in planning tree
9
+
10
+ ## Momentum
11
+
12
+ {{#if github.pullRequests.length}}
13
+ - **Recent PR activity:** {{length github.pullRequests}} PRs touched in the last {{daysLookback}} days.
14
+ {{else}}
15
+ - **Recent PR activity:** _none in window or GitHub unavailable._
16
+ {{/if}}
17
+
18
+ ## Risks & dependencies
19
+
20
+ - _Summarize top 2 risks with mitigation._
21
+
22
+ ## Timeline confidence
23
+
24
+ - _On track / at risk — cite evidence IDs below._
25
+
26
+ ## Evidence{{#each evidence}}
27
+ - {{this.label}}{{#if this.url}} — {{this.url}}{{/if}}
28
+ {{/each}}
@@ -0,0 +1,37 @@
1
+ # Release notes — {{projectName}}
2
+
3
+ > {{generatedAt}} · draft from planning artifacts + GitHub
4
+
5
+ ## Highlights
6
+
7
+ - _User-facing bullets — edit before publishing._
8
+
9
+ ## Completed work (planning)
10
+
11
+ {{#each artifacts.stories}}
12
+ {{#if (eq this.status 'done')}}
13
+ - `{{this.id}}` — {{this.title}}
14
+ {{/if}}
15
+ {{/each}}
16
+
17
+ {{#unless artifacts.stories}}
18
+ _No story data._
19
+ {{/unless}}
20
+
21
+ ## Merged / shipped (GitHub)
22
+
23
+ {{#if github.pullRequests.length}}
24
+ {{#each github.pullRequests}}
25
+ {{#if this.mergedAt}}
26
+ - [PR #{{this.number}}]({{this.url}}) — {{this.title}}
27
+ {{/if}}
28
+ {{/each}}
29
+ {{else}}
30
+ _No PR metadata — add manually._
31
+ {{/if}}
32
+
33
+ ## Evidence
34
+
35
+ {{#each evidence}}
36
+ - **{{this.kind}}** — {{this.label}}{{#if this.url}} — {{this.url}}{{/if}}
37
+ {{/each}}
@@ -0,0 +1,36 @@
1
+ # Sprint retrospective — {{projectName}}
2
+
3
+ > {{generatedAt}}
4
+
5
+ {{#if sprint}}
6
+ _Sprint: {{sprint.sprintId}} — {{sprint.name}} ({{sprint.status}})_
7
+ {{/if}}
8
+
9
+ ## What went well
10
+
11
+ -
12
+
13
+ ## What did not go well
14
+
15
+ -
16
+
17
+ ## Action items
18
+
19
+ | Action | Owner | Due |
20
+ |--------|-------|-----|
21
+ | | | |
22
+
23
+ ## Signals (automated)
24
+
25
+ {{#if github.commits.length}}
26
+ - Commits in window: {{length github.commits}}
27
+ {{/if}}
28
+ {{#if github.pullRequests.length}}
29
+ - PRs in window: {{length github.pullRequests}}
30
+ {{/if}}
31
+
32
+ ## Evidence
33
+
34
+ {{#each evidence}}
35
+ - {{this.label}}{{#if this.url}} — {{this.url}}{{/if}}
36
+ {{/each}}
@@ -0,0 +1,91 @@
1
+ # Sprint report — {{projectName}}
2
+
3
+ > Generated {{generatedAt}} · Type: **{{reportType}}** · Lookback: **{{daysLookback}}** days
4
+
5
+ {{#if branding.orgName}}
6
+ _Organization: {{branding.orgName}}_
7
+ {{/if}}
8
+
9
+ {{#if placeholders.noSprint}}
10
+ > **Note:** No sprint was selected (`--sprint`). Add `--sprint SPRINT-001` for sprint-scoped sections.
11
+ {{/if}}
12
+
13
+ ## Sprint snapshot
14
+
15
+ {{#if sprint}}
16
+ | Field | Value |
17
+ |-------|-------|
18
+ | Sprint | {{sprint.sprintId}} |
19
+ | Name | {{sprint.name}} |
20
+ | Status | {{sprint.status}} |
21
+ | Window | {{sprint.startDate}} → {{sprint.endDate}} |
22
+
23
+ {{#if sprint.goals.length}}
24
+ **Goals**
25
+ {{#each sprint.goals}}
26
+ - {{this}}
27
+ {{/each}}
28
+ {{/if}}
29
+
30
+ **Tasks in sprint:** {{#if sprint.taskIds.length}}{{join sprint.taskIds ", "}}{{else}}_none linked in frontmatter_{{/if}}
31
+
32
+ {{else}}
33
+ _No sprint context._
34
+ {{/if}}
35
+
36
+ ## Planning artifacts (summary)
37
+
38
+ - **Epics:** {{length artifacts.epics}}
39
+ - **Features:** {{length artifacts.features}}
40
+ - **Stories:** {{length artifacts.stories}}
41
+ - **Task lists:** {{length artifacts.tasks}}
42
+
43
+ **Stories**
44
+
45
+ {{#each artifacts.stories}}
46
+ - `{{this.id}}` — {{this.title}} — _{{this.status}}_
47
+ {{/each}}
48
+
49
+ ## GitHub activity
50
+
51
+ {{#if placeholders.noGitHub}}
52
+ _No GitHub data (disabled or unavailable)._
53
+ {{else}}
54
+ {{#if github.warning}}
55
+ > **Warning:** {{github.warning}}
56
+ {{/if}}
57
+
58
+ ### Recent commits
59
+
60
+ {{#if github.commits.length}}
61
+ {{#each github.commits}}
62
+ - [{{this.shortSha}}]({{this.url}}) — {{this.message}} — _{{this.authorLogin}}_
63
+ {{/each}}
64
+ {{else}}
65
+ _No commits in window._
66
+ {{/if}}
67
+
68
+ ### Pull requests
69
+
70
+ {{#if github.pullRequests.length}}
71
+ {{#each github.pullRequests}}
72
+ - [PR #{{this.number}}]({{this.url}}) — {{this.title}} — _{{this.state}} · {{this.authorLogin}}_
73
+ {{/each}}
74
+ {{else}}
75
+ _No pull requests in window._
76
+ {{/if}}
77
+ {{/if}}
78
+
79
+ ## Evidence appendix
80
+
81
+ {{#each evidence}}
82
+ - **{{this.kind}}** — {{this.label}}{{#if this.url}} — {{this.url}}{{/if}}{{#if this.detail}} — _{{this.detail}}_{{/if}}
83
+ {{/each}}
84
+
85
+ {{#if branding.customSections}}
86
+ {{#each branding.customSections}}
87
+ ## {{@key}}
88
+
89
+ {{{this}}}
90
+ {{/each}}
91
+ {{/if}}
@@ -0,0 +1,27 @@
1
+ # Standup — {{projectName}}
2
+
3
+ > {{generatedAt}}
4
+
5
+ ## Yesterday
6
+
7
+ {{#if github.commits.length}}
8
+ {{#each github.commits}}
9
+ - [{{this.shortSha}}]({{this.url}}) {{this.message}}
10
+ {{/each}}
11
+ {{else}}
12
+ - _No commits in lookback — describe what you finished manually._
13
+ {{/if}}
14
+
15
+ ## Today
16
+
17
+ - _Planned work — link tasks `TASK-___` or stories `US-___`._
18
+
19
+ ## Blockers
20
+
21
+ - _None / list with owner_
22
+
23
+ ## Evidence
24
+
25
+ {{#each evidence}}
26
+ - **{{this.kind}}** — {{this.label}}{{#if this.url}} — {{this.url}}{{/if}}
27
+ {{/each}}
@@ -0,0 +1,42 @@
1
+ # Weekly stakeholder update — {{projectName}}
2
+
3
+ > {{generatedAt}} · lookback {{daysLookback}}d
4
+
5
+ {{#if branding.logoUrl}}
6
+ ![Logo]({{branding.logoUrl}})
7
+ {{/if}}
8
+
9
+ ## Wins
10
+
11
+ _Edit bullets — each should link to a PR, issue, or artifact._
12
+
13
+ {{#if github.commits.length}}
14
+ - Shipped commits: {{length github.commits}} in the last {{daysLookback}} days (see Evidence).
15
+ {{else}}
16
+ - _No commit data — add links manually._
17
+ {{/if}}
18
+
19
+ ## Risks
20
+
21
+ {{#if placeholders.noStoriesCompleted}}
22
+ - **Planning:** No stories marked done — confirm whether delivery is blocked or statuses need updating.
23
+ {{/if}}
24
+ - _Add concrete risks with owners and dates._
25
+
26
+ ## Ask
27
+
28
+ - _One clear request to leadership (resource, decision, or scope)._
29
+
30
+ ## Evidence
31
+
32
+ {{#each evidence}}
33
+ - **{{this.kind}}** — {{this.label}}{{#if this.url}} — [link]({{this.url}}){{/if}}
34
+ {{/each}}
35
+
36
+ {{#if branding.customSections}}
37
+ {{#each branding.customSections}}
38
+ ## {{@key}}
39
+
40
+ {{{this}}}
41
+ {{/each}}
42
+ {{/if}}
@@ -0,0 +1,20 @@
1
+ # Voice standup workflow — {{projectName}}
2
+
3
+ **Date:** {{date}}
4
+
5
+ ## Suggested commands
6
+
7
+ ```bash
8
+ # Transcript file → markdown on stdout
9
+ planr voice standup --file ./transcript.txt
10
+
11
+ # Save, lint, and attach to a story
12
+ planr voice standup --file ./transcript.txt --write .planr/last-standup.md --lint --append-story US-028
13
+
14
+ # Same as above via story command
15
+ planr story standup --story US-028 --file ./transcript.txt --lint
16
+ ```
17
+
18
+ ## Microphone capture
19
+
20
+ Live mic capture is not bundled yet. Use OS dictation, Whisper, or another STT tool, then pass the text file with `--file` or pipe stdin.
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Minimal line-based unified diff for revise preview (EPIC-003, FEAT-011 §4.0).
3
+ *
4
+ * Implements a Wagner–Fischer LCS over lines, then prints hunks with
5
+ * `+` / `-` prefixes. Not a general-purpose diff tool — scoped to small
6
+ * planning artifacts (typically <1K lines), where O(m×n) time/memory is
7
+ * comfortable. Line equality is exact after trimming trailing newlines.
8
+ *
9
+ * We don't pull in an npm diff library because (a) the algorithm is small,
10
+ * (b) the format we emit is fixed and narrow, and (c) keeping the
11
+ * dependency footprint tight is a stated project preference.
12
+ */
13
+ export interface UnifiedDiffOptions {
14
+ /** Number of unchanged context lines around each change. Default: 3. */
15
+ context?: number;
16
+ /** Labels printed on the file-header `---` / `+++` rows. */
17
+ oldLabel?: string;
18
+ newLabel?: string;
19
+ }
20
+ /**
21
+ * Compute a unified diff between two strings. Empty string on either side
22
+ * is valid. Trailing newlines are normalized so a file that ends in `\n`
23
+ * does not spuriously diff against one that does not.
24
+ */
25
+ export declare function unifiedDiff(oldText: string, newText: string, options?: UnifiedDiffOptions): string;
26
+ //# sourceMappingURL=diff.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diff.d.ts","sourceRoot":"","sources":["../../src/utils/diff.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAaH,MAAM,WAAW,kBAAkB;IACjC,wEAAwE;IACxE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,4DAA4D;IAC5D,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CACzB,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,EACf,OAAO,GAAE,kBAAuB,GAC/B,MAAM,CAsBR"}
@@ -0,0 +1,143 @@
1
+ /**
2
+ * Minimal line-based unified diff for revise preview (EPIC-003, FEAT-011 §4.0).
3
+ *
4
+ * Implements a Wagner–Fischer LCS over lines, then prints hunks with
5
+ * `+` / `-` prefixes. Not a general-purpose diff tool — scoped to small
6
+ * planning artifacts (typically <1K lines), where O(m×n) time/memory is
7
+ * comfortable. Line equality is exact after trimming trailing newlines.
8
+ *
9
+ * We don't pull in an npm diff library because (a) the algorithm is small,
10
+ * (b) the format we emit is fixed and narrow, and (c) keeping the
11
+ * dependency footprint tight is a stated project preference.
12
+ */
13
+ /**
14
+ * Compute a unified diff between two strings. Empty string on either side
15
+ * is valid. Trailing newlines are normalized so a file that ends in `\n`
16
+ * does not spuriously diff against one that does not.
17
+ */
18
+ export function unifiedDiff(oldText, newText, options = {}) {
19
+ const contextLines = options.context ?? 3;
20
+ const oldLines = splitLines(oldText);
21
+ const newLines = splitLines(newText);
22
+ const items = lcsDiff(oldLines, newLines);
23
+ const hunks = buildHunks(items, contextLines);
24
+ if (hunks.length === 0)
25
+ return ''; // identical
26
+ const out = [];
27
+ out.push(`--- ${options.oldLabel ?? 'a'}`);
28
+ out.push(`+++ ${options.newLabel ?? 'b'}`);
29
+ for (const hunk of hunks) {
30
+ const oldLen = hunk.items.filter((i) => i.kind !== 'add').length;
31
+ const newLen = hunk.items.filter((i) => i.kind !== 'remove').length;
32
+ out.push(`@@ -${hunk.oldStart + 1},${oldLen} +${hunk.newStart + 1},${newLen} @@`);
33
+ for (const it of hunk.items) {
34
+ const prefix = it.kind === 'add' ? '+' : it.kind === 'remove' ? '-' : ' ';
35
+ out.push(`${prefix}${it.line}`);
36
+ }
37
+ }
38
+ return out.join('\n');
39
+ }
40
+ function splitLines(s) {
41
+ if (s.length === 0)
42
+ return [];
43
+ // Preserve empty-trailing-line behavior: drop a single trailing '' so the
44
+ // diff of "a\n" vs "a" is empty rather than noisy.
45
+ const lines = s.split('\n');
46
+ if (lines.length > 0 && lines[lines.length - 1] === '')
47
+ lines.pop();
48
+ return lines;
49
+ }
50
+ /**
51
+ * Build a sequence of DiffItems from two line arrays using LCS backtracking.
52
+ */
53
+ function lcsDiff(a, b) {
54
+ const m = a.length;
55
+ const n = b.length;
56
+ // dp[i][j] = length of LCS of a[0..i) and b[0..j)
57
+ const dp = Array.from({ length: m + 1 }, () => new Array(n + 1).fill(0));
58
+ for (let i = 0; i < m; i++) {
59
+ for (let j = 0; j < n; j++) {
60
+ dp[i + 1][j + 1] = a[i] === b[j] ? dp[i][j] + 1 : Math.max(dp[i + 1][j], dp[i][j + 1]);
61
+ }
62
+ }
63
+ const items = [];
64
+ let i = m;
65
+ let j = n;
66
+ while (i > 0 && j > 0) {
67
+ if (a[i - 1] === b[j - 1]) {
68
+ items.push({ kind: 'same', line: a[i - 1] });
69
+ i--;
70
+ j--;
71
+ }
72
+ else if (dp[i - 1][j] >= dp[i][j - 1]) {
73
+ items.push({ kind: 'remove', line: a[i - 1] });
74
+ i--;
75
+ }
76
+ else {
77
+ items.push({ kind: 'add', line: b[j - 1] });
78
+ j--;
79
+ }
80
+ }
81
+ while (i > 0) {
82
+ items.push({ kind: 'remove', line: a[--i] });
83
+ }
84
+ while (j > 0) {
85
+ items.push({ kind: 'add', line: b[--j] });
86
+ }
87
+ items.reverse();
88
+ return items;
89
+ }
90
+ /** Group items into hunks that include `context` unchanged lines around each change. */
91
+ function buildHunks(items, context) {
92
+ const hunks = [];
93
+ let oldIdx = 0;
94
+ let newIdx = 0;
95
+ // First pass: mark index of every item in old/new streams
96
+ const marks = items.map((it) => {
97
+ const m = { item: it, oldIdx, newIdx };
98
+ if (it.kind !== 'add')
99
+ oldIdx++;
100
+ if (it.kind !== 'remove')
101
+ newIdx++;
102
+ return m;
103
+ });
104
+ let i = 0;
105
+ while (i < marks.length) {
106
+ if (marks[i].item.kind === 'same') {
107
+ i++;
108
+ continue;
109
+ }
110
+ // Change region: expand left by `context`, then run forward including
111
+ // intermediate small same-runs (≤ 2*context apart → merge).
112
+ const start = Math.max(0, i - context);
113
+ let end = i;
114
+ while (end < marks.length) {
115
+ if (marks[end].item.kind !== 'same') {
116
+ end++;
117
+ continue;
118
+ }
119
+ // Look ahead: is the next change within 2*context?
120
+ let sameRun = 0;
121
+ let k = end;
122
+ while (k < marks.length && marks[k].item.kind === 'same') {
123
+ sameRun++;
124
+ k++;
125
+ }
126
+ if (k >= marks.length || sameRun > 2 * context) {
127
+ // Close the hunk after `context` trailing same-lines.
128
+ end += Math.min(context, sameRun);
129
+ break;
130
+ }
131
+ end = k;
132
+ }
133
+ const slice = marks.slice(start, Math.min(end, marks.length));
134
+ hunks.push({
135
+ oldStart: marks[start].oldIdx,
136
+ newStart: marks[start].newIdx,
137
+ items: slice.map((s) => s.item),
138
+ });
139
+ i = end;
140
+ }
141
+ return hunks;
142
+ }
143
+ //# sourceMappingURL=diff.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diff.js","sourceRoot":"","sources":["../../src/utils/diff.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "openplanr",
3
- "version": "1.2.6",
3
+ "version": "1.2.8",
4
4
  "description": "AI-powered planning CLI — backlog, sprints, task templates, estimation, GitHub sync, and AI agent rules for Cursor, Claude Code, and Codex",
5
5
  "type": "module",
6
6
  "main": "./dist/cli/index.js",