@principles/core 1.75.0 → 1.77.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 (76) hide show
  1. package/dist/runtime-v2/__tests__/architecture-regression.test.js +14 -1
  2. package/dist/runtime-v2/__tests__/architecture-regression.test.js.map +1 -1
  3. package/dist/runtime-v2/__tests__/feedback/create-report.test.d.ts +2 -0
  4. package/dist/runtime-v2/__tests__/feedback/create-report.test.d.ts.map +1 -0
  5. package/dist/runtime-v2/__tests__/feedback/create-report.test.js +402 -0
  6. package/dist/runtime-v2/__tests__/feedback/create-report.test.js.map +1 -0
  7. package/dist/runtime-v2/__tests__/feedback/privacy-preview.test.d.ts +2 -0
  8. package/dist/runtime-v2/__tests__/feedback/privacy-preview.test.d.ts.map +1 -0
  9. package/dist/runtime-v2/__tests__/feedback/privacy-preview.test.js +128 -0
  10. package/dist/runtime-v2/__tests__/feedback/privacy-preview.test.js.map +1 -0
  11. package/dist/runtime-v2/__tests__/feedback/redact-sensitive.test.d.ts +2 -0
  12. package/dist/runtime-v2/__tests__/feedback/redact-sensitive.test.d.ts.map +1 -0
  13. package/dist/runtime-v2/__tests__/feedback/redact-sensitive.test.js +231 -0
  14. package/dist/runtime-v2/__tests__/feedback/redact-sensitive.test.js.map +1 -0
  15. package/dist/runtime-v2/__tests__/feedback/render-github-url.test.d.ts +2 -0
  16. package/dist/runtime-v2/__tests__/feedback/render-github-url.test.d.ts.map +1 -0
  17. package/dist/runtime-v2/__tests__/feedback/render-github-url.test.js +102 -0
  18. package/dist/runtime-v2/__tests__/feedback/render-github-url.test.js.map +1 -0
  19. package/dist/runtime-v2/__tests__/feedback/render-markdown.test.d.ts +2 -0
  20. package/dist/runtime-v2/__tests__/feedback/render-markdown.test.d.ts.map +1 -0
  21. package/dist/runtime-v2/__tests__/feedback/render-markdown.test.js +130 -0
  22. package/dist/runtime-v2/__tests__/feedback/render-markdown.test.js.map +1 -0
  23. package/dist/runtime-v2/__tests__/workspace-guidance-migration.test.d.ts +2 -0
  24. package/dist/runtime-v2/__tests__/workspace-guidance-migration.test.d.ts.map +1 -0
  25. package/dist/runtime-v2/__tests__/workspace-guidance-migration.test.js +328 -0
  26. package/dist/runtime-v2/__tests__/workspace-guidance-migration.test.js.map +1 -0
  27. package/dist/runtime-v2/feature-flags/__tests__/feature-flag-contract.test.js +11 -0
  28. package/dist/runtime-v2/feature-flags/__tests__/feature-flag-contract.test.js.map +1 -1
  29. package/dist/runtime-v2/feature-flags/feature-flag-contract.d.ts.map +1 -1
  30. package/dist/runtime-v2/feature-flags/feature-flag-contract.js +2 -1
  31. package/dist/runtime-v2/feature-flags/feature-flag-contract.js.map +1 -1
  32. package/dist/runtime-v2/feedback/create-report.d.ts +14 -0
  33. package/dist/runtime-v2/feedback/create-report.d.ts.map +1 -0
  34. package/dist/runtime-v2/feedback/create-report.js +257 -0
  35. package/dist/runtime-v2/feedback/create-report.js.map +1 -0
  36. package/dist/runtime-v2/feedback/feedback-types.d.ts +120 -0
  37. package/dist/runtime-v2/feedback/feedback-types.d.ts.map +1 -0
  38. package/dist/runtime-v2/feedback/feedback-types.js +243 -0
  39. package/dist/runtime-v2/feedback/feedback-types.js.map +1 -0
  40. package/dist/runtime-v2/feedback/index.d.ts +9 -0
  41. package/dist/runtime-v2/feedback/index.d.ts.map +1 -0
  42. package/dist/runtime-v2/feedback/index.js +11 -0
  43. package/dist/runtime-v2/feedback/index.js.map +1 -0
  44. package/dist/runtime-v2/feedback/internal-guards.d.ts +2 -0
  45. package/dist/runtime-v2/feedback/internal-guards.d.ts.map +1 -0
  46. package/dist/runtime-v2/feedback/internal-guards.js +6 -0
  47. package/dist/runtime-v2/feedback/internal-guards.js.map +1 -0
  48. package/dist/runtime-v2/feedback/privacy-preview.d.ts +14 -0
  49. package/dist/runtime-v2/feedback/privacy-preview.d.ts.map +1 -0
  50. package/dist/runtime-v2/feedback/privacy-preview.js +128 -0
  51. package/dist/runtime-v2/feedback/privacy-preview.js.map +1 -0
  52. package/dist/runtime-v2/feedback/redact-sensitive.d.ts +37 -0
  53. package/dist/runtime-v2/feedback/redact-sensitive.d.ts.map +1 -0
  54. package/dist/runtime-v2/feedback/redact-sensitive.js +272 -0
  55. package/dist/runtime-v2/feedback/redact-sensitive.js.map +1 -0
  56. package/dist/runtime-v2/feedback/render-github-url.d.ts +21 -0
  57. package/dist/runtime-v2/feedback/render-github-url.d.ts.map +1 -0
  58. package/dist/runtime-v2/feedback/render-github-url.js +57 -0
  59. package/dist/runtime-v2/feedback/render-github-url.js.map +1 -0
  60. package/dist/runtime-v2/feedback/render-markdown.d.ts +12 -0
  61. package/dist/runtime-v2/feedback/render-markdown.d.ts.map +1 -0
  62. package/dist/runtime-v2/feedback/render-markdown.js +166 -0
  63. package/dist/runtime-v2/feedback/render-markdown.js.map +1 -0
  64. package/dist/runtime-v2/feedback/safe-stringify.d.ts +6 -0
  65. package/dist/runtime-v2/feedback/safe-stringify.d.ts.map +1 -0
  66. package/dist/runtime-v2/feedback/safe-stringify.js +115 -0
  67. package/dist/runtime-v2/feedback/safe-stringify.js.map +1 -0
  68. package/dist/runtime-v2/index.d.ts +4 -0
  69. package/dist/runtime-v2/index.d.ts.map +1 -1
  70. package/dist/runtime-v2/index.js +9 -0
  71. package/dist/runtime-v2/index.js.map +1 -1
  72. package/dist/runtime-v2/workspace-guidance-migration.d.ts +12 -0
  73. package/dist/runtime-v2/workspace-guidance-migration.d.ts.map +1 -0
  74. package/dist/runtime-v2/workspace-guidance-migration.js +193 -0
  75. package/dist/runtime-v2/workspace-guidance-migration.js.map +1 -0
  76. package/package.json +5 -1
@@ -0,0 +1,9 @@
1
+ export type { FeedbackType, UserSeverity, FeedbackSource, FeedbackContext, AgentDraft, FeedbackUserText, FeedbackDraftInput, NormalizedDraft, RecentEvent, CanaryStatus, DiagnosticSummary, ContextRef, PrivacyPreview, FeedbackReport, ValidationError, NormalizeResult, } from './feedback-types.js';
2
+ export { isFeedbackType, isUserSeverity, isFeedbackSource, isRecord, isBoolean, normalizeFeedbackDraftInput, } from './feedback-types.js';
3
+ export { redactAbsolutePaths, redactTokenLikeValues, redactEnvLikeValues, redactStackTrace, redactSensitiveFields, REDACTED_PATH, REDACTED_VALUE, NO_STACK, type RedactResult, } from './redact-sensitive.js';
4
+ export { renderReportMarkdown, MAX_MARKDOWN_LENGTH } from './render-markdown.js';
5
+ export { buildGitHubIssueDraftUrl, MAX_URL_BODY_LENGTH, GITHUB_REPO, type GithubUrlResult, } from './render-github-url.js';
6
+ export { buildPrivacyPreview, buildEmailText, DEFAULT_INCLUDED_SECTIONS, DEFAULT_EXCLUDED_CATEGORIES, } from './privacy-preview.js';
7
+ export { createFeedbackReport, type CreateReportResult } from './create-report.js';
8
+ export { safeStringifyPreview } from './safe-stringify.js';
9
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/runtime-v2/feedback/index.ts"],"names":[],"mappings":"AAIA,YAAY,EACV,YAAY,EACZ,YAAY,EACZ,cAAc,EACd,eAAe,EACf,UAAU,EACV,gBAAgB,EAChB,kBAAkB,EAClB,eAAe,EACf,WAAW,EACX,YAAY,EACZ,iBAAiB,EACjB,UAAU,EACV,cAAc,EACd,cAAc,EACd,eAAe,EACf,eAAe,GAChB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EACL,cAAc,EACd,cAAc,EACd,gBAAgB,EAChB,QAAQ,EACR,SAAS,EACT,2BAA2B,GAC5B,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EACL,mBAAmB,EACnB,qBAAqB,EACrB,mBAAmB,EACnB,gBAAgB,EAChB,qBAAqB,EACrB,aAAa,EACb,cAAc,EACd,QAAQ,EACR,KAAK,YAAY,GAClB,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAEjF,OAAO,EACL,wBAAwB,EACxB,mBAAmB,EACnB,WAAW,EACX,KAAK,eAAe,GACrB,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EACL,mBAAmB,EACnB,cAAc,EACd,yBAAyB,EACzB,2BAA2B,GAC5B,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EAAE,oBAAoB,EAAE,KAAK,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAEnF,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC"}
@@ -0,0 +1,11 @@
1
+ // feedback/index.ts
2
+ // Barrel re-exports for the feedback report contract.
3
+ // Pure logic only — no I/O, no fs, no process, no db, no network.
4
+ export { isFeedbackType, isUserSeverity, isFeedbackSource, isRecord, isBoolean, normalizeFeedbackDraftInput, } from './feedback-types.js';
5
+ export { redactAbsolutePaths, redactTokenLikeValues, redactEnvLikeValues, redactStackTrace, redactSensitiveFields, REDACTED_PATH, REDACTED_VALUE, NO_STACK, } from './redact-sensitive.js';
6
+ export { renderReportMarkdown, MAX_MARKDOWN_LENGTH } from './render-markdown.js';
7
+ export { buildGitHubIssueDraftUrl, MAX_URL_BODY_LENGTH, GITHUB_REPO, } from './render-github-url.js';
8
+ export { buildPrivacyPreview, buildEmailText, DEFAULT_INCLUDED_SECTIONS, DEFAULT_EXCLUDED_CATEGORIES, } from './privacy-preview.js';
9
+ export { createFeedbackReport } from './create-report.js';
10
+ export { safeStringifyPreview } from './safe-stringify.js';
11
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/runtime-v2/feedback/index.ts"],"names":[],"mappings":"AAAA,oBAAoB;AACpB,sDAAsD;AACtD,kEAAkE;AAqBlE,OAAO,EACL,cAAc,EACd,cAAc,EACd,gBAAgB,EAChB,QAAQ,EACR,SAAS,EACT,2BAA2B,GAC5B,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EACL,mBAAmB,EACnB,qBAAqB,EACrB,mBAAmB,EACnB,gBAAgB,EAChB,qBAAqB,EACrB,aAAa,EACb,cAAc,EACd,QAAQ,GAET,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAEjF,OAAO,EACL,wBAAwB,EACxB,mBAAmB,EACnB,WAAW,GAEZ,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EACL,mBAAmB,EACnB,cAAc,EACd,yBAAyB,EACzB,2BAA2B,GAC5B,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EAAE,oBAAoB,EAA2B,MAAM,oBAAoB,CAAC;AAEnF,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare function isString(value: unknown): value is string;
2
+ //# sourceMappingURL=internal-guards.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"internal-guards.d.ts","sourceRoot":"","sources":["../../../src/runtime-v2/feedback/internal-guards.ts"],"names":[],"mappings":"AAGA,wBAAgB,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CAExD"}
@@ -0,0 +1,6 @@
1
+ // internal-guards.ts
2
+ // Re-exported shared primitive guards used across the feedback module.
3
+ export function isString(value) {
4
+ return typeof value === 'string';
5
+ }
6
+ //# sourceMappingURL=internal-guards.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"internal-guards.js","sourceRoot":"","sources":["../../../src/runtime-v2/feedback/internal-guards.ts"],"names":[],"mappings":"AAAA,qBAAqB;AACrB,uEAAuE;AAEvE,MAAM,UAAU,QAAQ,CAAC,KAAc;IACrC,OAAO,OAAO,KAAK,KAAK,QAAQ,CAAC;AACnC,CAAC"}
@@ -0,0 +1,14 @@
1
+ import type { FeedbackReport, PrivacyPreview } from './feedback-types.js';
2
+ export declare const DEFAULT_INCLUDED_SECTIONS: readonly string[];
3
+ export declare const DEFAULT_EXCLUDED_CATEGORIES: readonly string[];
4
+ /**
5
+ * Build a fresh PrivacyPreview object. Each call returns new arrays so callers
6
+ * may mutate the result without affecting the defaults.
7
+ */
8
+ export declare function buildPrivacyPreview(redactionNotes: string[]): PrivacyPreview;
9
+ /**
10
+ * Build an email-ready plain-text version of a FeedbackReport.
11
+ * Uses real '\n' newlines. BigInt/cycle-safe via safeStringifyPreview.
12
+ */
13
+ export declare function buildEmailText(report: FeedbackReport): string;
14
+ //# sourceMappingURL=privacy-preview.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"privacy-preview.d.ts","sourceRoot":"","sources":["../../../src/runtime-v2/feedback/privacy-preview.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAI1E,eAAO,MAAM,yBAAyB,EAAE,SAAS,MAAM,EAOtD,CAAC;AAEF,eAAO,MAAM,2BAA2B,EAAE,SAAS,MAAM,EASxD,CAAC;AAEF;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,cAAc,EAAE,MAAM,EAAE,GAAG,cAAc,CAM5E;AAWD;;;GAGG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,cAAc,GAAG,MAAM,CA4E7D"}
@@ -0,0 +1,128 @@
1
+ // privacy-preview.ts
2
+ // Privacy metadata and email-text rendering.
3
+ // ERR-014/016/017: correct '\n' newlines, BigInt-safe, never throws on cycles.
4
+ import { safeStringifyPreview } from './safe-stringify.js';
5
+ import { redactAbsolutePaths, redactTokenLikeValues, redactEnvLikeValues } from './redact-sensitive.js';
6
+ export const DEFAULT_INCLUDED_SECTIONS = [
7
+ 'versions',
8
+ 'platform',
9
+ 'featureFlags',
10
+ 'canary',
11
+ 'userText',
12
+ 'contextIds',
13
+ ];
14
+ export const DEFAULT_EXCLUDED_CATEGORIES = [
15
+ 'rawPrompt',
16
+ 'rawChat',
17
+ 'rawTrajectory',
18
+ 'fileContents',
19
+ 'fullPaths',
20
+ 'envVars',
21
+ 'tokens',
22
+ 'fullStackTraces',
23
+ ];
24
+ /**
25
+ * Build a fresh PrivacyPreview object. Each call returns new arrays so callers
26
+ * may mutate the result without affecting the defaults.
27
+ */
28
+ export function buildPrivacyPreview(redactionNotes) {
29
+ return {
30
+ includedSections: [...DEFAULT_INCLUDED_SECTIONS],
31
+ excludedByDefault: [...DEFAULT_EXCLUDED_CATEGORIES],
32
+ redactionNotes: redactionNotes.slice(),
33
+ };
34
+ }
35
+ const MAX_EMAIL_FIELD = 1500;
36
+ const MAX_EMAIL_DIAGNOSTIC_FIELD = 1200;
37
+ function safe(s, max) {
38
+ if (typeof s !== 'string')
39
+ return '';
40
+ if (s.length <= max)
41
+ return s;
42
+ return s.slice(0, max) + '…';
43
+ }
44
+ /**
45
+ * Build an email-ready plain-text version of a FeedbackReport.
46
+ * Uses real '\n' newlines. BigInt/cycle-safe via safeStringifyPreview.
47
+ */
48
+ export function buildEmailText(report) {
49
+ const lines = [];
50
+ lines.push(`Subject: [PD feedback] [${report.type}] ${redactAbsolutePaths(report.title)}`);
51
+ lines.push('');
52
+ lines.push('— PD Feedback Report —');
53
+ lines.push(`ID: ${report.id}`);
54
+ lines.push(`Created: ${report.createdAt}`);
55
+ if (report.userText.userSeverity) {
56
+ lines.push(`User severity: ${report.userText.userSeverity}`);
57
+ }
58
+ lines.push('');
59
+ lines.push('— Description —');
60
+ lines.push(safe(report.userText.description, MAX_EMAIL_FIELD));
61
+ if (report.userText.stepsToReproduce) {
62
+ lines.push('');
63
+ lines.push('— Steps to reproduce —');
64
+ lines.push(safe(report.userText.stepsToReproduce, MAX_EMAIL_FIELD));
65
+ }
66
+ if (report.userText.expectedBehavior) {
67
+ lines.push('');
68
+ lines.push('— Expected behavior —');
69
+ lines.push(safe(report.userText.expectedBehavior, MAX_EMAIL_FIELD));
70
+ }
71
+ if (report.userText.actualBehavior) {
72
+ lines.push('');
73
+ lines.push('— Actual behavior —');
74
+ lines.push(safe(report.userText.actualBehavior, MAX_EMAIL_FIELD));
75
+ }
76
+ lines.push('');
77
+ lines.push('— Diagnostics (low-sensitivity) —');
78
+ lines.push('versions:');
79
+ lines.push(safeStringifyPreview(report.diagnosticSummary.versions).slice(0, MAX_EMAIL_DIAGNOSTIC_FIELD));
80
+ lines.push('platform:');
81
+ lines.push(safeStringifyPreview(report.diagnosticSummary.platform).slice(0, MAX_EMAIL_DIAGNOSTIC_FIELD));
82
+ lines.push('featureFlags:');
83
+ lines.push(safeStringifyPreview(report.diagnosticSummary.featureFlags).slice(0, MAX_EMAIL_DIAGNOSTIC_FIELD));
84
+ if (report.diagnosticSummary.canary.status === 'available') {
85
+ lines.push(`canary: available${report.diagnosticSummary.canary.summary ? ` — ${report.diagnosticSummary.canary.summary}` : ''}`);
86
+ }
87
+ else {
88
+ lines.push(`canary: unavailable${report.diagnosticSummary.canary.unavailableReason ? ` — ${report.diagnosticSummary.canary.unavailableReason}` : ''}`);
89
+ }
90
+ if (report.contextRefs.length > 0) {
91
+ lines.push('');
92
+ lines.push('— Context references —');
93
+ const maxContextRefs = 12;
94
+ const shownRefs = report.contextRefs.slice(0, maxContextRefs);
95
+ for (const r of shownRefs) {
96
+ const label = r.label ? ` — ${r.label}` : '';
97
+ lines.push(`- ${r.kind}: ${r.id}${label}`);
98
+ }
99
+ if (report.contextRefs.length > maxContextRefs) {
100
+ lines.push(`- … and ${report.contextRefs.length - maxContextRefs} more`);
101
+ }
102
+ }
103
+ lines.push('');
104
+ lines.push('— Privacy —');
105
+ lines.push('Included by default:');
106
+ for (const s of report.privacy.includedSections)
107
+ lines.push(`- ${s}`);
108
+ lines.push('Excluded by default:');
109
+ for (const s of report.privacy.excludedByDefault)
110
+ lines.push(`- ${s}`);
111
+ if (report.privacy.redactionNotes.length > 0) {
112
+ lines.push('Redaction notes:');
113
+ const maxNotes = 12;
114
+ const shownNotes = report.privacy.redactionNotes.slice(0, maxNotes);
115
+ for (const n of shownNotes)
116
+ lines.push(`- ${n}`);
117
+ if (report.privacy.redactionNotes.length > maxNotes) {
118
+ lines.push(`- … and ${report.privacy.redactionNotes.length - maxNotes} more`);
119
+ }
120
+ }
121
+ // Defense-in-depth: scrub any absolute path / token / env value that slipped through.
122
+ let email = lines.join('\n');
123
+ email = redactAbsolutePaths(email);
124
+ email = redactTokenLikeValues(email);
125
+ email = redactEnvLikeValues(email);
126
+ return email;
127
+ }
128
+ //# sourceMappingURL=privacy-preview.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"privacy-preview.js","sourceRoot":"","sources":["../../../src/runtime-v2/feedback/privacy-preview.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,37 @@
1
+ export declare const REDACTED_PATH = "<redacted-path>";
2
+ export declare const REDACTED_VALUE = "[REDACTED]";
3
+ export declare const NO_STACK = "<no-stack>";
4
+ /**
5
+ * Replace absolute paths with `<redacted-path>`. Relative paths are left alone.
6
+ */
7
+ export declare function redactAbsolutePaths(text: string): string;
8
+ /**
9
+ * Replace token-like values with `[REDACTED]`.
10
+ */
11
+ export declare function redactTokenLikeValues(text: string): string;
12
+ export declare function redactEnvLikeValues(text: string): string;
13
+ /**
14
+ * Reduce a stack trace to the error name and the first N frames (paths redacted).
15
+ * Empty input returns `<no-stack>`.
16
+ */
17
+ export declare function redactStackTrace(text: string, maxFrames?: number): string;
18
+ export type RedactResult = {
19
+ ok: true;
20
+ value: unknown;
21
+ notes: string[];
22
+ } | {
23
+ ok: false;
24
+ error: string;
25
+ nextAction: string;
26
+ };
27
+ /**
28
+ * Recursively redact sensitive fields in an unknown value.
29
+ * Never throws. Returns a structured result with notes describing what was redacted.
30
+ *
31
+ * ERR-002: returns `{ok:false,error,nextAction}` for non-object top-level input
32
+ * because field redaction is a structured-data operation. Primitives carry no
33
+ * fields; their values should be sanitized via `redactTokenLikeValues` /
34
+ * `redactEnvLikeValues` / `redactAbsolutePaths` instead.
35
+ */
36
+ export declare function redactSensitiveFields(value: unknown): RedactResult;
37
+ //# sourceMappingURL=redact-sensitive.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"redact-sensitive.d.ts","sourceRoot":"","sources":["../../../src/runtime-v2/feedback/redact-sensitive.ts"],"names":[],"mappings":"AAOA,eAAO,MAAM,aAAa,oBAAoB,CAAC;AAC/C,eAAO,MAAM,cAAc,eAAe,CAAC;AAC3C,eAAO,MAAM,QAAQ,eAAe,CAAC;AAWrC;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAGxD;AAaD;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAO1D;AAOD,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAGxD;AAMD;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,GAAE,MAAiC,GAAG,MAAM,CAUnG;AAyCD,MAAM,MAAM,YAAY,GACpB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,MAAM,EAAE,CAAA;CAAE,GAC7C;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CAAC;AAgIrD;;;;;;;;GAQG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,OAAO,GAAG,YAAY,CA2BlE"}
@@ -0,0 +1,272 @@
1
+ // redact-sensitive.ts
2
+ // Privacy-preserving redaction helpers used by the feedback pipeline.
3
+ // ERR-001/005: no `as` casts on untrusted values.
4
+ // ERR-002: never throws; pipeline functions return either a string or a structured result with notes.
5
+ // ERR-003: segment-exact key matching (e.g. "authorization", "auth_token"), never substring ("author" must NOT match).
6
+ // ERR-014/016: bounded output.
7
+ export const REDACTED_PATH = '<redacted-path>';
8
+ export const REDACTED_VALUE = '[REDACTED]';
9
+ export const NO_STACK = '<no-stack>';
10
+ const MAX_STACK_FRAMES_DEFAULT = 3;
11
+ // ── Path redaction ──────────────────────────────────────────────────────────
12
+ // Windows: C:\Users\alice\... D:\foo\bar E:/...
13
+ const WINDOWS_PATH = /(?:[A-Za-z]:[\\/](?:[^\\\s/:*?"<>|]+[\\/])+[^\\\s/:*?"<>|]*)/g;
14
+ // POSIX: /home/alice/... /usr/local/bin/...
15
+ const POSIX_PATH = /(?:\/(?:usr|home|var|opt|etc|tmp|root|run|mnt|media|srv|boot|dev|proc|sys)(?:\/[^\\\s/:*?"<>|]+)+)/g;
16
+ /**
17
+ * Replace absolute paths with `<redacted-path>`. Relative paths are left alone.
18
+ */
19
+ export function redactAbsolutePaths(text) {
20
+ if (typeof text !== 'string')
21
+ return text;
22
+ return text.replace(WINDOWS_PATH, REDACTED_PATH).replace(POSIX_PATH, REDACTED_PATH);
23
+ }
24
+ // ── Token redaction ─────────────────────────────────────────────────────────
25
+ // OpenAI sk-..., Anthropic sk-ant-..., generic sk-_...
26
+ const OPENAI_TOKEN = /\bsk-(?:ant-)?[A-Za-z0-9_-]{16,}\b/g;
27
+ // GitHub tokens: ghp_, gho_, ghu_, ghs_, ghr_
28
+ const GITHUB_TOKEN = /\bgh[pousr]_[A-Za-z0-9]{16,}\b/g;
29
+ // Generic api_key= / token= / secret= / password= assignments
30
+ const KEY_ASSIGN = /\b(api[_-]?key|token|secret|password|auth(?:_?token)?)\s*[:=]\s*['"]?([^\s'",}{]+)['"]?/gi;
31
+ // Bearer headers
32
+ const BEARER = /\bBearer\s+[A-Za-z0-9._\-+/=]{8,}\b/g;
33
+ /**
34
+ * Replace token-like values with `[REDACTED]`.
35
+ */
36
+ export function redactTokenLikeValues(text) {
37
+ if (typeof text !== 'string')
38
+ return text;
39
+ return text
40
+ .replace(OPENAI_TOKEN, REDACTED_VALUE)
41
+ .replace(GITHUB_TOKEN, REDACTED_VALUE)
42
+ .replace(BEARER, REDACTED_VALUE)
43
+ .replace(KEY_ASSIGN, (_m, key) => `${key}=${REDACTED_VALUE}`);
44
+ }
45
+ // ── Environment-like value redaction ────────────────────────────────────────
46
+ // KEY=value (basic) / KEY="value with spaces"
47
+ const ENV_ASSIGN = /\b([A-Z_][A-Z0-9_]{2,})\s*=\s*(?:"([^"]*)"|'([^']*)'|([^\s,;}{]+))/g;
48
+ export function redactEnvLikeValues(text) {
49
+ if (typeof text !== 'string')
50
+ return text;
51
+ return text.replace(ENV_ASSIGN, (_m, key) => `${key}=${REDACTED_VALUE}`);
52
+ }
53
+ // ── Stack trace redaction ──────────────────────────────────────────────────
54
+ const STACK_FRAME_LINE = /^\s*at\s+.*$/gm;
55
+ /**
56
+ * Reduce a stack trace to the error name and the first N frames (paths redacted).
57
+ * Empty input returns `<no-stack>`.
58
+ */
59
+ export function redactStackTrace(text, maxFrames = MAX_STACK_FRAMES_DEFAULT) {
60
+ if (typeof text !== 'string' || text.length === 0)
61
+ return NO_STACK;
62
+ const firstLine = text.split('\n', 1)[0]?.trim() ?? '';
63
+ const frames = text.match(STACK_FRAME_LINE) ?? [];
64
+ const kept = frames
65
+ .slice(0, Math.max(0, maxFrames))
66
+ .map((f) => f.replace(WINDOWS_PATH, REDACTED_PATH).replace(POSIX_PATH, REDACTED_PATH))
67
+ .join('\n');
68
+ if (!kept)
69
+ return firstLine || NO_STACK;
70
+ return kept.includes(firstLine) ? kept : `${firstLine}\n${kept}`;
71
+ }
72
+ // ── Structured field redaction ──────────────────────────────────────────────
73
+ /**
74
+ * Segment-exact sensitive key names (split on `_-`).
75
+ * ERR-003 fix: do not match substrings like "author" → "auth".
76
+ */
77
+ const SENSITIVE_KEY_SEGMENTS = new Set([
78
+ 'password',
79
+ 'passwd',
80
+ 'secret',
81
+ 'token',
82
+ 'api',
83
+ 'apikey',
84
+ 'authorization',
85
+ 'auth',
86
+ 'credential',
87
+ 'credentials',
88
+ 'private',
89
+ 'key',
90
+ ]);
91
+ function segmentsOfKey(key) {
92
+ return key
93
+ .toLowerCase()
94
+ .split(/[_\-.]/g)
95
+ .filter((s) => s.length > 0);
96
+ }
97
+ function isSensitiveKey(key) {
98
+ const segs = segmentsOfKey(key);
99
+ if (segs.length === 0)
100
+ return false;
101
+ // A key is sensitive if ANY of its segments matches a sensitive segment.
102
+ // This catches composite names like "github_token" or "db_password".
103
+ for (const seg of segs) {
104
+ if (SENSITIVE_KEY_SEGMENTS.has(seg))
105
+ return true;
106
+ }
107
+ return false;
108
+ }
109
+ const REDACT_MAX_DEPTH = 6;
110
+ const REDACT_MAX_KEYS = 100;
111
+ const REDACT_MAX_STRING = 2000;
112
+ // Internal helpers (defined above the public entry point to satisfy
113
+ // `no-use-before-define` while still being hoisted via `function` declarations).
114
+ function redactInner(value, ctx) {
115
+ if (value === null)
116
+ return { ok: true, value: null, notes: [] };
117
+ if (value === undefined)
118
+ return { ok: true, value: undefined, notes: [] };
119
+ const t = typeof value;
120
+ if (t === 'string') {
121
+ let s = value;
122
+ const original = s;
123
+ // Run string through path/token/env redactors before truncation so
124
+ // secrets embedded in values (e.g. buildId, cwd) are cleaned regardless of key name.
125
+ s = redactAbsolutePaths(s);
126
+ s = redactTokenLikeValues(s);
127
+ s = redactEnvLikeValues(s);
128
+ if (s !== original) {
129
+ ctx.notes.push('string value redacted (path/token/env)');
130
+ }
131
+ if (s.length > REDACT_MAX_STRING) {
132
+ s = s.slice(0, REDACT_MAX_STRING) + '…';
133
+ ctx.notes.push(`string truncated to ${REDACT_MAX_STRING} chars`);
134
+ }
135
+ return { ok: true, value: s, notes: ctx.notes };
136
+ }
137
+ if (t === 'bigint') {
138
+ // BigInt-safe preview: encode as a string marker so JSON.stringify callers don't throw
139
+ return { ok: true, value: `<bigint:${value.toString()}>`, notes: [] };
140
+ }
141
+ if (t !== 'object') {
142
+ return { ok: true, value, notes: [] };
143
+ }
144
+ if (ctx.depth >= REDACT_MAX_DEPTH) {
145
+ return { ok: true, value: '<deep>', notes: [] };
146
+ }
147
+ const obj = value;
148
+ if (ctx.seen.has(obj)) {
149
+ ctx.notes.push('circular reference detected');
150
+ return { ok: true, value: '<circular>', notes: [] };
151
+ }
152
+ ctx.seen.add(obj);
153
+ try {
154
+ if (Array.isArray(value)) {
155
+ const arr = [];
156
+ for (let i = 0; i < value.length; i++) {
157
+ const r = redactInner(value[i], { seen: ctx.seen, depth: ctx.depth + 1, notes: ctx.notes });
158
+ if (!r.ok)
159
+ return r;
160
+ arr.push(r.value);
161
+ }
162
+ return { ok: true, value: arr, notes: [] };
163
+ }
164
+ const record = value;
165
+ const out = {};
166
+ const keys = Object.keys(record).slice(0, REDACT_MAX_KEYS);
167
+ for (const k of keys) {
168
+ if (isSensitiveKey(k)) {
169
+ out[k] = REDACTED_VALUE;
170
+ ctx.notes.push(`field "${k}" redacted`);
171
+ continue;
172
+ }
173
+ const v = record[k];
174
+ if (v !== null && typeof v === 'object' && ctx.seen.has(v)) {
175
+ ctx.notes.push(`circular reference detected at "${k}"`);
176
+ out[k] = '<circular>';
177
+ continue;
178
+ }
179
+ const r = redactInner(v, { seen: ctx.seen, depth: ctx.depth + 1, notes: ctx.notes });
180
+ if (!r.ok)
181
+ return r;
182
+ out[k] = r.value;
183
+ }
184
+ return { ok: true, value: out, notes: [] };
185
+ }
186
+ finally {
187
+ ctx.seen.delete(obj);
188
+ }
189
+ }
190
+ function redactArray(arr) {
191
+ const notes = [];
192
+ const out = [];
193
+ const ctx = { seen: new WeakSet(), depth: 0, notes };
194
+ ctx.seen.add(arr);
195
+ for (let i = 0; i < arr.length; i++) {
196
+ const item = arr[i];
197
+ if (item !== null && typeof item === 'object' && ctx.seen.has(item)) {
198
+ notes.push('circular reference detected in array');
199
+ out.push('<circular>');
200
+ continue;
201
+ }
202
+ const r = redactInner(item, ctx);
203
+ if (!r.ok)
204
+ return r;
205
+ out.push(r.value);
206
+ }
207
+ return { ok: true, value: out, notes };
208
+ }
209
+ function redactObject(obj) {
210
+ const rec = obj;
211
+ const notes = [];
212
+ const ctx = { seen: new WeakSet(), depth: 0, notes };
213
+ ctx.seen.add(obj);
214
+ const out = {};
215
+ const keys = Object.keys(rec).slice(0, REDACT_MAX_KEYS);
216
+ for (const k of keys) {
217
+ if (isSensitiveKey(k)) {
218
+ out[k] = REDACTED_VALUE;
219
+ notes.push(`field "${k}" redacted`);
220
+ continue;
221
+ }
222
+ const v = rec[k];
223
+ if (v !== null && typeof v === 'object' && ctx.seen.has(v)) {
224
+ notes.push(`circular reference detected at "${k}"`);
225
+ out[k] = '<circular>';
226
+ continue;
227
+ }
228
+ const r = redactInner(v, ctx);
229
+ if (!r.ok)
230
+ return r;
231
+ out[k] = r.value;
232
+ }
233
+ return { ok: true, value: out, notes };
234
+ }
235
+ /**
236
+ * Recursively redact sensitive fields in an unknown value.
237
+ * Never throws. Returns a structured result with notes describing what was redacted.
238
+ *
239
+ * ERR-002: returns `{ok:false,error,nextAction}` for non-object top-level input
240
+ * because field redaction is a structured-data operation. Primitives carry no
241
+ * fields; their values should be sanitized via `redactTokenLikeValues` /
242
+ * `redactEnvLikeValues` / `redactAbsolutePaths` instead.
243
+ */
244
+ export function redactSensitiveFields(value) {
245
+ if (value === null) {
246
+ return {
247
+ ok: false,
248
+ error: 'redactSensitiveFields: null is not a redactable object',
249
+ nextAction: 'pass a JSON object or array; null carries no fields to redact',
250
+ };
251
+ }
252
+ if (value === undefined) {
253
+ return {
254
+ ok: false,
255
+ error: 'redactSensitiveFields: undefined is not a redactable object',
256
+ nextAction: 'pass a JSON object or array; undefined carries no fields to redact',
257
+ };
258
+ }
259
+ const t = typeof value;
260
+ if (t !== 'object') {
261
+ return {
262
+ ok: false,
263
+ error: `redactSensitiveFields: top-level value must be an object or array (got ${t})`,
264
+ nextAction: 'pass a JSON object or array; for primitive values use redactTokenLikeValues / redactEnvLikeValues / redactAbsolutePaths',
265
+ };
266
+ }
267
+ if (Array.isArray(value)) {
268
+ return redactArray(value);
269
+ }
270
+ return redactObject(value);
271
+ }
272
+ //# sourceMappingURL=redact-sensitive.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"redact-sensitive.js","sourceRoot":"","sources":["../../../src/runtime-v2/feedback/redact-sensitive.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ import type { FeedbackType } from './feedback-types.js';
2
+ export declare const MAX_URL_BODY_LENGTH = 500;
3
+ export declare const GITHUB_REPO = "csuzngjh/principles";
4
+ export type GithubUrlResult = {
5
+ ok: true;
6
+ url: string;
7
+ } | {
8
+ ok: false;
9
+ error: string;
10
+ nextAction: string;
11
+ };
12
+ /**
13
+ * Build a `https://github.com/<repo>/issues/new?...` URL containing a redacted
14
+ * title and a short summary as the body. Body is bounded to MAX_URL_BODY_LENGTH.
15
+ *
16
+ * ERR-014/016: body is truncated to MAX_URL_BODY_LENGTH before encoding so the
17
+ * decoded body never exceeds the bound. Newlines inside the body are encoded
18
+ * as %0A by `encodeURIComponent`, preserving the markdown structure.
19
+ */
20
+ export declare function buildGitHubIssueDraftUrl(title: string, type: FeedbackType | unknown, shortSummary: string): GithubUrlResult;
21
+ //# sourceMappingURL=render-github-url.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"render-github-url.d.ts","sourceRoot":"","sources":["../../../src/runtime-v2/feedback/render-github-url.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAIxD,eAAO,MAAM,mBAAmB,MAAM,CAAC;AACvC,eAAO,MAAM,WAAW,wBAAwB,CAAC;AAEjD,MAAM,MAAM,eAAe,GACvB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GACzB;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CAAC;AAOrD;;;;;;;GAOG;AACH,wBAAgB,wBAAwB,CACtC,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,YAAY,GAAG,OAAO,EAC5B,YAAY,EAAE,MAAM,GACnB,eAAe,CAsCjB"}
@@ -0,0 +1,57 @@
1
+ // render-github-url.ts
2
+ // Builds a bounded GitHub issue draft URL.
3
+ // ERR-001/005: no `as FeedbackType` cast; use isFeedbackType validator.
4
+ // ERR-014/016: correct '\n' newlines, bounded body.
5
+ import { isFeedbackType } from './feedback-types.js';
6
+ import { redactAbsolutePaths, redactTokenLikeValues, redactEnvLikeValues } from './redact-sensitive.js';
7
+ export const MAX_URL_BODY_LENGTH = 500;
8
+ export const GITHUB_REPO = 'csuzngjh/principles';
9
+ function truncateToMax(s, max) {
10
+ if (s.length <= max)
11
+ return s;
12
+ return s.slice(0, max);
13
+ }
14
+ /**
15
+ * Build a `https://github.com/<repo>/issues/new?...` URL containing a redacted
16
+ * title and a short summary as the body. Body is bounded to MAX_URL_BODY_LENGTH.
17
+ *
18
+ * ERR-014/016: body is truncated to MAX_URL_BODY_LENGTH before encoding so the
19
+ * decoded body never exceeds the bound. Newlines inside the body are encoded
20
+ * as %0A by `encodeURIComponent`, preserving the markdown structure.
21
+ */
22
+ export function buildGitHubIssueDraftUrl(title, type, shortSummary) {
23
+ if (!isFeedbackType(type)) {
24
+ return {
25
+ ok: false,
26
+ error: `invalid feedback type: ${String(type)}`,
27
+ nextAction: 'provide a valid FeedbackType (bug, confusing, privacy_concern, feature_request, other)',
28
+ };
29
+ }
30
+ if (typeof title !== 'string') {
31
+ return {
32
+ ok: false,
33
+ error: 'title must be a string',
34
+ nextAction: 'provide a string value for title',
35
+ };
36
+ }
37
+ // ERR-009/010: fail loud when shortSummary is not a string
38
+ if (typeof shortSummary !== 'string') {
39
+ return {
40
+ ok: false,
41
+ error: 'shortSummary must be a string',
42
+ nextAction: 'provide a string value for shortSummary',
43
+ };
44
+ }
45
+ const safeTitle = redactEnvLikeValues(redactAbsolutePaths(redactTokenLikeValues(title))).slice(0, 200);
46
+ const issueTitle = `[${type}] ${safeTitle}`.trim();
47
+ // The body must stay short and free of secrets — only the shortSummary
48
+ // reaches the URL. We truncate to MAX_URL_BODY_LENGTH *before* URL-encoding
49
+ // so the decoded body never exceeds the bound.
50
+ const bodySource = redactEnvLikeValues(redactAbsolutePaths(redactTokenLikeValues(shortSummary)));
51
+ const body = truncateToMax(bodySource, MAX_URL_BODY_LENGTH);
52
+ const encodedTitle = encodeURIComponent(issueTitle);
53
+ const encodedBody = encodeURIComponent(body);
54
+ const url = `https://github.com/${GITHUB_REPO}/issues/new?title=${encodedTitle}&body=${encodedBody}`;
55
+ return { ok: true, url };
56
+ }
57
+ //# sourceMappingURL=render-github-url.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"render-github-url.js","sourceRoot":"","sources":["../../../src/runtime-v2/feedback/render-github-url.ts"],"names":[],"mappings":"AAAA,uBAAuB;AACvB,2CAA2C;AAC3C,wEAAwE;AACxE,oDAAoD;AAGpD,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EAAE,mBAAmB,EAAE,qBAAqB,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAExG,MAAM,CAAC,MAAM,mBAAmB,GAAG,GAAG,CAAC;AACvC,MAAM,CAAC,MAAM,WAAW,GAAG,qBAAqB,CAAC;AAMjD,SAAS,aAAa,CAAC,CAAS,EAAE,GAAW;IAC3C,IAAI,CAAC,CAAC,MAAM,IAAI,GAAG;QAAE,OAAO,CAAC,CAAC;IAC9B,OAAO,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;AACzB,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,wBAAwB,CACtC,KAAa,EACb,IAA4B,EAC5B,YAAoB;IAEpB,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,EAAE,CAAC;QAC1B,OAAO;YACL,EAAE,EAAE,KAAK;YACT,KAAK,EAAE,0BAA0B,MAAM,CAAC,IAAI,CAAC,EAAE;YAC/C,UAAU,EAAE,wFAAwF;SACrG,CAAC;IACJ,CAAC;IACD,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,OAAO;YACL,EAAE,EAAE,KAAK;YACT,KAAK,EAAE,wBAAwB;YAC/B,UAAU,EAAE,kCAAkC;SAC/C,CAAC;IACJ,CAAC;IAED,2DAA2D;IAC3D,IAAI,OAAO,YAAY,KAAK,QAAQ,EAAE,CAAC;QACrC,OAAO;YACL,EAAE,EAAE,KAAK;YACT,KAAK,EAAE,+BAA+B;YACtC,UAAU,EAAE,yCAAyC;SACtD,CAAC;IACJ,CAAC;IAED,MAAM,SAAS,GAAG,mBAAmB,CAAC,mBAAmB,CAAC,qBAAqB,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IACvG,MAAM,UAAU,GAAG,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC,IAAI,EAAE,CAAC;IAEnD,uEAAuE;IACvE,4EAA4E;IAC5E,+CAA+C;IAC/C,MAAM,UAAU,GAAG,mBAAmB,CAAC,mBAAmB,CAAC,qBAAqB,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IACjG,MAAM,IAAI,GAAG,aAAa,CAAC,UAAU,EAAE,mBAAmB,CAAC,CAAC;IAE5D,MAAM,YAAY,GAAG,kBAAkB,CAAC,UAAU,CAAC,CAAC;IACpD,MAAM,WAAW,GAAG,kBAAkB,CAAC,IAAI,CAAC,CAAC;IAC7C,MAAM,GAAG,GAAG,sBAAsB,WAAW,qBAAqB,YAAY,SAAS,WAAW,EAAE,CAAC;IACrG,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC;AAC3B,CAAC"}
@@ -0,0 +1,12 @@
1
+ import type { FeedbackReport } from './feedback-types.js';
2
+ export declare const MAX_MARKDOWN_LENGTH = 10240;
3
+ /**
4
+ * Render a FeedbackReport to a Markdown string.
5
+ * Uses real `\n` newlines (not the broken `'\\n'` literal).
6
+ * Output is bounded to MAX_MARKDOWN_LENGTH characters.
7
+ *
8
+ * Mutates `report.privacy.redactionNotes` to record field-level truncation
9
+ * events (ERR-014). The renderer never throws.
10
+ */
11
+ export declare function renderReportMarkdown(report: FeedbackReport): string;
12
+ //# sourceMappingURL=render-markdown.d.ts.map