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
@@ -0,0 +1,173 @@
1
+ /**
2
+ * Stakeholder report generation from context packs and Handlebars templates.
3
+ */
4
+ import path from 'node:path';
5
+ import { ensureDir, writeFile } from '../utils/fs.js';
6
+ import { logger } from '../utils/logger.js';
7
+ import { buildStakeholderReportContext } from './context-pack-service.js';
8
+ import { renderTemplate } from './template-service.js';
9
+ const TEMPLATE_BY_TYPE = {
10
+ sprint: 'reports/sprint.md.hbs',
11
+ weekly: 'reports/weekly.md.hbs',
12
+ executive: 'reports/executive.md.hbs',
13
+ standup: 'reports/standup.md.hbs',
14
+ retro: 'reports/retrospective.md.hbs',
15
+ release: 'reports/release-notes.md.hbs',
16
+ };
17
+ export function resolveReportTemplate(reportType) {
18
+ return TEMPLATE_BY_TYPE[reportType];
19
+ }
20
+ export async function generateStakeholderReportMarkdown(context, config) {
21
+ const templatePath = resolveReportTemplate(context.reportType);
22
+ try {
23
+ return await renderTemplate(templatePath, { ...context, json: JSON.stringify(context, null, 2) }, config.templateOverrides);
24
+ }
25
+ catch (err) {
26
+ logger.debug('report template render failed', err);
27
+ throw new Error(`Failed to render report template "${templatePath}": ${err.message}`);
28
+ }
29
+ }
30
+ function wrapHtmlDocument(title, bodyMarkdownAsHtml, accent) {
31
+ const color = accent || '#4169E1';
32
+ return `<!DOCTYPE html>
33
+ <html lang="en">
34
+ <head>
35
+ <meta charset="utf-8"/>
36
+ <meta name="viewport" content="width=device-width, initial-scale=1"/>
37
+ <title>${escapeHtml(title)}</title>
38
+ <style>
39
+ body { font-family: system-ui, sans-serif; max-width: 52rem; margin: 2rem auto; padding: 0 1rem; color: #111; }
40
+ h1 { border-bottom: 2px solid ${color}; padding-bottom: 0.25rem; }
41
+ h2 { margin-top: 1.75rem; color: #222; }
42
+ code, pre { background: #f4f4f4; padding: 0.2em 0.4em; border-radius: 4px; }
43
+ a { color: ${color}; }
44
+ .meta { color: #555; font-size: 0.9rem; }
45
+ </style>
46
+ </head>
47
+ <body>
48
+ <h1>${escapeHtml(title)}</h1>
49
+ <p class="meta">Generated by OpenPlanr</p>
50
+ <div class="content">
51
+ ${bodyMarkdownAsHtml}
52
+ </div>
53
+ </body>
54
+ </html>`;
55
+ }
56
+ function escapeHtml(s) {
57
+ return s
58
+ .replace(/&/g, '&amp;')
59
+ .replace(/</g, '&lt;')
60
+ .replace(/>/g, '&gt;')
61
+ .replace(/"/g, '&quot;');
62
+ }
63
+ function isSafeHttpUrl(url) {
64
+ try {
65
+ const u = new URL(url);
66
+ return u.protocol === 'http:' || u.protocol === 'https:';
67
+ }
68
+ catch {
69
+ return false;
70
+ }
71
+ }
72
+ /**
73
+ * Remove the first Markdown H1 line (and following blank lines) so HTML export does not
74
+ * duplicate the document title: wrapHtmlDocument() already injects a single <h1>.
75
+ */
76
+ export function stripLeadingMarkdownH1(md) {
77
+ const lines = md.split(/\r?\n/);
78
+ if (lines.length === 0)
79
+ return md;
80
+ const first = lines[0]?.trim() ?? '';
81
+ if (!/^#\s+.+$/.test(first))
82
+ return md;
83
+ let i = 1;
84
+ while (i < lines.length && lines[i]?.trim() === '')
85
+ i += 1;
86
+ return lines.slice(i).join('\n');
87
+ }
88
+ /** Minimal markdown → HTML for reports (headings, lists, links, paragraphs). */
89
+ export function markdownToBasicHtml(md) {
90
+ const lines = md.split(/\r?\n/);
91
+ const out = [];
92
+ let inUl = false;
93
+ const flushUl = () => {
94
+ if (inUl) {
95
+ out.push('</ul>');
96
+ inUl = false;
97
+ }
98
+ };
99
+ for (const line of lines) {
100
+ const h2 = line.match(/^## (.+)$/);
101
+ if (h2) {
102
+ flushUl();
103
+ out.push(`<h2>${escapeHtml(h2[1])}</h2>`);
104
+ continue;
105
+ }
106
+ const h1 = line.match(/^# (.+)$/);
107
+ if (h1) {
108
+ flushUl();
109
+ out.push(`<h1>${escapeHtml(h1[1])}</h1>`);
110
+ continue;
111
+ }
112
+ const li = line.match(/^\s*[-*]\s+(.+)$/);
113
+ if (li) {
114
+ if (!inUl) {
115
+ out.push('<ul>');
116
+ inUl = true;
117
+ }
118
+ out.push(`<li>${inlineMd(li[1])}</li>`);
119
+ continue;
120
+ }
121
+ if (line.trim() === '') {
122
+ flushUl();
123
+ continue;
124
+ }
125
+ flushUl();
126
+ out.push(`<p>${inlineMd(line)}</p>`);
127
+ }
128
+ flushUl();
129
+ return out.join('\n');
130
+ }
131
+ function inlineMd(text) {
132
+ let s = escapeHtml(text);
133
+ s = s.replace(/`([^`]+)`/g, '<code>$1</code>');
134
+ s = s.replace(/\[([^\]]+)\]\(([^)]+)\)/g, (_m, label, urlEsc) => {
135
+ const url = urlEsc.replace(/&amp;/g, '&');
136
+ if (isSafeHttpUrl(url)) {
137
+ return `<a href="${escapeHtml(url)}" rel="noopener noreferrer">${label}</a>`;
138
+ }
139
+ return `${label} (${urlEsc})`;
140
+ });
141
+ return s;
142
+ }
143
+ export async function formatStakeholderReportOutput(context, config, format) {
144
+ const markdown = await generateStakeholderReportMarkdown(context, config);
145
+ if (format === 'html') {
146
+ const inner = markdownToBasicHtml(stripLeadingMarkdownH1(markdown));
147
+ const title = `${context.projectName} — ${context.reportType} report`;
148
+ const html = wrapHtmlDocument(title, inner, context.branding?.accentColor);
149
+ return { markdown, html };
150
+ }
151
+ return { markdown };
152
+ }
153
+ export async function generateStakeholderReport(projectDir, config, opts) {
154
+ const context = await buildStakeholderReportContext(projectDir, config, opts);
155
+ const { markdown, html } = await formatStakeholderReportOutput(context, config, opts.format);
156
+ return { markdown, html, context };
157
+ }
158
+ export async function writeReportOutputs(args) {
159
+ const rel = args.outputDir ?? path.join(args.config.outputPaths.agile, 'reports');
160
+ const dir = path.join(args.projectDir, rel);
161
+ await ensureDir(dir);
162
+ const stamp = new Date().toISOString().split('T')[0];
163
+ const safe = args.baseName.replace(/[^a-z0-9-_]+/gi, '-').toLowerCase();
164
+ const mdPath = path.join(dir, `${stamp}-${safe}.md`);
165
+ await writeFile(mdPath, args.markdown);
166
+ let htmlPath;
167
+ if (args.html) {
168
+ htmlPath = path.join(dir, `${stamp}-${safe}.html`);
169
+ await writeFile(htmlPath, args.html);
170
+ }
171
+ return { mdPath, htmlPath };
172
+ }
173
+ //# sourceMappingURL=report-service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"report-service.js","sourceRoot":"","sources":["../../src/services/report-service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Content-hash run cache for `planr revise` (EPIC-003, FEAT-014 §2.0).
3
+ *
4
+ * Between runs, we hash each artifact's raw content (+ the codebase-digest
5
+ * input, when present) and skip artifacts whose hash matches the last
6
+ * successful revise of that artifact with the same codebase state. Keeps
7
+ * `--all` cheap to re-run on an untouched repo (a common check-before-PR
8
+ * workflow) without sacrificing correctness: any edit to the artifact or
9
+ * the codebase invalidates the cache entry automatically.
10
+ *
11
+ * Persisted at `.planr/reports/.revise-cache.json`. JSON was chosen over
12
+ * a line-oriented format because the cache is small (one entry per
13
+ * artifact) and atomic updates via atomicWriteFile are simpler with JSON.
14
+ *
15
+ * Cache semantics are best-effort: if the cache file is missing or
16
+ * malformed, reads return empty (never throw). Writes are fire-and-forget.
17
+ */
18
+ export interface ReviseCacheEntry {
19
+ artifactHash: string;
20
+ /** Digest over codebase-context-relevant state (folder tree, architecture files) — optional. */
21
+ codebaseHash?: string;
22
+ lastOutcome: 'skipped-by-agent' | 'applied' | 'would-apply' | 'flagged';
23
+ lastRunAt: string;
24
+ }
25
+ export interface ReviseCache {
26
+ entries: Record<string, ReviseCacheEntry>;
27
+ }
28
+ export declare function defaultCachePath(projectDir: string): string;
29
+ export declare function loadCache(projectDir: string): ReviseCache;
30
+ export declare function saveCache(projectDir: string, cache: ReviseCache): Promise<void>;
31
+ /** SHA-256 of the artifact raw content (body + frontmatter) used as cache key. */
32
+ export declare function hashArtifactContent(raw: string): string;
33
+ /** Optional SHA-256 over the codebase context string, so code changes invalidate cache. */
34
+ export declare function hashCodebaseContext(formatted?: string): string | undefined;
35
+ /**
36
+ * Returns true when the given artifact + codebase hash matches the cache
37
+ * entry from a prior successful revise — caller may skip the AI call.
38
+ * A mismatch on either dimension invalidates the entry.
39
+ */
40
+ export declare function shouldSkipArtifact(cache: ReviseCache, artifactId: string, artifactHash: string, codebaseHash: string | undefined): boolean;
41
+ /**
42
+ * Record an outcome in the cache. Returns a new cache object (pure) so
43
+ * callers can decide when to flush.
44
+ */
45
+ export declare function recordOutcome(cache: ReviseCache, artifactId: string, artifactHash: string, codebaseHash: string | undefined, outcome: ReviseCacheEntry['lastOutcome']): ReviseCache;
46
+ //# sourceMappingURL=revise-cache-service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"revise-cache-service.d.ts","sourceRoot":"","sources":["../../src/services/revise-cache-service.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAOH,MAAM,WAAW,gBAAgB;IAC/B,YAAY,EAAE,MAAM,CAAC;IACrB,gGAAgG;IAChG,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,kBAAkB,GAAG,SAAS,GAAG,aAAa,GAAG,SAAS,CAAC;IACxE,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;CAC3C;AAID,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAE3D;AAED,wBAAgB,SAAS,CAAC,UAAU,EAAE,MAAM,GAAG,WAAW,CAazD;AAED,wBAAsB,SAAS,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAErF;AAED,kFAAkF;AAClF,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAEvD;AAED,2FAA2F;AAC3F,wBAAgB,mBAAmB,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAG1E;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,WAAW,EAClB,UAAU,EAAE,MAAM,EAClB,YAAY,EAAE,MAAM,EACpB,YAAY,EAAE,MAAM,GAAG,SAAS,GAC/B,OAAO,CAOT;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAC3B,KAAK,EAAE,WAAW,EAClB,UAAU,EAAE,MAAM,EAClB,YAAY,EAAE,MAAM,EACpB,YAAY,EAAE,MAAM,GAAG,SAAS,EAChC,OAAO,EAAE,gBAAgB,CAAC,aAAa,CAAC,GACvC,WAAW,CAYb"}
@@ -0,0 +1,88 @@
1
+ /**
2
+ * Content-hash run cache for `planr revise` (EPIC-003, FEAT-014 §2.0).
3
+ *
4
+ * Between runs, we hash each artifact's raw content (+ the codebase-digest
5
+ * input, when present) and skip artifacts whose hash matches the last
6
+ * successful revise of that artifact with the same codebase state. Keeps
7
+ * `--all` cheap to re-run on an untouched repo (a common check-before-PR
8
+ * workflow) without sacrificing correctness: any edit to the artifact or
9
+ * the codebase invalidates the cache entry automatically.
10
+ *
11
+ * Persisted at `.planr/reports/.revise-cache.json`. JSON was chosen over
12
+ * a line-oriented format because the cache is small (one entry per
13
+ * artifact) and atomic updates via atomicWriteFile are simpler with JSON.
14
+ *
15
+ * Cache semantics are best-effort: if the cache file is missing or
16
+ * malformed, reads return empty (never throw). Writes are fire-and-forget.
17
+ */
18
+ import { createHash } from 'node:crypto';
19
+ import { existsSync, readFileSync } from 'node:fs';
20
+ import path from 'node:path';
21
+ import { atomicWriteFile } from './atomic-write-service.js';
22
+ const EMPTY = { entries: {} };
23
+ export function defaultCachePath(projectDir) {
24
+ return path.join(projectDir, '.planr', 'reports', '.revise-cache.json');
25
+ }
26
+ export function loadCache(projectDir) {
27
+ const p = defaultCachePath(projectDir);
28
+ if (!existsSync(p))
29
+ return { entries: {} };
30
+ try {
31
+ const raw = readFileSync(p, 'utf-8');
32
+ const parsed = JSON.parse(raw);
33
+ if (parsed && typeof parsed === 'object' && parsed.entries) {
34
+ return { entries: parsed.entries };
35
+ }
36
+ return EMPTY;
37
+ }
38
+ catch {
39
+ return EMPTY;
40
+ }
41
+ }
42
+ export async function saveCache(projectDir, cache) {
43
+ await atomicWriteFile(defaultCachePath(projectDir), JSON.stringify(cache, null, 2));
44
+ }
45
+ /** SHA-256 of the artifact raw content (body + frontmatter) used as cache key. */
46
+ export function hashArtifactContent(raw) {
47
+ return createHash('sha256').update(raw).digest('hex');
48
+ }
49
+ /** Optional SHA-256 over the codebase context string, so code changes invalidate cache. */
50
+ export function hashCodebaseContext(formatted) {
51
+ if (!formatted)
52
+ return undefined;
53
+ return createHash('sha256').update(formatted).digest('hex');
54
+ }
55
+ /**
56
+ * Returns true when the given artifact + codebase hash matches the cache
57
+ * entry from a prior successful revise — caller may skip the AI call.
58
+ * A mismatch on either dimension invalidates the entry.
59
+ */
60
+ export function shouldSkipArtifact(cache, artifactId, artifactHash, codebaseHash) {
61
+ const entry = cache.entries[artifactId];
62
+ if (!entry)
63
+ return false;
64
+ if (entry.artifactHash !== artifactHash)
65
+ return false;
66
+ if (entry.codebaseHash !== codebaseHash)
67
+ return false;
68
+ // Only cache-skip when the prior outcome indicated "nothing to do".
69
+ return entry.lastOutcome === 'skipped-by-agent';
70
+ }
71
+ /**
72
+ * Record an outcome in the cache. Returns a new cache object (pure) so
73
+ * callers can decide when to flush.
74
+ */
75
+ export function recordOutcome(cache, artifactId, artifactHash, codebaseHash, outcome) {
76
+ return {
77
+ entries: {
78
+ ...cache.entries,
79
+ [artifactId]: {
80
+ artifactHash,
81
+ codebaseHash,
82
+ lastOutcome: outcome,
83
+ lastRunAt: new Date().toISOString(),
84
+ },
85
+ },
86
+ };
87
+ }
88
+ //# sourceMappingURL=revise-cache-service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"revise-cache-service.js","sourceRoot":"","sources":["../../src/services/revise-cache-service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,108 @@
1
+ /**
2
+ * `planr revise` — core service (EPIC-003, FEAT-010 + FEAT-011).
3
+ *
4
+ * Exposes composable primitives; the CLI and future cascade service
5
+ * orchestrate them. Phase 1 (FEAT-010) ships `reviseArtifact` for dry-run
6
+ * decision generation; Phase 2 (FEAT-011) adds `applyDecision` for the
7
+ * write path and exposes the verifier context so callers can run
8
+ * `verifyDecision` against the same inputs the agent saw.
9
+ */
10
+ import { type RevisePromptArtifact, type ReviseWritableScope } from '../ai/prompts/prompt-builder.js';
11
+ import { type AIProvider, type AIUsage } from '../ai/types.js';
12
+ import type { ArtifactType, OpenPlanrConfig, ReviseAuditEntry, ReviseDecision } from '../models/types.js';
13
+ import type { AuditLogWriter } from './audit-log-service.js';
14
+ import type { EvidenceVerifierContext } from './evidence-verifier.js';
15
+ export interface ReviseArtifactOptions {
16
+ /** Must be `true` in Phase 1; reserved for future write path (FEAT-011). */
17
+ dryRun: true;
18
+ /** Which parts of the artifact the agent may modify. Default: 'all'. */
19
+ writableScope?: ReviseWritableScope;
20
+ /** Skip codebase context assembly (fast mode). Default: include code. */
21
+ noCodeContext?: boolean;
22
+ /** Skip immediate-sibling context gathering (fast mode / first-pass). Default: include. */
23
+ noSiblingContext?: boolean;
24
+ /** Maximum number of sibling artifacts to inject (budget guard). Default: 8. */
25
+ maxSiblings?: number;
26
+ }
27
+ export interface ReviseArtifactContextStats {
28
+ parentsLoaded: number;
29
+ siblingsLoaded: number;
30
+ codebaseContextIncluded: boolean;
31
+ sourcesLoaded: number;
32
+ }
33
+ export interface ReviseArtifactResult {
34
+ decision: ReviseDecision;
35
+ usage: AIUsage;
36
+ contextStats: ReviseArtifactContextStats;
37
+ /** Filesystem path the decision's revisedMarkdown would be written to. */
38
+ artifactPath: string;
39
+ /** Pre-revise raw content, used for diff rendering and auditing. */
40
+ originalContent: string;
41
+ /** Context the caller should pass to `verifyDecision`. */
42
+ verifierContext: EvidenceVerifierContext;
43
+ }
44
+ /**
45
+ * Error thrown when an artifact id cannot be resolved to an artifact type or
46
+ * the artifact file does not exist on disk.
47
+ */
48
+ export declare class ReviseArtifactNotFoundError extends Error {
49
+ readonly artifactId: string;
50
+ constructor(artifactId: string, message: string);
51
+ }
52
+ /**
53
+ * Revise a single artifact — Phase 1 dry-run.
54
+ *
55
+ * Does NOT write any files. The returned decision is the agent output after
56
+ * schema validation; evidence verification, diff preview, and write are all
57
+ * Phase 2 responsibilities (FEAT-011). Cascade, siblings, and declared
58
+ * sources are Phase 3 (FEAT-012) and onwards.
59
+ */
60
+ export declare function reviseArtifact(projectDir: string, config: OpenPlanrConfig, provider: AIProvider, artifactId: string, options: ReviseArtifactOptions): Promise<ReviseArtifactResult>;
61
+ export interface ApplyDecisionOptions {
62
+ artifactPath: string;
63
+ originalContent: string;
64
+ decision: ReviseDecision;
65
+ /**
66
+ * Directory where sidecar backups are written. Typically
67
+ * `.planr/reports/revise-<scope>-<date>/backup/` — set by the CLI.
68
+ */
69
+ backupDir: string;
70
+ /** Audit writer that will persist an entry describing the outcome. */
71
+ audit: AuditLogWriter;
72
+ /** When true, produces an audit entry but does not write the artifact. */
73
+ dryRun: boolean;
74
+ /** Cascade level tag for audit log grouping; omit for single-artifact runs. */
75
+ cascadeLevel?: ReviseAuditEntry['cascadeLevel'];
76
+ }
77
+ export interface ApplyDecisionResult {
78
+ outcome: ReviseAuditEntry['outcome'];
79
+ wrote: boolean;
80
+ diff: string;
81
+ }
82
+ /**
83
+ * Apply a (verified) decision: write the artifact atomically when
84
+ * `action === 'revise'` and `dryRun` is false, emit an audit entry
85
+ * describing the outcome either way.
86
+ *
87
+ * Caller is expected to have already run `verifyDecision` — `applyDecision`
88
+ * trusts that whatever decision arrives is allowed to be written.
89
+ */
90
+ export declare function applyDecision(options: ApplyDecisionOptions): Promise<ApplyDecisionResult>;
91
+ /**
92
+ * Load immediate-sibling artifacts (same artifact type, same parent) as
93
+ * prompt entries. Lazy-reads each sibling's body only if it's going to be
94
+ * included — the listing check is cheap, the reads are budgeted by
95
+ * `maxSiblings` (default 8) so the prompt stays within token budget even on
96
+ * epics with many features.
97
+ *
98
+ * For epic scope, there are no siblings (epics live at the top). For types
99
+ * without a parent-id relationship (quick, backlog, etc.), returns empty.
100
+ */
101
+ export declare function loadSiblingPromptArtifacts(projectDir: string, config: OpenPlanrConfig, type: ArtifactType, id: string, maxSiblings: number): Promise<RevisePromptArtifact[]>;
102
+ /**
103
+ * Resolve the parent chain for an artifact and return it as the ordered
104
+ * `RevisePromptArtifact[]` the prompt builder expects (epic → feature →
105
+ * story). Empty array for top-level artifacts (epic scope).
106
+ */
107
+ export declare function loadParentPromptArtifacts(projectDir: string, config: OpenPlanrConfig, type: ArtifactType, id: string): Promise<RevisePromptArtifact[]>;
108
+ //# sourceMappingURL=revise-service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"revise-service.d.ts","sourceRoot":"","sources":["../../src/services/revise-service.ts"],"names":[],"mappings":"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"}