@polishd/next 0.2.3-dev.5 → 0.2.3-dev.7

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 (90) hide show
  1. package/AGENTS.md +1 -1
  2. package/CHANGELOG.md +79 -14
  3. package/README.md +13 -3
  4. package/dist/ai/actions.d.ts +13 -1
  5. package/dist/ai/actions.d.ts.map +1 -1
  6. package/dist/ai/actions.js +20 -1
  7. package/dist/ai/actions.js.map +1 -1
  8. package/dist/ai/design.d.ts +5 -1
  9. package/dist/ai/design.d.ts.map +1 -1
  10. package/dist/ai/design.js +21 -4
  11. package/dist/ai/design.js.map +1 -1
  12. package/dist/ai/fix.d.ts +14 -0
  13. package/dist/ai/fix.d.ts.map +1 -0
  14. package/dist/ai/fix.js +254 -0
  15. package/dist/ai/fix.js.map +1 -0
  16. package/dist/ai/guard.d.ts.map +1 -1
  17. package/dist/ai/guard.js +8 -32
  18. package/dist/ai/guard.js.map +1 -1
  19. package/dist/ai/issues.d.ts +29 -6
  20. package/dist/ai/issues.d.ts.map +1 -1
  21. package/dist/ai/issues.js +113 -40
  22. package/dist/ai/issues.js.map +1 -1
  23. package/dist/ai/types.d.ts +52 -0
  24. package/dist/ai/types.d.ts.map +1 -1
  25. package/dist/dashboard/design-review-card.d.ts +3 -1
  26. package/dist/dashboard/design-review-card.d.ts.map +1 -1
  27. package/dist/dashboard/design-review-card.js +14 -6
  28. package/dist/dashboard/design-review-card.js.map +1 -1
  29. package/dist/dashboard/design.d.ts.map +1 -1
  30. package/dist/dashboard/design.js +75 -17
  31. package/dist/dashboard/design.js.map +1 -1
  32. package/dist/dashboard/file-bug-button.d.ts +14 -0
  33. package/dist/dashboard/file-bug-button.d.ts.map +1 -0
  34. package/dist/dashboard/file-bug-button.js +37 -0
  35. package/dist/dashboard/file-bug-button.js.map +1 -0
  36. package/dist/dashboard/index.d.ts.map +1 -1
  37. package/dist/dashboard/index.js +4 -2
  38. package/dist/dashboard/index.js.map +1 -1
  39. package/dist/dashboard/issue-list.d.ts +11 -0
  40. package/dist/dashboard/issue-list.d.ts.map +1 -0
  41. package/dist/dashboard/issue-list.js +159 -0
  42. package/dist/dashboard/issue-list.js.map +1 -0
  43. package/dist/dashboard/issues.d.ts +31 -2
  44. package/dist/dashboard/issues.d.ts.map +1 -1
  45. package/dist/dashboard/issues.js +4 -71
  46. package/dist/dashboard/issues.js.map +1 -1
  47. package/dist/dashboard/markdown-parse.d.ts +87 -0
  48. package/dist/dashboard/markdown-parse.d.ts.map +1 -0
  49. package/dist/dashboard/markdown-parse.js +244 -0
  50. package/dist/dashboard/markdown-parse.js.map +1 -0
  51. package/dist/dashboard/markdown.d.ts +5 -0
  52. package/dist/dashboard/markdown.d.ts.map +1 -0
  53. package/dist/dashboard/markdown.js +65 -0
  54. package/dist/dashboard/markdown.js.map +1 -0
  55. package/dist/dashboard/snapshot-actions.d.ts.map +1 -1
  56. package/dist/dashboard/snapshot-actions.js +22 -54
  57. package/dist/dashboard/snapshot-actions.js.map +1 -1
  58. package/dist/dashboard/snapshots.d.ts.map +1 -1
  59. package/dist/dashboard/snapshots.js +7 -20
  60. package/dist/dashboard/snapshots.js.map +1 -1
  61. package/dist/dashboard/summary.d.ts.map +1 -1
  62. package/dist/dashboard/summary.js +8 -36
  63. package/dist/dashboard/summary.js.map +1 -1
  64. package/dist/dashboard/ui.d.ts +1 -0
  65. package/dist/dashboard/ui.d.ts.map +1 -1
  66. package/dist/dashboard/ui.js +1 -0
  67. package/dist/dashboard/ui.js.map +1 -1
  68. package/dist/dashboard/value-preview.d.ts +47 -0
  69. package/dist/dashboard/value-preview.d.ts.map +1 -0
  70. package/dist/dashboard/value-preview.js +138 -0
  71. package/dist/dashboard/value-preview.js.map +1 -0
  72. package/dist/dashboard.css +234 -62
  73. package/dist/server/snapshot-blob.d.ts +38 -0
  74. package/dist/server/snapshot-blob.d.ts.map +1 -0
  75. package/dist/server/snapshot-blob.js +75 -0
  76. package/dist/server/snapshot-blob.js.map +1 -0
  77. package/dist/server/snapshots.d.ts +32 -4
  78. package/dist/server/snapshots.d.ts.map +1 -1
  79. package/dist/server/snapshots.js +195 -55
  80. package/dist/server/snapshots.js.map +1 -1
  81. package/dist/server/value-previews.d.ts +47 -0
  82. package/dist/server/value-previews.d.ts.map +1 -0
  83. package/dist/server/value-previews.js +313 -0
  84. package/dist/server/value-previews.js.map +1 -0
  85. package/dist/shared/design-values.d.ts +71 -0
  86. package/dist/shared/design-values.d.ts.map +1 -0
  87. package/dist/shared/design-values.js +98 -0
  88. package/dist/shared/design-values.js.map +1 -0
  89. package/docs/SETUP.md +4 -2
  90. package/package.json +1 -1
package/AGENTS.md CHANGED
@@ -325,7 +325,7 @@ survive there.
325
325
  | Variable | Required | Purpose |
326
326
  |---|---|---|
327
327
  | `POLISHD_DATABASE_URL` | for production capture | Pooled Postgres connection string |
328
- | `BLOB_READ_WRITE_TOKEN` | for production site snapshots | Injected automatically when a Vercel Blob store is connected; snapshot images upload there instead of the (read-only) filesystem |
328
+ | `BLOB_STORE_ID` or `BLOB_READ_WRITE_TOKEN` | for production site snapshots | Injected automatically when a Vercel Blob store is connected — `BLOB_STORE_ID` for an OIDC connection, `BLOB_READ_WRITE_TOKEN` for the classic one; either works, as do public and private stores. Snapshot images upload there instead of the (read-only) filesystem. `BLOB_WEBHOOK_PUBLIC_KEY` isn't needed |
329
329
  | `POLISHD_DASHBOARD_TOKEN` | for production, unless auth is wired | Protects `/polishd`. `openssl rand -hex 32` |
330
330
  | `POLISHD_DASHBOARD_PUBLIC` | no | `true` to serve the dashboard unguarded on purpose |
331
331
  | `POLISHD_SESSION_COOKIE` | no | Rename the session cookie; read by both proxy and ingest |
package/CHANGELOG.md CHANGED
@@ -2,6 +2,85 @@
2
2
 
3
3
  ## Unreleased
4
4
 
5
+ ### Hover a one-off to see where it renders
6
+
7
+ The Design tab flags one-off type styles, colors and corner radii, and
8
+ off-grid paddings — but a flag only says *what* drifted, never *where*, and
9
+ "a 17px / 500 somewhere on /pricing" left the hunt to you. Hovering (or
10
+ focusing, or tapping) a flagged value now opens a card with a **picture of
11
+ the element that carries it**: ringed in the badge's amber, the rest of the
12
+ page dimmed, cropped wide enough to show the component it sits in — plus the
13
+ page, device and theme it was shot on.
14
+
15
+ - The pictures are taken by **Capture snapshot**. After each route's full
16
+ shots, the same browser reloads the route, finds every flagged value's
17
+ element with the client scanner's own rules, scrolls it into view and
18
+ screenshots a crop around it. Matching is by value, not by a recorded
19
+ selector, so the picture always shows the value really rendering at that
20
+ size and theme. Usually that's one extra page load per route with flagged
21
+ values, capped at 15 seconds per route.
22
+ - A value the capture looked for and never saw on screen — one that only
23
+ renders after a click, or at a width snapshots don't shoot — says so on its
24
+ card instead of showing a wrong crop. Values with no picture yet still list
25
+ the pages they were measured on.
26
+ - Pictures are stored with the snapshot's shots (on disk, or in Vercel Blob
27
+ when it's connected) and pruned with them. Polishd's own beacons from the
28
+ extra page load are answered locally, so it never lands in the analytics as
29
+ a visit. Snapshots captured before this release have no pictures; capture
30
+ again to get them.
31
+
32
+ ### Issues open in a drawer, rendered as the markdown they are
33
+
34
+ An issue body on the Issues tab used to be a raw `<pre>` dump behind a
35
+ "Show issue body" toggle — real GitHub-flavored markdown, displayed as if it
36
+ weren't. Clicking a row now opens a **right-side drawer** (the same pattern as
37
+ the sampled user journeys) with the full issue: title, state, the metadata
38
+ GitHub reports, the analytics evidence polishd kept, and the body **rendered
39
+ as markdown** — headings, code, linked file lists, tables, task lists,
40
+ screenshots.
41
+
42
+ - The renderer is written in-house (`src/dashboard/markdown-parse.ts` +
43
+ `markdown.tsx`): the package's zero-runtime-dependency rule rules out
44
+ `react-markdown`, and the GFM subset that actually appears in issues is
45
+ small enough to own. Single newlines are hard breaks, the way GitHub
46
+ renders issue comments, and anything unrecognized degrades to plain
47
+ paragraph text rather than ever crashing. The grammar is pinned down by
48
+ its own test file.
49
+ - Rows are still links to the tracker — the title goes to GitHub, the row
50
+ goes to the drawer.
51
+
52
+ ### The drawer can suggest the fix, not just show the bug
53
+
54
+ With the GitHub codebase connected, every filed issue carries a **"Suggest a
55
+ fix"** button. One click asks the configured model to first **classify the
56
+ bug — an interaction issue (something users do fails) or a design issue
57
+ (something users see is wrong)** — and then design a fix on the published
58
+ practice for that class: Nielsen Norman's usability heuristics and the
59
+ WAI-ARIA Authoring Practices for interaction bugs; WCAG 2.2 contrast rules,
60
+ spacing rhythm, and layout-stability guidance for design bugs.
61
+
62
+ - The suggestion is grounded in the repository's real source: the pipeline
63
+ re-reads the files the issue body cites, code-searches the analytics
64
+ evidence, and answers with an **implementation path** — ordered,
65
+ file-by-file edits, each path linking to the file on GitHub — plus
66
+ "grounded in" chips naming the guidelines it leaned on, so the advice can
67
+ be judged by its sources.
68
+ - Suggestions are cached per issue in the store and load with the tab;
69
+ regenerating is one click. Nothing is offered without a model key, and an
70
+ issue polishd didn't file is refused — there's no evidence to ground.
71
+
72
+ ### Design-review issues can be filed as bugs
73
+
74
+ The aesthetic review's "Breaking the system" list used to be read-only; the
75
+ same one-click **File bug** button the summary's losses have now sits on each
76
+ design issue when GitHub is connected. It runs the same verify-then-file
77
+ pipeline — the model checks the flagged design token (a hex color, a px value,
78
+ a page path) against the repository's source, files a GitHub issue with the
79
+ technical analysis and the review's own suggested fix when it holds up, and
80
+ answers "not a bug" with the reasoning when the code shows the value is
81
+ deliberate. Filed issues show up in the Issues tab like any other, dedupe on
82
+ their evidence citation, and render as their issue link when the tab reloads.
83
+
5
84
  ### Snapshot capture survives serverless time limits
6
85
 
7
86
  Capturing a site snapshot on Vercel could fail with no error box at all — the
@@ -25,20 +104,6 @@ request itself was the problem.
25
104
  - `polishd init` now writes `export const maxDuration = 300` into the
26
105
  dashboard page it generates, and the docs recommend it — headroom for heavy
27
106
  pages on hosts with strict limits, no longer a requirement.
28
- - **A failed capture call now names its error.** The error box carries the
29
- rejection's message and Next's error digest (the id to grep the host's
30
- function logs for) instead of a generic "check your logs", the browser
31
- console gets the full error, and the server logs every capture-action
32
- failure under a `[polishd]` prefix.
33
- - **The action guard no longer depends on the page module having loaded.**
34
- When no policy is registered in the runtime — possible on serverless hosts
35
- serving an action POST cold — it now derives the same policy from the
36
- environment (token mode, public opt-out, or locked), instead of denying a
37
- legitimate dashboard session. A genuine denial reads as a message in the
38
- capture UI rather than an opaque digest.
39
- - Planning a capture no longer depends on the design data being readable:
40
- if those queries fail, the capture shoots `/` with no fingerprint instead
41
- of failing outright.
42
107
 
43
108
  ### The dashboard streams instead of loading all at once
44
109
 
package/README.md CHANGED
@@ -460,10 +460,20 @@ snapshots are kept), and each snapshot is stamped with the design-metrics
460
460
  fingerprint at capture time — so a snapshot taken before a round of design
461
461
  fixes can be held against one taken after.
462
462
 
463
+ Each capture also pictures the flagged values in place: for every one-off type
464
+ style, color and radius, and the most-used off-grid paddings, it finds the
465
+ element carrying the value on its page and saves a ringed crop of it. Hover a
466
+ flagged value on the Design tab to see that picture and the page it's on.
467
+
463
468
  **In production on Vercel**, capture works too — connect a
464
469
  [Blob store](https://vercel.com/docs/vercel-blob) to the project and that's
465
- the whole setup: the `BLOB_READ_WRITE_TOKEN` it injects switches image storage
466
- from disk to Blob, and the browser comes from `@sparticuz/chromium` (a
470
+ the whole setup: whichever variable the connection injects switches image
471
+ storage from disk to Blob — `BLOB_STORE_ID` for a store connected over OIDC
472
+ (authenticated by the short-lived token Vercel issues at runtime) or the
473
+ classic `BLOB_READ_WRITE_TOKEN`. The `BLOB_WEBHOOK_PUBLIC_KEY` an OIDC
474
+ connection also adds isn't needed. Public and private stores both work;
475
+ either way the dashboard serves the images itself, behind its own access
476
+ check. The browser comes from `@sparticuz/chromium` (a
467
477
  Chromium built for serverless sandboxes, installed automatically as an
468
478
  optional dependency). The snapshot index rides in the same database the rest
469
479
  of Polishd already requires in production, so no other wiring changes. Capture
@@ -471,7 +481,7 @@ runs as one short server call per page, so it fits inside serverless function
471
481
  time limits; if a single heavy page still brushes against a strict limit,
472
482
  `export const maxDuration = 300` in the dashboard's `page.tsx` adds headroom
473
483
  (`polishd init` writes it for you). On hosts with neither a writable
474
- filesystem nor a Blob token, the button explains what's missing rather than
484
+ filesystem nor a Blob store, the button explains what's missing rather than
475
485
  failing silently.
476
486
 
477
487
  ## Component-level tracking
@@ -1,5 +1,5 @@
1
1
  import { type ListModelsInput, type SaveAISettingsInput } from "./settings";
2
- import type { PolishdAISettingsPublic, PolishdLossItem, CreateIssueResult, GenerateDesignReviewResult, GenerateProfileResult, GenerateSummaryResult, IgnoreLossResult, ListModelsResult, UnignoreLossResult, VerifyGithubResult } from "./types";
2
+ import type { PolishdAISettingsPublic, PolishdDesignIssue, PolishdLossItem, CreateIssueResult, GenerateDesignReviewResult, GenerateProfileResult, GenerateSummaryResult, IgnoreLossResult, ListModelsResult, SuggestFixResult, UnignoreLossResult, VerifyGithubResult } from "./types";
3
3
  /** Generate or refresh the narrative. `force` re-asks the model even if data is unchanged. */
4
4
  export declare function generateSummaryAction(force?: boolean): Promise<GenerateSummaryResult>;
5
5
  /**
@@ -31,6 +31,18 @@ export declare function verifyGithubAction(): Promise<VerifyGithubResult>;
31
31
  * disproved report returns `not-a-bug` with the reasoning instead of filing.
32
32
  */
33
33
  export declare function createIssueFromLossAction(loss: Pick<PolishdLossItem, "issue" | "evidence" | "location">): Promise<CreateIssueResult>;
34
+ /**
35
+ * The same verify-then-file pipeline for one of the design review's issues —
36
+ * the evidence is a measured design token (hex, px value, page path) instead
37
+ * of an analytics identifier.
38
+ */
39
+ export declare function createIssueFromDesignIssueAction(issue: Pick<PolishdDesignIssue, "issue" | "evidence" | "suggestion">): Promise<CreateIssueResult>;
40
+ /**
41
+ * Classify one filed issue (interaction vs design) and propose a fix grounded
42
+ * in the repository's source and in published practice, with the file-by-file
43
+ * implementation path. Cached per issue; `force` regenerates.
44
+ */
45
+ export declare function suggestIssueFixAction(issueNumber: number, force?: boolean): Promise<SuggestFixResult>;
34
46
  /**
35
47
  * The other verdict on a loss: dismiss it, with an optional reason. The loss
36
48
  * leaves every summary from here on, and the dismissal — reason included — is
@@ -1 +1 @@
1
- {"version":3,"file":"actions.d.ts","sourceRoot":"","sources":["../../src/ai/actions.ts"],"names":[],"mappings":"AAsBA,OAAO,EAGL,KAAK,eAAe,EACpB,KAAK,mBAAmB,EACzB,MAAM,YAAY,CAAC;AAEpB,OAAO,KAAK,EACV,uBAAuB,EACvB,eAAe,EACf,iBAAiB,EACjB,0BAA0B,EAC1B,qBAAqB,EACrB,qBAAqB,EACrB,gBAAgB,EAChB,gBAAgB,EAChB,kBAAkB,EAClB,kBAAkB,EACnB,MAAM,SAAS,CAAC;AAEjB,8FAA8F;AAC9F,wBAAsB,qBAAqB,CAAC,KAAK,UAAQ,GAAG,OAAO,CAAC,qBAAqB,CAAC,CAGzF;AAED;;;;GAIG;AACH,wBAAsB,0BAA0B,CAC9C,KAAK,UAAQ,GACZ,OAAO,CAAC,0BAA0B,CAAC,CAGrC;AAED,mFAAmF;AACnF,wBAAsB,oBAAoB,CACxC,KAAK,EAAE,mBAAmB,GACzB,OAAO,CAAC,uBAAuB,CAAC,CAGlC;AAED;;;GAGG;AACH,wBAAsB,qBAAqB,IAAI,OAAO,CAAC,qBAAqB,CAAC,CAI5E;AAED;;;GAGG;AACH,wBAAsB,gBAAgB,CAAC,KAAK,EAAE,eAAe,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAGxF;AAED;;;GAGG;AACH,wBAAsB,kBAAkB,IAAI,OAAO,CAAC,kBAAkB,CAAC,CAGtE;AAED;;;;GAIG;AACH,wBAAsB,yBAAyB,CAC7C,IAAI,EAAE,IAAI,CAAC,eAAe,EAAE,OAAO,GAAG,UAAU,GAAG,UAAU,CAAC,GAC7D,OAAO,CAAC,iBAAiB,CAAC,CAG5B;AAED;;;;;GAKG;AACH,wBAAsB,gBAAgB,CACpC,IAAI,EAAE,IAAI,CAAC,eAAe,EAAE,OAAO,GAAG,UAAU,CAAC,EACjD,MAAM,CAAC,EAAE,MAAM,GACd,OAAO,CAAC,gBAAgB,CAAC,CAM3B;AAED,kEAAkE;AAClE,wBAAsB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAKtF"}
1
+ {"version":3,"file":"actions.d.ts","sourceRoot":"","sources":["../../src/ai/actions.ts"],"names":[],"mappings":"AAuBA,OAAO,EAGL,KAAK,eAAe,EACpB,KAAK,mBAAmB,EACzB,MAAM,YAAY,CAAC;AAEpB,OAAO,KAAK,EACV,uBAAuB,EACvB,kBAAkB,EAClB,eAAe,EACf,iBAAiB,EACjB,0BAA0B,EAC1B,qBAAqB,EACrB,qBAAqB,EACrB,gBAAgB,EAChB,gBAAgB,EAChB,gBAAgB,EAChB,kBAAkB,EAClB,kBAAkB,EACnB,MAAM,SAAS,CAAC;AAEjB,8FAA8F;AAC9F,wBAAsB,qBAAqB,CAAC,KAAK,UAAQ,GAAG,OAAO,CAAC,qBAAqB,CAAC,CAGzF;AAED;;;;GAIG;AACH,wBAAsB,0BAA0B,CAC9C,KAAK,UAAQ,GACZ,OAAO,CAAC,0BAA0B,CAAC,CAGrC;AAED,mFAAmF;AACnF,wBAAsB,oBAAoB,CACxC,KAAK,EAAE,mBAAmB,GACzB,OAAO,CAAC,uBAAuB,CAAC,CAGlC;AAED;;;GAGG;AACH,wBAAsB,qBAAqB,IAAI,OAAO,CAAC,qBAAqB,CAAC,CAI5E;AAED;;;GAGG;AACH,wBAAsB,gBAAgB,CAAC,KAAK,EAAE,eAAe,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAGxF;AAED;;;GAGG;AACH,wBAAsB,kBAAkB,IAAI,OAAO,CAAC,kBAAkB,CAAC,CAGtE;AAED;;;;GAIG;AACH,wBAAsB,yBAAyB,CAC7C,IAAI,EAAE,IAAI,CAAC,eAAe,EAAE,OAAO,GAAG,UAAU,GAAG,UAAU,CAAC,GAC7D,OAAO,CAAC,iBAAiB,CAAC,CAG5B;AAED;;;;GAIG;AACH,wBAAsB,gCAAgC,CACpD,KAAK,EAAE,IAAI,CAAC,kBAAkB,EAAE,OAAO,GAAG,UAAU,GAAG,YAAY,CAAC,GACnE,OAAO,CAAC,iBAAiB,CAAC,CAG5B;AAED;;;;GAIG;AACH,wBAAsB,qBAAqB,CACzC,WAAW,EAAE,MAAM,EACnB,KAAK,UAAQ,GACZ,OAAO,CAAC,gBAAgB,CAAC,CAG3B;AAED;;;;;GAKG;AACH,wBAAsB,gBAAgB,CACpC,IAAI,EAAE,IAAI,CAAC,eAAe,EAAE,OAAO,GAAG,UAAU,CAAC,EACjD,MAAM,CAAC,EAAE,MAAM,GACd,OAAO,CAAC,gBAAgB,CAAC,CAM3B;AAED,kEAAkE;AAClE,wBAAsB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAKtF"}
@@ -14,9 +14,10 @@
14
14
  */
15
15
  import { requirePolishdAuth } from "./guard";
16
16
  import { generateDesignReview } from "./design";
17
+ import { suggestIssueFix } from "./fix";
17
18
  import { verifyGithubConnection } from "./github";
18
19
  import { ignoreLoss, unignoreLoss } from "./ignored";
19
- import { createIssueFromLoss } from "./issues";
20
+ import { createIssueFromDesignIssue, createIssueFromLoss } from "./issues";
20
21
  import { generateProjectProfile } from "./profile";
21
22
  import { loadPolishdDashboardData } from "../server/queries";
22
23
  import { listModelsForProvider, saveAISettings, } from "./settings";
@@ -74,6 +75,24 @@ export async function createIssueFromLossAction(loss) {
74
75
  await requirePolishdAuth();
75
76
  return createIssueFromLoss(loss);
76
77
  }
78
+ /**
79
+ * The same verify-then-file pipeline for one of the design review's issues —
80
+ * the evidence is a measured design token (hex, px value, page path) instead
81
+ * of an analytics identifier.
82
+ */
83
+ export async function createIssueFromDesignIssueAction(issue) {
84
+ await requirePolishdAuth();
85
+ return createIssueFromDesignIssue(issue);
86
+ }
87
+ /**
88
+ * Classify one filed issue (interaction vs design) and propose a fix grounded
89
+ * in the repository's source and in published practice, with the file-by-file
90
+ * implementation path. Cached per issue; `force` regenerates.
91
+ */
92
+ export async function suggestIssueFixAction(issueNumber, force = false) {
93
+ await requirePolishdAuth();
94
+ return suggestIssueFix(issueNumber, force);
95
+ }
77
96
  /**
78
97
  * The other verdict on a loss: dismiss it, with an optional reason. The loss
79
98
  * leaves every summary from here on, and the dismissal — reason included — is
@@ -1 +1 @@
1
- {"version":3,"file":"actions.js","sourceRoot":"","sources":["../../src/ai/actions.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb;;;;;;;;;;;;GAYG;AACH,OAAO,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAC7C,OAAO,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAC;AAChD,OAAO,EAAE,sBAAsB,EAAE,MAAM,UAAU,CAAC;AAClD,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AACrD,OAAO,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAC;AAC/C,OAAO,EAAE,sBAAsB,EAAE,MAAM,WAAW,CAAC;AACnD,OAAO,EAAE,wBAAwB,EAAE,MAAM,mBAAmB,CAAC;AAC7D,OAAO,EACL,qBAAqB,EACrB,cAAc,GAGf,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAc5C,8FAA8F;AAC9F,MAAM,CAAC,KAAK,UAAU,qBAAqB,CAAC,KAAK,GAAG,KAAK;IACvD,MAAM,kBAAkB,EAAE,CAAC;IAC3B,OAAO,eAAe,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;AACpC,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,0BAA0B,CAC9C,KAAK,GAAG,KAAK;IAEb,MAAM,kBAAkB,EAAE,CAAC;IAC3B,OAAO,oBAAoB,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;AACzC,CAAC;AAED,mFAAmF;AACnF,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,KAA0B;IAE1B,MAAM,kBAAkB,EAAE,CAAC;IAC3B,OAAO,cAAc,CAAC,KAAK,CAAC,CAAC;AAC/B,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,qBAAqB;IACzC,MAAM,kBAAkB,EAAE,CAAC;IAC3B,MAAM,IAAI,GAAG,MAAM,wBAAwB,EAAE,CAAC;IAC9C,OAAO,sBAAsB,CAAC,IAAI,CAAC,CAAC;AACtC,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,KAAsB;IAC3D,MAAM,kBAAkB,EAAE,CAAC;IAC3B,OAAO,qBAAqB,CAAC,KAAK,CAAC,CAAC;AACtC,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB;IACtC,MAAM,kBAAkB,EAAE,CAAC;IAC3B,OAAO,sBAAsB,EAAE,CAAC;AAClC,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,yBAAyB,CAC7C,IAA8D;IAE9D,MAAM,kBAAkB,EAAE,CAAC;IAC3B,OAAO,mBAAmB,CAAC,IAAI,CAAC,CAAC;AACnC,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,IAAiD,EACjD,MAAe;IAEf,MAAM,kBAAkB,EAAE,CAAC;IAC3B,MAAM,OAAO,GAAG,MAAM,UAAU,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IAC/C,OAAO,OAAO;QACZ,CAAC,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE;QACvB,CAAC,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,mEAAmE,EAAE,CAAC;AAClG,CAAC;AAED,kEAAkE;AAClE,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,QAAgB;IACvD,MAAM,kBAAkB,EAAE,CAAC;IAC3B,OAAO,CAAC,MAAM,YAAY,CAAC,QAAQ,CAAC,CAAC;QACnC,CAAC,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE;QACd,CAAC,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,mEAAmE,EAAE,CAAC;AAClG,CAAC"}
1
+ {"version":3,"file":"actions.js","sourceRoot":"","sources":["../../src/ai/actions.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,10 @@
1
1
  import { type PolishdDesignData } from "../server/design";
2
2
  import type { GenerateDesignReviewResult, PolishdDesignReview } from "./types";
3
- /** The last generated review, or null. Read-only — never calls a model. */
3
+ /**
4
+ * The last generated review, or null. Read-only — never calls a model. Issues
5
+ * whose evidence already has a GitHub issue in the log come back with the link
6
+ * attached, so the tab renders it instead of a "file bug" button.
7
+ */
4
8
  export declare function loadDesignReview(): Promise<PolishdDesignReview | null>;
5
9
  /**
6
10
  * Render the aggregated design data as a terse, model-readable brief.
@@ -1 +1 @@
1
- {"version":3,"file":"design.d.ts","sourceRoot":"","sources":["../../src/ai/design.ts"],"names":[],"mappings":"AAgBA,OAAO,EAAiB,KAAK,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAIzE,OAAO,KAAK,EACV,0BAA0B,EAE1B,mBAAmB,EACpB,MAAM,SAAS,CAAC;AAIjB,2EAA2E;AAC3E,wBAAsB,gBAAgB,IAAI,OAAO,CAAC,mBAAmB,GAAG,IAAI,CAAC,CAQ5E;AAsBD;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,iBAAiB,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAmEnF;AAgED;;;;;;GAMG;AACH,wBAAsB,oBAAoB,CACxC,IAAI,GAAE;IAAE,KAAK,CAAC,EAAE,OAAO,CAAA;CAAO,GAC7B,OAAO,CAAC,0BAA0B,CAAC,CAgErC;AAED;;;GAGG;AACH,wBAAsB,qBAAqB,CAAC,SAAS,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC;IAClF,MAAM,EAAE,mBAAmB,GAAG,IAAI,CAAC;IACnC,KAAK,EAAE,OAAO,CAAC;CAChB,CAAC,CASD"}
1
+ {"version":3,"file":"design.d.ts","sourceRoot":"","sources":["../../src/ai/design.ts"],"names":[],"mappings":"AAgBA,OAAO,EAAiB,KAAK,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAKzE,OAAO,KAAK,EACV,0BAA0B,EAE1B,mBAAmB,EACpB,MAAM,SAAS,CAAC;AAIjB;;;;GAIG;AACH,wBAAsB,gBAAgB,IAAI,OAAO,CAAC,mBAAmB,GAAG,IAAI,CAAC,CAa5E;AAsBD;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,iBAAiB,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAmEnF;AAgED;;;;;;GAMG;AACH,wBAAsB,oBAAoB,CACxC,IAAI,GAAE;IAAE,KAAK,CAAC,EAAE,OAAO,CAAA;CAAO,GAC7B,OAAO,CAAC,0BAA0B,CAAC,CAuErC;AAED;;;GAGG;AACH,wBAAsB,qBAAqB,CAAC,SAAS,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC;IAClF,MAAM,EAAE,mBAAmB,GAAG,IAAI,CAAC;IACnC,KAAK,EAAE,OAAO,CAAC;CAChB,CAAC,CASD"}
package/dist/ai/design.js CHANGED
@@ -16,20 +16,30 @@
16
16
  import { getMeta, setMeta } from "../server/store";
17
17
  import { getDesignData } from "../server/design";
18
18
  import { fingerprintDigest } from "./digest";
19
+ import { attachGithubIssuesToDesignIssues } from "./issues";
19
20
  import { callModel } from "./providers";
20
21
  import { resolveSettings } from "./settings";
21
22
  const DESIGN_REVIEW_KEY = "ai_design_review";
22
- /** The last generated review, or null. Read-only — never calls a model. */
23
+ /**
24
+ * The last generated review, or null. Read-only — never calls a model. Issues
25
+ * whose evidence already has a GitHub issue in the log come back with the link
26
+ * attached, so the tab renders it instead of a "file bug" button.
27
+ */
23
28
  export async function loadDesignReview() {
24
29
  const raw = await getMeta(DESIGN_REVIEW_KEY);
25
30
  if (!raw)
26
31
  return null;
32
+ let review;
27
33
  try {
28
- return JSON.parse(raw);
34
+ review = JSON.parse(raw);
29
35
  }
30
36
  catch {
31
37
  return null;
32
38
  }
39
+ if (review.issues?.length) {
40
+ review.issues = await attachGithubIssuesToDesignIssues(review.issues);
41
+ }
42
+ return review;
33
43
  }
34
44
  const SYSTEM_PROMPT = "You are a senior brand and product designer reviewing a shipped website. " +
35
45
  "You receive design tokens reverse-engineered from the rendered pages — the " +
@@ -214,18 +224,25 @@ export async function generateDesignReview(opts = {}) {
214
224
  };
215
225
  }
216
226
  const parsed = parseStructured(reply.text);
227
+ const issues = verifyIssues(parsed.issues, digest);
217
228
  const review = {
218
229
  text: parsed.assessment,
219
230
  strengths: parsed.strengths,
220
- issues: verifyIssues(parsed.issues, digest),
231
+ issues,
221
232
  provider: settings.provider,
222
233
  model: settings.model,
223
234
  generatedAt: Date.now(),
224
235
  fingerprint,
225
236
  usage: reply.usage,
226
237
  };
238
+ // Persisted without issue links — those live in the issue log and are
239
+ // attached on every read, so the cached review can't hold a stale link.
227
240
  await setMeta(DESIGN_REVIEW_KEY, JSON.stringify(review));
228
- return { ok: true, review, regenerated: true };
241
+ return {
242
+ ok: true,
243
+ review: { ...review, issues: await attachGithubIssuesToDesignIssues(issues) },
244
+ regenerated: true,
245
+ };
229
246
  }
230
247
  /**
231
248
  * For the Design tab's first render: the cached review plus whether the live
@@ -1 +1 @@
1
- {"version":3,"file":"design.js","sourceRoot":"","sources":["../../src/ai/design.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"design.js","sourceRoot":"","sources":["../../src/ai/design.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AACnD,OAAO,EAAE,aAAa,EAA0B,MAAM,kBAAkB,CAAC;AACzE,OAAO,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAC7C,OAAO,EAAE,gCAAgC,EAAE,MAAM,UAAU,CAAC;AAC5D,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAO7C,MAAM,iBAAiB,GAAG,kBAAkB,CAAC;AAE7C;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB;IACpC,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,iBAAiB,CAAC,CAAC;IAC7C,IAAI,CAAC,GAAG;QAAE,OAAO,IAAI,CAAC;IACtB,IAAI,MAA2B,CAAC;IAChC,IAAI,CAAC;QACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAwB,CAAC;IAClD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;IACD,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC;QAC1B,MAAM,CAAC,MAAM,GAAG,MAAM,gCAAgC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IACxE,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,aAAa,GACjB,2EAA2E;IAC3E,6EAA6E;IAC7E,4EAA4E;IAC5E,4EAA4E;IAC5E,2DAA2D;IAC3D,sEAAsE;IACtE,gIAAgI;IAChI,sEAAsE;IACtE,6EAA6E;IAC7E,0EAA0E;IAC1E,sEAAsE;IACtE,wEAAwE;IACxE,6CAA6C;IAC7C,2EAA2E;IAC3E,6EAA6E;IAC7E,oEAAoE;IACpE,0EAA0E;IAC1E,2EAA2E,CAAC;AAE9E;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAAC,IAAuB,EAAE,OAAgB;IACzE,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,IAAI,OAAO,IAAI,OAAO,CAAC,IAAI,EAAE;QAAE,KAAK,CAAC,IAAI,CAAC,SAAS,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;IAErE,KAAK,CAAC,IAAI,CACR,YAAY,IAAI,CAAC,KAAK,CAAC,MAAM,WAAW,IAAI,CAAC,KAAK;SAC/C,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC;SACZ,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;SAClB,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,IAAI,CACxD,CAAC;IAEF,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC;QACzB,KAAK,CAAC,IAAI,CAAC,iBAAiB,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,KAAK,QAAQ,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;IACvG,CAAC;IAED,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;QACtB,KAAK,CAAC,IAAI,CAAC,gDAAgD,CAAC,CAAC;QAC7D,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC;YACxC,KAAK,CAAC,IAAI,CACR,OAAO,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC,MAAM,MAAM,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,KAAK,UAAU,CAAC,CAAC,KAAK,CAAC,MAAM,QAAQ;gBACnF,GAAG,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,EAAE,CACrF,CAAC;QACJ,CAAC;IACH,CAAC;IAED,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;QACvB,KAAK,CAAC,IAAI,CAAC,qCAAqC,CAAC,CAAC;QAClD,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC;YACzC,MAAM,KAAK,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC;iBAClC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC;iBACxB,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;iBACf,IAAI,CAAC,GAAG,CAAC,CAAC;YACb,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,GAAG,MAAM,KAAK,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QACnF,CAAC;IACH,CAAC;IAED,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;IACvD,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;QACnB,KAAK,CAAC,IAAI,CAAC,8BAA8B,CAAC,CAAC;QAC3C,KAAK,MAAM,CAAC,IAAI,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;YACpC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,KAAK,SAAS,CAAC,CAAC,SAAS,aAAa,CAAC,CAAC,QAAQ,KAAK,CAAC,CAAC;QACjG,CAAC;IACH,CAAC;IAED,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;QACtB,KAAK,CAAC,IAAI,CACR,gBAAgB,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,KAAK,KAAK,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAC9G,CAAC;IACJ,CAAC;IAED,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC;QACxB,KAAK,CAAC,IAAI,CACR,6BAA6B;YAC3B,IAAI,CAAC,OAAO;iBACT,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC;iBACZ,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;iBACxD,IAAI,CAAC,IAAI,CAAC;YACb,0BAA0B,CAC7B,CAAC;IACJ,CAAC;IAED,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;QACtB,KAAK,CAAC,IAAI,CAAC,sBAAsB,CAAC,CAAC;QACnC,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,KAAK;YAAE,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,OAAO,KAAK,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;IAC5E,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC;AAQD,gFAAgF;AAChF,SAAS,eAAe,CAAC,IAAY;IAKnC,IAAI,CAAC,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;IACpB,MAAM,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,8BAA8B,CAAC,CAAC;IACtD,IAAI,KAAK;QAAE,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IAC/B,MAAM,KAAK,GAAG,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IAC7B,MAAM,GAAG,GAAG,CAAC,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IAC/B,IAAI,KAAK,IAAI,CAAC,IAAI,GAAG,GAAG,KAAK,EAAE,CAAC;QAC9B,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,EAAE,GAAG,GAAG,CAAC,CAAC,CAA4B,CAAC;YAC3E,MAAM,UAAU,GAAG,OAAO,GAAG,CAAC,UAAU,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACnF,IAAI,UAAU,EAAE,CAAC;gBACf,MAAM,SAAS,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC;oBAC5C,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,EAAe,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC;oBACpG,CAAC,CAAC,EAAE,CAAC;gBACP,MAAM,MAAM,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAE,GAAG,CAAC,MAAqB,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;gBACvF,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,EAAE,CAAC;YAC3C,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,kBAAkB;QACpB,CAAC;IACH,CAAC;IACD,OAAO,EAAE,UAAU,EAAE,IAAI,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;AAChE,CAAC;AAED;;;GAGG;AACH,SAAS,YAAY,CAAC,GAAe,EAAE,MAAc;IACnD,MAAM,GAAG,GAAG,MAAM,CAAC,WAAW,EAAE,CAAC;IACjC,MAAM,GAAG,GAAyB,EAAE,CAAC;IACrC,KAAK,MAAM,CAAC,IAAI,GAAG,EAAE,CAAC;QACpB,IAAI,OAAO,CAAC,CAAC,KAAK,KAAK,QAAQ,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,EAAE;YAAE,SAAS;QAC7D,MAAM,QAAQ,GAAG,OAAO,CAAC,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACzE,IAAI,CAAC,QAAQ;YAAE,SAAS;QACxB,MAAM,MAAM,GAAG,QAAQ;aACpB,WAAW,EAAE;aACb,KAAK,CAAC,YAAY,CAAC;aACnB,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC,CAAC;QAChC,IAAI,CAAC,MAAM,CAAC,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;YAAE,SAAS;QACrE,GAAG,CAAC,IAAI,CAAC;YACP,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,IAAI,EAAE;YACrB,QAAQ;YACR,UAAU,EACR,OAAO,CAAC,CAAC,UAAU,KAAK,QAAQ,IAAI,CAAC,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,SAAS;SAC5F,CAAC,CAAC;QACH,IAAI,GAAG,CAAC,MAAM,IAAI,CAAC;YAAE,MAAM;IAC7B,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,OAA4B,EAAE;IAE9B,MAAM,EAAE,QAAQ,EAAE,GAAG,MAAM,eAAe,EAAE,CAAC;IAC7C,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC;QACrB,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,wBAAwB,EAAE,CAAC;IAC3E,CAAC;IAED,MAAM,IAAI,GAAG,MAAM,aAAa,EAAE,CAAC;IACnC,IAAI,CAAC,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC3C,OAAO;YACL,EAAE,EAAE,KAAK;YACT,KAAK,EAAE,SAAS;YAChB,OAAO,EAAE,uDAAuD;SACjE,CAAC;IACJ,CAAC;IAED,MAAM,MAAM,GAAG,iBAAiB,CAAC,IAAI,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAC;IACzD,MAAM,WAAW,GAAG,iBAAiB,CAAC,MAAM,CAAC,CAAC;IAE9C,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;QAChB,MAAM,MAAM,GAAG,MAAM,gBAAgB,EAAE,CAAC;QACxC,IAAI,MAAM,IAAI,MAAM,CAAC,WAAW,KAAK,WAAW,EAAE,CAAC;YACjD,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,KAAK,EAAE,CAAC;QAC1D,CAAC;IACH,CAAC;IAED,MAAM,MAAM,GAAG,QAAQ,CAAC,YAAY;QAClC,CAAC,CAAC,GAAG,aAAa,oDAAoD,QAAQ,CAAC,YAAY,EAAE;QAC7F,CAAC,CAAC,aAAa,CAAC;IAElB,IAAI,KAAK,CAAC;IACV,IAAI,CAAC;QACH,KAAK,GAAG,MAAM,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IACpD,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO;YACL,EAAE,EAAE,KAAK;YACT,KAAK,EAAE,gBAAgB;YACvB,OAAO,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,2BAA2B;SAC1E,CAAC;IACJ,CAAC;IACD,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;QAChB,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,gBAAgB,EAAE,OAAO,EAAE,uCAAuC,EAAE,CAAC;IAClG,CAAC;IACD,IAAI,KAAK,CAAC,SAAS,EAAE,CAAC;QACpB,OAAO;YACL,EAAE,EAAE,KAAK;YACT,KAAK,EAAE,gBAAgB;YACvB,OAAO,EACL,4GAA4G;SAC/G,CAAC;IACJ,CAAC;IAED,MAAM,MAAM,GAAG,eAAe,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC3C,MAAM,MAAM,GAAG,YAAY,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnD,MAAM,MAAM,GAAwB;QAClC,IAAI,EAAE,MAAM,CAAC,UAAU;QACvB,SAAS,EAAE,MAAM,CAAC,SAAS;QAC3B,MAAM;QACN,QAAQ,EAAE,QAAQ,CAAC,QAAQ;QAC3B,KAAK,EAAE,QAAQ,CAAC,KAAK;QACrB,WAAW,EAAE,IAAI,CAAC,GAAG,EAAE;QACvB,WAAW;QACX,KAAK,EAAE,KAAK,CAAC,KAAK;KACnB,CAAC;IACF,sEAAsE;IACtE,wEAAwE;IACxE,MAAM,OAAO,CAAC,iBAAiB,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC;IACzD,OAAO;QACL,EAAE,EAAE,IAAI;QACR,MAAM,EAAE,EAAE,GAAG,MAAM,EAAE,MAAM,EAAE,MAAM,gCAAgC,CAAC,MAAM,CAAC,EAAE;QAC7E,WAAW,EAAE,IAAI;KAClB,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,qBAAqB,CAAC,SAA6B;IAIvE,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;QACvC,gBAAgB,EAAE;QAClB,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,aAAa,EAAE;KACzD,CAAC,CAAC;IACH,IAAI,CAAC,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC;IAC5E,MAAM,EAAE,QAAQ,EAAE,GAAG,MAAM,eAAe,EAAE,CAAC;IAC7C,MAAM,WAAW,GAAG,iBAAiB,CAAC,iBAAiB,CAAC,IAAI,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC;IACjF,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,IAAI,MAAM,CAAC,WAAW,KAAK,WAAW,EAAE,CAAC;AAClF,CAAC"}
@@ -0,0 +1,14 @@
1
+ import type { PolishdFixSuggestion, SuggestFixResult } from "./types";
2
+ /**
3
+ * Every cached suggestion, keyed by issue number — what the Issues tab loads
4
+ * up front so an already-answered issue opens with its fix in place.
5
+ */
6
+ export declare function listFixSuggestions(): Promise<Record<number, PolishdFixSuggestion>>;
7
+ /**
8
+ * Propose (or re-propose, with `force`) a fix for one filed issue. Refuses
9
+ * cleanly when nothing is connected, no model key is set, or the number isn't
10
+ * an issue polishd filed; a model hiccup comes back as `provider-error`, and
11
+ * nothing is cached on failure.
12
+ */
13
+ export declare function suggestIssueFix(issueNumber: number, force?: boolean): Promise<SuggestFixResult>;
14
+ //# sourceMappingURL=fix.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fix.d.ts","sourceRoot":"","sources":["../../src/ai/fix.ts"],"names":[],"mappings":"AAkCA,OAAO,KAAK,EAEV,oBAAoB,EACpB,gBAAgB,EACjB,MAAM,SAAS,CAAC;AAwBjB;;;GAGG;AACH,wBAAsB,kBAAkB,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,oBAAoB,CAAC,CAAC,CAKxF;AAiHD;;;;;GAKG;AACH,wBAAsB,eAAe,CACnC,WAAW,EAAE,MAAM,EACnB,KAAK,UAAQ,GACZ,OAAO,CAAC,gBAAgB,CAAC,CAgG3B"}
package/dist/ai/fix.js ADDED
@@ -0,0 +1,254 @@
1
+ /**
2
+ * Polishd — filed issue → suggested fix (server only).
3
+ *
4
+ * The Issues tab shows what was reported; this module answers the next
5
+ * question: how would you actually fix it? Only meaningful when the GitHub
6
+ * codebase is connected — the whole point is that the suggestion is grounded
7
+ * in the repository's real source, not in the issue text alone:
8
+ *
9
+ * 1. Recover the analytics evidence behind the issue from the filed log —
10
+ * an issue polishd didn't file is refused, there's no evidence to ground.
11
+ * 2. Pull source: files the issue body already cites (the ones the original
12
+ * verification read), then code-search hits for the evidence.
13
+ * 3. Ask the model to first CLASSIFY the bug — an interaction issue
14
+ * (something users do fails) or a design issue (something users see is
15
+ * wrong) — and then design the fix on the published practice for that
16
+ * class: Nielsen Norman's usability heuristics and the WAI-ARIA
17
+ * Authoring Practices for interaction, WCAG 2.2 and spacing/type-scale
18
+ * rhythm for design. The reply names the guidelines it leaned on, so the
19
+ * owner can judge the advice by its sources.
20
+ * 4. The answer is an implementation path — ordered, file-by-file edits —
21
+ * not just prose, and it's cached per issue number: the issue and the
22
+ * source rarely change under it, and a regenerate is one click away.
23
+ */
24
+ import { getMeta, setMeta } from "../server/store";
25
+ import { isGithubConnected, readGithubFile, readGithubIssue, searchGithubCode, } from "./github";
26
+ import { evidenceSearchTerms, findFiledIssue } from "./issues";
27
+ import { loadProjectProfile } from "./profile";
28
+ import { callModel } from "./providers";
29
+ import { resolveSettings } from "./settings";
30
+ const FIX_LOG_KEY = "issue_fix_suggestions";
31
+ const MAX_FILES = 4;
32
+ const MAX_CHARS_PER_FILE = 8_000;
33
+ const MAX_BODY_CHARS = 6_000;
34
+ /** The reply carries prose + steps, not one paragraph — give it headroom. */
35
+ const MAX_OUTPUT_TOKENS = 4_096;
36
+ async function loadFixLog() {
37
+ const raw = await getMeta(FIX_LOG_KEY);
38
+ if (!raw)
39
+ return {};
40
+ try {
41
+ return JSON.parse(raw);
42
+ }
43
+ catch {
44
+ return {};
45
+ }
46
+ }
47
+ /**
48
+ * Every cached suggestion, keyed by issue number — what the Issues tab loads
49
+ * up front so an already-answered issue opens with its fix in place.
50
+ */
51
+ export async function listFixSuggestions() {
52
+ const log = await loadFixLog();
53
+ const out = {};
54
+ for (const s of Object.values(log))
55
+ out[s.issueNumber] = s;
56
+ return out;
57
+ }
58
+ // ── The prompt ───────────────────────────────────────────────────────────────
59
+ const FIX_PROMPT = "You are a senior product engineer proposing a concrete fix for a bug that " +
60
+ "a product-analytics tool filed from real user-behavior data. You receive " +
61
+ "the GitHub issue (title and body), the analytics identifier cited as " +
62
+ "evidence, and source files from the site's repository.\n\n" +
63
+ "First classify the bug, then design the fix on the widely adopted practice " +
64
+ "for that class:\n" +
65
+ "- interaction: something users DO fails or frustrates — rage/dead clicks, " +
66
+ "broken or missing handlers, unresponsive or inaccessible controls, " +
67
+ "confusing flows, runtime errors. Ground the fix in Nielsen Norman's " +
68
+ "usability heuristics (visibility of system status, error prevention and " +
69
+ "recovery), the WAI-ARIA Authoring Practices for correct interactive " +
70
+ "semantics and keyboard support, and touch-target guidance (WCAG 2.5.8 / " +
71
+ "the 44px platform minimums).\n" +
72
+ "- design: something users SEE is wrong — contrast, visual hierarchy, " +
73
+ "spacing, typography, layout shift. Ground the fix in WCAG 2.2 (1.4.3 text " +
74
+ "contrast, 1.4.11 non-text contrast), a consistent spacing rhythm and type " +
75
+ "scale, and the web-vitals guidance on layout stability (CLS).\n\n" +
76
+ "Respond with ONLY a JSON object (no markdown fences, no preamble):\n" +
77
+ '{ "bugType": "interaction" | "design", "classification": string, ' +
78
+ '"approach": string, "steps": [{ "path": string, "change": string }], ' +
79
+ '"practices": string[] }\n\n' +
80
+ "bugType: which class this bug falls into.\n" +
81
+ "classification: one sentence on why it's that class.\n" +
82
+ "approach: the fix in 2-5 sentences, written for the developer who will " +
83
+ "implement it, citing the code it changes. Inline markdown (backticked " +
84
+ "identifiers) is welcome; no headings.\n" +
85
+ "steps: the implementation path, in order. Each path MUST be a repository " +
86
+ "file path taken from the source files provided; each change describes the " +
87
+ "exact edit in 1-3 sentences. 1-5 steps.\n" +
88
+ "practices: 1-3 short names of the published guidelines the fix leans on, " +
89
+ 'e.g. "WCAG 2.2 §1.4.3 contrast", "ARIA APG disclosure pattern", ' +
90
+ '"NN/g error prevention". Only ones that genuinely informed the fix.';
91
+ // ── Source gathering ─────────────────────────────────────────────────────────
92
+ /** Repo paths the issue body itself cites — `[`src/x.tsx`](…)` and the like. */
93
+ function citedPaths(body) {
94
+ const out = [];
95
+ for (const m of body.matchAll(/`([\w@./-]+\.[a-z]{2,4})`/gi)) {
96
+ if (m[1].includes("/") && !out.includes(m[1]))
97
+ out.push(m[1]);
98
+ }
99
+ return out;
100
+ }
101
+ /** The issue's own citations first, then code-search hits for the evidence. */
102
+ async function collectSource(evidence, body) {
103
+ const paths = citedPaths(body);
104
+ for (const p of await searchGithubCode(evidenceSearchTerms(evidence), MAX_FILES)) {
105
+ if (!paths.includes(p))
106
+ paths.push(p);
107
+ }
108
+ const out = [];
109
+ for (const path of paths.slice(0, MAX_FILES)) {
110
+ const content = await readGithubFile(path);
111
+ if (content)
112
+ out.push({ path, content: content.slice(0, MAX_CHARS_PER_FILE) });
113
+ }
114
+ return out;
115
+ }
116
+ // ── Parsing ──────────────────────────────────────────────────────────────────
117
+ /** Tolerant JSON extraction, same approach as the investigation parser. */
118
+ function parseSuggestion(text) {
119
+ let t = text.trim();
120
+ const fence = t.match(/```(?:json)?\s*([\s\S]*?)```/);
121
+ if (fence)
122
+ t = fence[1].trim();
123
+ const start = t.indexOf("{");
124
+ const end = t.lastIndexOf("}");
125
+ if (start < 0 || end <= start)
126
+ return null;
127
+ try {
128
+ const obj = JSON.parse(t.slice(start, end + 1));
129
+ const approach = typeof obj.approach === "string" ? obj.approach.trim() : "";
130
+ if (!approach)
131
+ return null;
132
+ const steps = Array.isArray(obj.steps)
133
+ ? obj.steps
134
+ .flatMap((s) => {
135
+ if (typeof s !== "object" || s === null)
136
+ return [];
137
+ const { path, change } = s;
138
+ return typeof path === "string" && typeof change === "string" && path.trim()
139
+ ? [{ path: path.trim(), change: change.trim() }]
140
+ : [];
141
+ })
142
+ .slice(0, 5)
143
+ : [];
144
+ return {
145
+ bugType: obj.bugType === "design" ? "design" : "interaction",
146
+ classification: typeof obj.classification === "string" ? obj.classification.trim() : "",
147
+ approach,
148
+ steps,
149
+ practices: Array.isArray(obj.practices)
150
+ ? obj.practices
151
+ .filter((p) => typeof p === "string" && p.trim().length > 0)
152
+ .slice(0, 3)
153
+ : [],
154
+ };
155
+ }
156
+ catch {
157
+ return null;
158
+ }
159
+ }
160
+ // ── The pipeline ─────────────────────────────────────────────────────────────
161
+ /**
162
+ * Propose (or re-propose, with `force`) a fix for one filed issue. Refuses
163
+ * cleanly when nothing is connected, no model key is set, or the number isn't
164
+ * an issue polishd filed; a model hiccup comes back as `provider-error`, and
165
+ * nothing is cached on failure.
166
+ */
167
+ export async function suggestIssueFix(issueNumber, force = false) {
168
+ if (!(await isGithubConnected())) {
169
+ return {
170
+ ok: false,
171
+ error: "not-connected",
172
+ message: "Connect a GitHub repository in the settings first.",
173
+ };
174
+ }
175
+ const { settings } = await resolveSettings();
176
+ if (!settings.apiKey) {
177
+ return {
178
+ ok: false,
179
+ error: "no-key",
180
+ message: "Configure a model API key in the settings first.",
181
+ };
182
+ }
183
+ const key = String(issueNumber);
184
+ if (!force) {
185
+ const cached = (await loadFixLog())[key];
186
+ if (cached)
187
+ return { ok: true, suggestion: cached, regenerated: false };
188
+ }
189
+ const filed = await findFiledIssue(issueNumber);
190
+ if (!filed) {
191
+ return {
192
+ ok: false,
193
+ error: "not-found",
194
+ message: `Issue #${issueNumber} isn't one polishd filed.`,
195
+ };
196
+ }
197
+ // Live issue text when GitHub will still give it; the stored claim otherwise.
198
+ const detail = await readGithubIssue(issueNumber);
199
+ const title = detail?.title ?? filed.claim ?? `Issue #${issueNumber}`;
200
+ const body = (detail?.body ?? "").slice(0, MAX_BODY_CHARS);
201
+ const files = await collectSource(filed.evidence, body);
202
+ const profile = await loadProjectProfile();
203
+ const sections = [
204
+ `THE ISSUE (#${issueNumber}): ${title}`,
205
+ "",
206
+ "ISSUE BODY:",
207
+ body || filed.claim || "(no body available)",
208
+ "",
209
+ `EVIDENCE (identifier from the analytics data): ${filed.evidence}`,
210
+ ];
211
+ if (profile) {
212
+ sections.push("", `PROJECT PROFILE (what this site and its components are):\n${profile.text}`);
213
+ }
214
+ if (files.length > 0) {
215
+ sections.push("", "SOURCE FILES (from the GitHub repository):", ...files.map((f) => `--- ${f.path} ---\n${f.content}`));
216
+ }
217
+ else {
218
+ sections.push("", "SOURCE FILES: none could be located for this evidence — keep steps to " +
219
+ "the paths the issue body cites, or describe where the change belongs.");
220
+ }
221
+ try {
222
+ const reply = await callModel(settings, FIX_PROMPT, sections.join("\n"), {
223
+ maxTokens: MAX_OUTPUT_TOKENS,
224
+ });
225
+ const parsed = reply.text ? parseSuggestion(reply.text) : null;
226
+ if (!parsed) {
227
+ return {
228
+ ok: false,
229
+ error: "provider-error",
230
+ message: "The model's suggestion could not be parsed. Try again.",
231
+ };
232
+ }
233
+ const suggestion = {
234
+ ...parsed,
235
+ issueNumber,
236
+ files: files.map((f) => f.path),
237
+ provider: settings.provider,
238
+ model: settings.model,
239
+ generatedAt: Date.now(),
240
+ };
241
+ const log = await loadFixLog();
242
+ log[key] = suggestion;
243
+ await setMeta(FIX_LOG_KEY, JSON.stringify(log));
244
+ return { ok: true, suggestion, regenerated: true };
245
+ }
246
+ catch (err) {
247
+ return {
248
+ ok: false,
249
+ error: "provider-error",
250
+ message: err instanceof Error ? err.message : "The model call failed.",
251
+ };
252
+ }
253
+ }
254
+ //# sourceMappingURL=fix.js.map