ctxr-cli 0.23.0 → 0.25.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 (197) hide show
  1. package/README.md +65 -5
  2. package/dist/commands/graph-diff.d.ts +33 -0
  3. package/dist/commands/graph-diff.d.ts.map +1 -0
  4. package/dist/commands/graph-diff.js +52 -0
  5. package/dist/commands/graph-diff.js.map +1 -0
  6. package/dist/commands/land.d.ts +50 -0
  7. package/dist/commands/land.d.ts.map +1 -0
  8. package/dist/commands/land.js +414 -0
  9. package/dist/commands/land.js.map +1 -0
  10. package/dist/commands/publish-check.d.ts +6 -0
  11. package/dist/commands/publish-check.d.ts.map +1 -1
  12. package/dist/commands/publish-check.js +78 -3
  13. package/dist/commands/publish-check.js.map +1 -1
  14. package/dist/commands/publish-gather.d.ts.map +1 -1
  15. package/dist/commands/publish-gather.js +4 -1
  16. package/dist/commands/publish-gather.js.map +1 -1
  17. package/dist/commands/publish-new.d.ts +5 -0
  18. package/dist/commands/publish-new.d.ts.map +1 -1
  19. package/dist/commands/publish-new.js +30 -10
  20. package/dist/commands/publish-new.js.map +1 -1
  21. package/dist/commands/publish-stamp.d.ts +32 -0
  22. package/dist/commands/publish-stamp.d.ts.map +1 -0
  23. package/dist/commands/publish-stamp.js +78 -0
  24. package/dist/commands/publish-stamp.js.map +1 -0
  25. package/dist/commands/publish-urls.d.ts +13 -0
  26. package/dist/commands/publish-urls.d.ts.map +1 -1
  27. package/dist/commands/publish-urls.js +23 -6
  28. package/dist/commands/publish-urls.js.map +1 -1
  29. package/dist/commands/review-list.d.ts +34 -0
  30. package/dist/commands/review-list.d.ts.map +1 -0
  31. package/dist/commands/review-list.js +49 -0
  32. package/dist/commands/review-list.js.map +1 -0
  33. package/dist/commands/serve.d.ts +3 -6
  34. package/dist/commands/serve.d.ts.map +1 -1
  35. package/dist/commands/serve.js +106 -9
  36. package/dist/commands/serve.js.map +1 -1
  37. package/dist/config/schema.d.ts +40 -0
  38. package/dist/config/schema.d.ts.map +1 -1
  39. package/dist/config/schema.js +39 -0
  40. package/dist/config/schema.js.map +1 -1
  41. package/dist/core/approval/decision.d.ts +73 -0
  42. package/dist/core/approval/decision.d.ts.map +1 -0
  43. package/dist/core/approval/decision.js +166 -0
  44. package/dist/core/approval/decision.js.map +1 -0
  45. package/dist/core/approval/file-diff.d.ts +32 -0
  46. package/dist/core/approval/file-diff.d.ts.map +1 -0
  47. package/dist/core/approval/file-diff.js +83 -0
  48. package/dist/core/approval/file-diff.js.map +1 -0
  49. package/dist/core/approval/identity.d.ts +34 -0
  50. package/dist/core/approval/identity.d.ts.map +1 -0
  51. package/dist/core/approval/identity.js +105 -0
  52. package/dist/core/approval/identity.js.map +1 -0
  53. package/dist/core/approval/landing-record.d.ts +17 -0
  54. package/dist/core/approval/landing-record.d.ts.map +1 -0
  55. package/dist/core/approval/landing-record.js +30 -0
  56. package/dist/core/approval/landing-record.js.map +1 -0
  57. package/dist/core/approval/resolver.d.ts +15 -0
  58. package/dist/core/approval/resolver.d.ts.map +1 -0
  59. package/dist/core/approval/resolver.js +41 -0
  60. package/dist/core/approval/resolver.js.map +1 -0
  61. package/dist/core/approval/sessions.d.ts +36 -0
  62. package/dist/core/approval/sessions.d.ts.map +1 -0
  63. package/dist/core/approval/sessions.js +76 -0
  64. package/dist/core/approval/sessions.js.map +1 -0
  65. package/dist/core/browse/approve.d.ts +45 -0
  66. package/dist/core/browse/approve.d.ts.map +1 -0
  67. package/dist/core/browse/approve.js +239 -0
  68. package/dist/core/browse/approve.js.map +1 -0
  69. package/dist/core/browse/diagram-assets.d.ts +15 -0
  70. package/dist/core/browse/diagram-assets.d.ts.map +1 -0
  71. package/dist/core/browse/diagram-assets.js +35 -0
  72. package/dist/core/browse/diagram-assets.js.map +1 -0
  73. package/dist/core/browse/page-url.d.ts +22 -0
  74. package/dist/core/browse/page-url.d.ts.map +1 -1
  75. package/dist/core/browse/page-url.js +31 -0
  76. package/dist/core/browse/page-url.js.map +1 -1
  77. package/dist/core/browse/render.d.ts +10 -1
  78. package/dist/core/browse/render.d.ts.map +1 -1
  79. package/dist/core/browse/render.js +23 -1
  80. package/dist/core/browse/render.js.map +1 -1
  81. package/dist/core/browse/review.d.ts +21 -0
  82. package/dist/core/browse/review.d.ts.map +1 -0
  83. package/dist/core/browse/review.js +52 -0
  84. package/dist/core/browse/review.js.map +1 -0
  85. package/dist/core/browse/templates.d.ts +4 -1
  86. package/dist/core/browse/templates.d.ts.map +1 -1
  87. package/dist/core/browse/templates.js +18 -2
  88. package/dist/core/browse/templates.js.map +1 -1
  89. package/dist/core/checks/organize-checks.d.ts +17 -0
  90. package/dist/core/checks/organize-checks.d.ts.map +1 -1
  91. package/dist/core/checks/organize-checks.js +116 -0
  92. package/dist/core/checks/organize-checks.js.map +1 -1
  93. package/dist/core/errors.d.ts +67 -0
  94. package/dist/core/errors.d.ts.map +1 -1
  95. package/dist/core/errors.js +160 -0
  96. package/dist/core/errors.js.map +1 -1
  97. package/dist/core/forge/credentials.d.ts +69 -0
  98. package/dist/core/forge/credentials.d.ts.map +1 -0
  99. package/dist/core/forge/credentials.js +197 -0
  100. package/dist/core/forge/credentials.js.map +1 -0
  101. package/dist/core/forge/github.d.ts +73 -0
  102. package/dist/core/forge/github.d.ts.map +1 -0
  103. package/dist/core/forge/github.js +101 -0
  104. package/dist/core/forge/github.js.map +1 -0
  105. package/dist/core/git/exec.d.ts +25 -0
  106. package/dist/core/git/exec.d.ts.map +1 -1
  107. package/dist/core/git/exec.js +100 -2
  108. package/dist/core/git/exec.js.map +1 -1
  109. package/dist/core/graph/diff-block.d.ts +6 -0
  110. package/dist/core/graph/diff-block.d.ts.map +1 -0
  111. package/dist/core/graph/diff-block.js +63 -0
  112. package/dist/core/graph/diff-block.js.map +1 -0
  113. package/dist/core/graph/diff-document.d.ts +38 -0
  114. package/dist/core/graph/diff-document.d.ts.map +1 -0
  115. package/dist/core/graph/diff-document.js +117 -0
  116. package/dist/core/graph/diff-document.js.map +1 -0
  117. package/dist/core/graph/diff.d.ts +123 -0
  118. package/dist/core/graph/diff.d.ts.map +1 -0
  119. package/dist/core/graph/diff.js +253 -0
  120. package/dist/core/graph/diff.js.map +1 -0
  121. package/dist/core/graph/tree.d.ts +24 -0
  122. package/dist/core/graph/tree.d.ts.map +1 -0
  123. package/dist/core/graph/tree.js +45 -0
  124. package/dist/core/graph/tree.js.map +1 -0
  125. package/dist/core/notes/list.d.ts +10 -0
  126. package/dist/core/notes/list.d.ts.map +1 -1
  127. package/dist/core/notes/list.js +35 -12
  128. package/dist/core/notes/list.js.map +1 -1
  129. package/dist/core/publish/filing.d.ts +12 -12
  130. package/dist/core/publish/filing.d.ts.map +1 -1
  131. package/dist/core/publish/filing.js +20 -18
  132. package/dist/core/publish/filing.js.map +1 -1
  133. package/dist/core/publish/lifespan.d.ts +37 -0
  134. package/dist/core/publish/lifespan.d.ts.map +1 -0
  135. package/dist/core/publish/lifespan.js +59 -0
  136. package/dist/core/publish/lifespan.js.map +1 -0
  137. package/dist/core/publish/represents.d.ts +72 -0
  138. package/dist/core/publish/represents.d.ts.map +1 -0
  139. package/dist/core/publish/represents.js +83 -0
  140. package/dist/core/publish/represents.js.map +1 -0
  141. package/dist/run.d.ts.map +1 -1
  142. package/dist/run.js +60 -4
  143. package/dist/run.js.map +1 -1
  144. package/dist/version.d.ts +1 -1
  145. package/dist/version.js +1 -1
  146. package/package.json +2 -1
  147. package/templates/approve/approve-button.md +1 -0
  148. package/templates/approve/author-heading.md +1 -0
  149. package/templates/approve/author-note.md +1 -0
  150. package/templates/approve/comment-label.md +1 -0
  151. package/templates/approve/comment-required.md +1 -0
  152. package/templates/approve/commits-heading.md +1 -0
  153. package/templates/approve/decision-heading.md +1 -0
  154. package/templates/approve/decision-note.md +1 -0
  155. package/templates/approve/diff-binary.md +1 -0
  156. package/templates/approve/diff-empty.md +1 -0
  157. package/templates/approve/diff-heading.md +1 -0
  158. package/templates/approve/facts-heading.md +1 -0
  159. package/templates/approve/forge-unreachable.md +1 -0
  160. package/templates/approve/github-app-manifest.json +15 -0
  161. package/templates/approve/head-missing.md +1 -0
  162. package/templates/approve/index-empty.md +1 -0
  163. package/templates/approve/index-heading.md +1 -0
  164. package/templates/approve/index-intro.md +1 -0
  165. package/templates/approve/landed.md +1 -0
  166. package/templates/approve/moved-head.md +1 -0
  167. package/templates/approve/no-pull.md +1 -0
  168. package/templates/approve/not-open.md +1 -0
  169. package/templates/approve/pages-heading.md +1 -0
  170. package/templates/approve/pages-note.md +1 -0
  171. package/templates/approve/record-failed.md +1 -0
  172. package/templates/approve/request-changes-button.md +1 -0
  173. package/templates/approve/state-line.md +1 -0
  174. package/templates/conventions/baseline-conventions.md +6 -0
  175. package/templates/graph/knowledge-changes/archived-item.md +1 -0
  176. package/templates/graph/knowledge-changes/archived.md +1 -0
  177. package/templates/graph/knowledge-changes/bare-route.md +2 -0
  178. package/templates/graph/knowledge-changes/block.md +10 -0
  179. package/templates/graph/knowledge-changes/counts.md +1 -0
  180. package/templates/graph/knowledge-changes/dangling-item.md +1 -0
  181. package/templates/graph/knowledge-changes/dangling.md +1 -0
  182. package/templates/graph/knowledge-changes/empty.md +1 -0
  183. package/templates/graph/knowledge-changes/reason-ambiguous.md +1 -0
  184. package/templates/graph/knowledge-changes/reason-not_found.md +1 -0
  185. package/templates/graph/knowledge-changes/review.md +4 -0
  186. package/templates/graph/review/moved-head.md +1 -0
  187. package/templates/land/resolver.md +12 -0
  188. package/templates/serve/diagrams.mjs +136 -0
  189. package/templates/serve/shell.html +1 -1
  190. package/templates/serve/style.css +90 -0
  191. package/templates/skills/ctxr-land.md +37 -31
  192. package/templates/skills/ctxr-organize-audit.md +19 -0
  193. package/templates/skills/ctxr-publish.md +100 -45
  194. package/templates/skills/ctxr-second-opinion/run.mjs +28 -17
  195. package/templates/skills/ctxr-second-opinion.md +19 -14
  196. package/templates/skills/ctxr-session-lifecycle.md +9 -0
  197. package/templates/skills/ctxr-submit.md +28 -17
@@ -0,0 +1,76 @@
1
+ import path from 'node:path';
2
+ import { ForgeUnreachableError } from '../errors.js';
3
+ import { patchIds } from '../git/exec.js';
4
+ import { listWorktrees } from '../git/worktree.js';
5
+ import { ForgeRequestError } from '../forge/github.js';
6
+ import { isSessionBranch, isSessionWorktreePath } from '../session.js';
7
+ import { resolveReviewState } from './decision.js';
8
+ /** The session worktrees git knows, recognized as `ctxr session list` recognizes them. */
9
+ export async function sessionWorktrees(git, repoCwd, config) {
10
+ const worktrees = await listWorktrees(git, repoCwd);
11
+ return worktrees
12
+ .filter((w) => w.branch !== null && (isSessionBranch(config, w.branch) || isSessionWorktreePath(config, w.path)))
13
+ .map((w) => ({ name: path.basename(w.path), path: w.path, branch: w.branch }));
14
+ }
15
+ /** `origin/<default>` when the repository has that ref, else the local default branch — the review route's own rule. */
16
+ export async function baseRef(git, cwd, defaultBranch) {
17
+ const remote = await git.run(['rev-parse', '--verify', '--quiet', `refs/remotes/origin/${defaultBranch}`], { cwd, allowFailure: true });
18
+ return remote.exitCode === 0 ? `origin/${defaultBranch}` : defaultBranch;
19
+ }
20
+ /**
21
+ * write-lifecycle spec (design.md D5): whether `currentHead` carries over the
22
+ * approval of `approvedHead` — each head's commits since it left `base`, compared
23
+ * by patch identity, commit for commit. Anything that cannot be computed (an
24
+ * approved head no longer in this repository) is "no".
25
+ */
26
+ export async function carriesOver(git, cwd, base, approvedHead, currentHead) {
27
+ try {
28
+ const forkOf = async (head) => (await git.run(['merge-base', head, base], { cwd })).stdout.trim();
29
+ const before = await patchIds(cwd, `${await forkOf(approvedHead)}..${approvedHead}`);
30
+ const after = await patchIds(cwd, `${await forkOf(currentHead)}..${currentHead}`);
31
+ return before.length > 0 && before.length === after.length && before.every((id, i) => id === after[i]);
32
+ }
33
+ catch {
34
+ return false;
35
+ }
36
+ }
37
+ /** Every forge call here, turned into the usage error the spec asks for when the forge cannot be read. */
38
+ export async function forgeRead(call) {
39
+ try {
40
+ return await call();
41
+ }
42
+ catch (err) {
43
+ if (err instanceof ForgeRequestError)
44
+ throw new ForgeUnreachableError(err.message);
45
+ throw err;
46
+ }
47
+ }
48
+ /** One pull request's decision state, with an approval of an earlier head upgraded when the current head carries it over. */
49
+ export async function reviewStateOf(git, cwd, base, forge, recordingLogin, pull) {
50
+ const [reviews, comments] = await Promise.all([forge.reviews(pull.number), forge.comments(pull.number)]);
51
+ const state = resolveReviewState({ reviews, comments, recordingLogin, head: pull.headSha });
52
+ if (state.approvalNeedsCarryCheck && state.decision !== null && (await carriesOver(git, cwd, base, state.decision.head, pull.headSha))) {
53
+ return { ...state, state: 'approved', approvalNeedsCarryCheck: false };
54
+ }
55
+ return state;
56
+ }
57
+ /**
58
+ * change-approval spec: every session worktree whose branch has an open pull
59
+ * request, with its decision state. A worktree with no open pull request is
60
+ * left out.
61
+ */
62
+ export async function sessionPulls(git, repoCwd, config, forge, recordingLogin) {
63
+ const worktrees = await sessionWorktrees(git, repoCwd, config);
64
+ const open = await forgeRead(() => forge.openPulls());
65
+ const base = await baseRef(git, repoCwd, config.git.default_branch);
66
+ const result = [];
67
+ for (const worktree of worktrees) {
68
+ const pull = open.find((p) => p.headRef === worktree.branch);
69
+ if (pull === undefined)
70
+ continue;
71
+ const review = await forgeRead(() => reviewStateOf(git, worktree.path, base, forge, recordingLogin, pull));
72
+ result.push({ ...worktree, pull, review });
73
+ }
74
+ return result;
75
+ }
76
+ //# sourceMappingURL=sessions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sessions.js","sourceRoot":"","sources":["../../../src/core/approval/sessions.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,45 @@
1
+ import type { IncomingMessage } from 'node:http';
2
+ import type { ChangeApprovalConfig } from '../../config/schema.js';
3
+ import type { IdentityVerifier } from '../approval/identity.js';
4
+ import type { ForgeClient } from '../forge/github.js';
5
+ import type { GitRunner } from '../git/exec.js';
6
+ import type { Store } from '../store.js';
7
+ import type { LinkResolver } from './link-resolver.js';
8
+ import { type RenderedBody } from './render.js';
9
+ /**
10
+ * change-approval spec: the approval index, one session's approval page, and
11
+ * the one route on this server that admits `POST`. Every path under the prefix
12
+ * is answered here, and only after the identity assertion verifies — nothing
13
+ * about the store or the forge is read before that.
14
+ */
15
+ export declare const APPROVE_ROUTE_PREFIX = "/approve/";
16
+ export interface ApprovalServer {
17
+ approval: ChangeApprovalConfig;
18
+ /** The origin of `serve.base_url`, which a decision's `Origin` header must equal (design.md D9). */
19
+ origin: string;
20
+ forge: ForgeClient;
21
+ verifier: IdentityVerifier;
22
+ git: GitRunner;
23
+ now(): Date;
24
+ }
25
+ /** What a route needs from the browsing surface once the requester is known: the shell, and note links. */
26
+ export interface PageKit {
27
+ page(title: string, body: RenderedBody): Promise<string>;
28
+ linkFor(notePath: string): string | null;
29
+ resolveLink: LinkResolver;
30
+ }
31
+ export interface Reply {
32
+ status: number;
33
+ contentType: string;
34
+ body: string;
35
+ headers?: Record<string, string>;
36
+ }
37
+ export declare function isApprovePath(pathname: string): boolean;
38
+ export declare function isDecisionRoute(pathname: string): boolean;
39
+ /**
40
+ * Answers every request under the approval prefix. `server` is null when the
41
+ * store declares no change approval, and then every such path is `404`.
42
+ * `makeKit` builds the browsing surface's shell only after the requester is known.
43
+ */
44
+ export declare function handleApprove(store: Store, server: ApprovalServer | null, req: IncomingMessage, method: string, pathname: string, makeKit: () => Promise<PageKit>): Promise<Reply>;
45
+ //# sourceMappingURL=approve.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"approve.d.ts","sourceRoot":"","sources":["../../../src/core/browse/approve.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AACjD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAInE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAIhE,OAAO,KAAK,EAAE,WAAW,EAAe,MAAM,oBAAoB,CAAC;AAEnE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAEhD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAEzC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,EAA8B,KAAK,YAAY,EAAE,MAAM,aAAa,CAAC;AAG5E;;;;;GAKG;AACH,eAAO,MAAM,oBAAoB,cAAc,CAAC;AAOhD,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,oBAAoB,CAAC;IAC/B,oGAAoG;IACpG,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,WAAW,CAAC;IACnB,QAAQ,EAAE,gBAAgB,CAAC;IAC3B,GAAG,EAAE,SAAS,CAAC;IACf,GAAG,IAAI,IAAI,CAAC;CACb;AAED,2GAA2G;AAC3G,MAAM,WAAW,OAAO;IACtB,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IACzD,OAAO,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;IACzC,WAAW,EAAE,YAAY,CAAC;CAC3B;AAED,MAAM,WAAW,KAAK;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAClC;AAQD,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAEvD;AAED,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAEzD;AAwND;;;;GAIG;AACH,wBAAsB,aAAa,CACjC,KAAK,EAAE,KAAK,EACZ,MAAM,EAAE,cAAc,GAAG,IAAI,EAC7B,GAAG,EAAE,eAAe,EACpB,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,GAC9B,OAAO,CAAC,KAAK,CAAC,CAgBhB"}
@@ -0,0 +1,239 @@
1
+ import path from 'node:path';
2
+ import { pageUrlsFor } from '../../commands/publish-urls.js';
3
+ import { decisionBody, isDecider } from '../approval/decision.js';
4
+ import { readFileDiffs, renderFileDiffs } from '../approval/file-diff.js';
5
+ import { readLandingRecord } from '../approval/landing-record.js';
6
+ import { baseRef, forgeRead, reviewStateOf, sessionPulls, sessionWorktrees } from '../approval/sessions.js';
7
+ import { ForgeUnreachableError } from '../errors.js';
8
+ import { ForgeRequestError } from '../forge/github.js';
9
+ import { storePrefix } from '../graph/tree.js';
10
+ import { packagedTemplate } from '../templates.js';
11
+ import { escapeHtml, renderNoteBody } from './render.js';
12
+ import { renderReview } from './review.js';
13
+ /**
14
+ * change-approval spec: the approval index, one session's approval page, and
15
+ * the one route on this server that admits `POST`. Every path under the prefix
16
+ * is answered here, and only after the identity assertion verifies — nothing
17
+ * about the store or the forge is read before that.
18
+ */
19
+ export const APPROVE_ROUTE_PREFIX = '/approve/';
20
+ const DECISION_ROUTE = /^\/approve\/([^/]+)\/decision$/;
21
+ const PAGE_ROUTE = /^\/approve\/([^/]+)\/?$/;
22
+ const SHA = /^[0-9a-f]{40}$/;
23
+ const MAX_FORM_BYTES = 64 * 1024;
24
+ const MAX_COMMENT_CHARS = 20_000;
25
+ const text = (status, message) => ({ status, contentType: 'text/plain; charset=utf-8', body: `${message}\n` });
26
+ function copy(name) {
27
+ return packagedTemplate('approve', name);
28
+ }
29
+ export function isApprovePath(pathname) {
30
+ return pathname === '/approve' || pathname.startsWith(APPROVE_ROUTE_PREFIX);
31
+ }
32
+ export function isDecisionRoute(pathname) {
33
+ return DECISION_ROUTE.test(pathname);
34
+ }
35
+ function approveRoute(name) {
36
+ return `${APPROVE_ROUTE_PREFIX}${encodeURIComponent(name)}/`;
37
+ }
38
+ const STATE_LABEL = {
39
+ awaiting: 'awaiting a decision',
40
+ approved: 'approved, landing shortly',
41
+ 'changes-requested': 'changes requested',
42
+ 'needs-reapproval': 'needs a new decision',
43
+ blocked: 'blocked',
44
+ };
45
+ async function readForm(req) {
46
+ const chunks = [];
47
+ let size = 0;
48
+ for await (const chunk of req) {
49
+ size += chunk.length;
50
+ if (size > MAX_FORM_BYTES)
51
+ return null;
52
+ chunks.push(chunk);
53
+ }
54
+ return new URLSearchParams(Buffer.concat(chunks).toString('utf8'));
55
+ }
56
+ async function locate(store, server, name) {
57
+ const worktree = (await sessionWorktrees(server.git, store.root, store.config)).find((w) => w.name === name);
58
+ if (worktree === undefined)
59
+ return null;
60
+ const open = await forgeRead(() => server.forge.openPulls());
61
+ return { name, worktreePath: worktree.path, branch: worktree.branch, pull: open.find((p) => p.headRef === worktree.branch) ?? null };
62
+ }
63
+ async function indexPage(store, server, kit) {
64
+ const html = [`<h1>${escapeHtml(copy('index-heading'))}</h1>`];
65
+ try {
66
+ const pulls = await sessionPulls(server.git, store.root, store.config, server.forge, server.approval.recording_login);
67
+ if (pulls.length === 0) {
68
+ html.push(`<p class="ctxr-empty">${escapeHtml(copy('index-empty'))}</p>`);
69
+ }
70
+ else {
71
+ html.push(`<p>${escapeHtml(copy('index-intro'))}</p>`);
72
+ html.push('<table class="ctxr-approve-index"><thead><tr><th>Change</th><th>Pull request</th><th>Commit</th><th>State</th></tr></thead><tbody>');
73
+ for (const p of pulls) {
74
+ html.push(`<tr><td><a href="${approveRoute(p.name)}">${escapeHtml(p.name)}</a></td><td>#${p.pull.number}</td>` +
75
+ `<td><code>${escapeHtml(p.pull.headSha.slice(0, 7))}</code></td><td>${escapeHtml(STATE_LABEL[p.review.state])}</td></tr>`);
76
+ }
77
+ html.push('</tbody></table>');
78
+ }
79
+ }
80
+ catch (err) {
81
+ if (!(err instanceof ForgeUnreachableError))
82
+ throw err;
83
+ html.push(`<p class="ctxr-approve-notice">${escapeHtml(copy('forge-unreachable'))}</p>`);
84
+ }
85
+ return { status: 200, contentType: 'text/html; charset=utf-8', body: await kit.page('approve', { html: html.join('\n'), hasDiagram: false }) };
86
+ }
87
+ async function renderChangePage(store, server, kit, name, notice = {}) {
88
+ const title = `approve — ${name}`;
89
+ const shell = async (status, parts, hasDiagram = false) => ({
90
+ status,
91
+ contentType: 'text/html; charset=utf-8',
92
+ body: await kit.page(title, { html: parts.join('\n'), hasDiagram }),
93
+ });
94
+ const html = [`<h1>${escapeHtml(name)}</h1>`];
95
+ if (notice.message !== undefined)
96
+ html.push(`<p class="ctxr-approve-notice">${escapeHtml(notice.message)}</p>`);
97
+ let located;
98
+ try {
99
+ located = await locate(store, server, name);
100
+ }
101
+ catch (err) {
102
+ if (!(err instanceof ForgeUnreachableError))
103
+ throw err;
104
+ return shell(notice.status ?? 200, [...html, `<p class="ctxr-approve-notice">${escapeHtml(copy('forge-unreachable'))}</p>`]);
105
+ }
106
+ if (located === null) {
107
+ const record = await readLandingRecord(store.root, name);
108
+ if (record === null)
109
+ return text(404, 'not found');
110
+ const landed = escapeHtml(copy('landed'))
111
+ .replace('__PR__', () => String(record.pull_request))
112
+ .replace('__COMMIT__', () => `<code>${escapeHtml(record.merged_commit ?? 'unknown')}</code>`);
113
+ return shell(200, [...html, `<p>${landed}</p>`]);
114
+ }
115
+ if (located.pull === null)
116
+ return shell(notice.status ?? 200, [...html, `<p class="ctxr-empty">${escapeHtml(copy('no-pull'))}</p>`]);
117
+ const pull = located.pull;
118
+ const head = pull.headSha;
119
+ if (notice.movedFrom !== undefined) {
120
+ const moved = escapeHtml(copy('moved-head'))
121
+ .replace('__RECORDED__', () => `<code>${escapeHtml(notice.movedFrom)}</code>`)
122
+ .replace('__CURRENT__', () => `<code>${escapeHtml(head)}</code>`);
123
+ html.push(`<p class="ctxr-review-moved">${moved}</p>`);
124
+ }
125
+ const present = await server.git.run(['cat-file', '-e', `${head}^{commit}`], { cwd: located.worktreePath, allowFailure: true });
126
+ if (present.exitCode !== 0) {
127
+ return shell(notice.status ?? 200, [...html, `<p class="ctxr-approve-notice">${escapeHtml(copy('head-missing')).replace('__HEAD__', () => `<code>${escapeHtml(head)}</code>`)}</p>`]);
128
+ }
129
+ const base = await baseRef(server.git, located.worktreePath, store.config.git.default_branch);
130
+ const prefix = await storePrefix(server.git, store.root);
131
+ const worktreeStoreRoot = path.join(located.worktreePath, prefix);
132
+ const state = await forgeRead(() => reviewStateOf(server.git, located.worktreePath, base, server.forge, server.approval.recording_login, pull));
133
+ let hasDiagram = false;
134
+ html.push(`<p>Pull request <a href="${escapeHtml(pull.url)}">#${pull.number}</a>, commit <code>${escapeHtml(head)}</code>. ${escapeHtml(copy('state-line').replace('__STATE__', STATE_LABEL[state.state]))}</p>`);
135
+ // The author's account: labelled as such, and kept apart from everything computed below.
136
+ const authorBody = renderNoteBody(pull.body, kit.resolveLink);
137
+ hasDiagram ||= authorBody.hasDiagram;
138
+ const log = await server.git.run(['log', '--reverse', '--no-color', '--format=%H%x1f%B%x1e', `${base}..${head}`], { cwd: located.worktreePath });
139
+ const commits = log.stdout
140
+ .split('\x1e')
141
+ .map((entry) => entry.trim())
142
+ .filter(Boolean)
143
+ .map((entry) => {
144
+ const [sha, message] = entry.split('\x1f');
145
+ return `<li><code>${escapeHtml(sha.slice(0, 7))}</code><pre class="ctxr-commit-message">${escapeHtml(message.trim())}</pre></li>`;
146
+ });
147
+ html.push(`<section class="ctxr-author-account"><h2>${escapeHtml(copy('author-heading'))}</h2>`, `<p class="ctxr-summary">${escapeHtml(copy('author-note'))}</p>`, `<h3>${escapeHtml(pull.title)}</h3>`, authorBody.html, `<h3>${escapeHtml(copy('commits-heading'))}</h3><ol class="ctxr-commits">${commits.join('\n')}</ol>`, '</section>');
148
+ const facts = await renderReview(store, name, null, kit.linkFor, kit.resolveLink, head);
149
+ hasDiagram ||= facts.hasDiagram;
150
+ html.push(`<section class="ctxr-derived"><h2>${escapeHtml(copy('facts-heading'))}</h2>`, facts.html, '</section>');
151
+ const pages = await pageUrlsFor({ root: worktreeStoreRoot, config: store.config }, [`${base}...${head}`]);
152
+ if (pages.length > 0) {
153
+ const link = (address) => address === null ? '—' : `<a href="${escapeHtml(address.url ?? address.route)}">${escapeHtml(address.url ?? address.route)}</a>`;
154
+ const rows = pages.map((p) => `<tr><td>${escapeHtml(p.status)}</td><td>${escapeHtml(p.lifespan)}</td><td><code>${escapeHtml(p.path)}</code></td>` +
155
+ `<td>${p.status === 'removed' ? '—' : link(p.preview)}</td><td>${link(p.published)}</td></tr>`);
156
+ html.push(`<section class="ctxr-pages"><h2>${escapeHtml(copy('pages-heading'))}</h2><p class="ctxr-summary">${escapeHtml(copy('pages-note'))}</p>`, `<table><thead><tr><th>Status</th><th>Lifespan</th><th>Page</th><th>Preview</th><th>Published</th></tr></thead><tbody>${rows.join('')}</tbody></table></section>`);
157
+ }
158
+ const files = await readFileDiffs(server.git, worktreeStoreRoot, base, head, store.config.derived.paths);
159
+ html.push(`<section class="ctxr-changed-files"><h2>${escapeHtml(copy('diff-heading'))}</h2>`, renderFileDiffs(files, { binary: copy('diff-binary'), noFiles: copy('diff-empty') }), '</section>');
160
+ const action = `${approveRoute(name)}decision`;
161
+ const note = escapeHtml(copy('decision-note')).replace('__HEAD__', () => `<code>${escapeHtml(head.slice(0, 7))}</code>`);
162
+ html.push(`<section class="ctxr-decision"><h2>${escapeHtml(copy('decision-heading'))}</h2><p>${note}</p>`, `<form method="post" action="${action}"><input type="hidden" name="decision" value="approve"><input type="hidden" name="head" value="${head}"><button type="submit">${escapeHtml(copy('approve-button'))}</button></form>`, `<form method="post" action="${action}"><input type="hidden" name="decision" value="request-changes"><input type="hidden" name="head" value="${head}">` +
163
+ `<label for="ctxr-comment">${escapeHtml(copy('comment-label'))}</label><textarea id="ctxr-comment" name="comment" rows="5" required></textarea>` +
164
+ `<button type="submit">${escapeHtml(copy('request-changes-button'))}</button></form>`, '</section>');
165
+ return shell(notice.status ?? 200, html, hasDiagram);
166
+ }
167
+ async function decide(store, server, kit, req, name, email) {
168
+ if (req.headers.origin !== server.origin)
169
+ return text(403, 'cross-site decision refused');
170
+ const form = await readForm(req);
171
+ if (form === null)
172
+ return text(413, 'decision too large');
173
+ const decision = form.get('decision');
174
+ const head = form.get('head') ?? '';
175
+ const comment = (form.get('comment') ?? '').trim();
176
+ if ((decision !== 'approve' && decision !== 'request-changes') || !SHA.test(head))
177
+ return text(400, 'malformed decision');
178
+ if (comment.length > MAX_COMMENT_CHARS)
179
+ return text(413, 'comment too long');
180
+ let located;
181
+ try {
182
+ located = await locate(store, server, name);
183
+ }
184
+ catch (err) {
185
+ if (!(err instanceof ForgeUnreachableError))
186
+ throw err;
187
+ return renderChangePage(store, server, kit, name, { status: 502, message: copy('record-failed') });
188
+ }
189
+ if (located === null)
190
+ return text(404, 'not found');
191
+ if (located.pull === null || located.pull.state !== 'open')
192
+ return renderChangePage(store, server, kit, name, { status: 409, message: copy('not-open') });
193
+ if (located.pull.headSha !== head)
194
+ return renderChangePage(store, server, kit, name, { status: 409, movedFrom: head });
195
+ if (decision === 'request-changes' && comment === '')
196
+ return renderChangePage(store, server, kit, name, { status: 400, message: copy('comment-required') });
197
+ const kind = decision;
198
+ try {
199
+ await server.forge.createReview(located.pull.number, {
200
+ event: kind === 'approve' ? 'APPROVE' : 'REQUEST_CHANGES',
201
+ commitId: head,
202
+ body: decisionBody({ decision: kind, head, by: email, at: server.now().toISOString(), carriedFrom: null, comment: kind === 'approve' ? null : comment }),
203
+ });
204
+ }
205
+ catch (err) {
206
+ if (!(err instanceof ForgeRequestError))
207
+ throw err;
208
+ return renderChangePage(store, server, kit, name, { status: 502, message: copy('record-failed') });
209
+ }
210
+ // Post/redirect/get: the page the decider lands on reads the recorded state back from the forge.
211
+ return { status: 303, contentType: 'text/plain; charset=utf-8', body: 'recorded\n', headers: { Location: approveRoute(name) } };
212
+ }
213
+ /**
214
+ * Answers every request under the approval prefix. `server` is null when the
215
+ * store declares no change approval, and then every such path is `404`.
216
+ * `makeKit` builds the browsing surface's shell only after the requester is known.
217
+ */
218
+ export async function handleApprove(store, server, req, method, pathname, makeKit) {
219
+ if (server === null)
220
+ return text(404, 'not found');
221
+ const verified = await server.verifier.verify(req.headers[server.approval.identity.header.toLowerCase()]);
222
+ if (!verified.ok)
223
+ return text(401, 'a verified identity assertion is required');
224
+ if (!isDecider(verified.email, server.approval.deciders))
225
+ return text(403, 'this identity may not decide on changes here');
226
+ const decisionMatch = DECISION_ROUTE.exec(pathname);
227
+ if (method === 'POST') {
228
+ if (decisionMatch === null)
229
+ return text(405, 'method not allowed');
230
+ return decide(store, server, await makeKit(), req, decisionMatch[1], verified.email);
231
+ }
232
+ if (pathname === '/approve' || pathname === APPROVE_ROUTE_PREFIX)
233
+ return indexPage(store, server, await makeKit());
234
+ const pageMatch = PAGE_ROUTE.exec(pathname);
235
+ if (pageMatch === null)
236
+ return text(404, 'not found');
237
+ return renderChangePage(store, server, await makeKit(), pageMatch[1]);
238
+ }
239
+ //# sourceMappingURL=approve.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"approve.js","sourceRoot":"","sources":["../../../src/core/browse/approve.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ /** The page script that draws each diagram block; a file under `templates/serve/`. */
2
+ export declare const DIAGRAM_SCRIPT_ROUTE = "/assets/diagrams.mjs";
3
+ export declare const DIAGRAM_SCRIPT_FILE = "diagrams.mjs";
4
+ /** Every renderer route starts here; one naming any version but the installed one is a 404. */
5
+ export declare const RENDERER_ROUTE_PREFIX = "/assets/mermaid/";
6
+ export interface DiagramRenderer {
7
+ /** Absolute path of the renderer file inside the installed dependency. */
8
+ filePath: string;
9
+ version: string;
10
+ /** `/assets/mermaid/<version>/mermaid.tiny.js`. */
11
+ route: string;
12
+ }
13
+ /** Resolved once and memoized: the installed dependency cannot change under a running process. */
14
+ export declare function diagramRenderer(): DiagramRenderer;
15
+ //# sourceMappingURL=diagram-assets.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diagram-assets.d.ts","sourceRoot":"","sources":["../../../src/core/browse/diagram-assets.ts"],"names":[],"mappings":"AAgBA,sFAAsF;AACtF,eAAO,MAAM,oBAAoB,yBAAyB,CAAC;AAC3D,eAAO,MAAM,mBAAmB,iBAAiB,CAAC;AAElD,+FAA+F;AAC/F,eAAO,MAAM,qBAAqB,qBAAqB,CAAC;AAExD,MAAM,WAAW,eAAe;IAC9B,0EAA0E;IAC1E,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,mDAAmD;IACnD,KAAK,EAAE,MAAM,CAAC;CACf;AAID,kGAAkG;AAClG,wBAAgB,eAAe,IAAI,eAAe,CAWjD"}
@@ -0,0 +1,35 @@
1
+ import { readFileSync } from 'node:fs';
2
+ import { createRequire } from 'node:module';
3
+ import path from 'node:path';
4
+ /**
5
+ * render-diagrams-in-notes design.md D4/D6: the diagram renderer is the
6
+ * installed `@mermaid-js/tiny` dependency's single-file build, served from
7
+ * where npm put it rather than copied into `templates/`. Its route carries
8
+ * the installed version, so an upgrade changes the URL and an immutably
9
+ * cached copy can never go stale. The shell builds its script references
10
+ * and `serve.ts` matches requests from the constants here — two readers,
11
+ * one spelling.
12
+ */
13
+ const RENDERER_PACKAGE = '@mermaid-js/tiny';
14
+ const RENDERER_FILE = 'mermaid.tiny.js';
15
+ /** The page script that draws each diagram block; a file under `templates/serve/`. */
16
+ export const DIAGRAM_SCRIPT_ROUTE = '/assets/diagrams.mjs';
17
+ export const DIAGRAM_SCRIPT_FILE = 'diagrams.mjs';
18
+ /** Every renderer route starts here; one naming any version but the installed one is a 404. */
19
+ export const RENDERER_ROUTE_PREFIX = '/assets/mermaid/';
20
+ let resolved;
21
+ /** Resolved once and memoized: the installed dependency cannot change under a running process. */
22
+ export function diagramRenderer() {
23
+ if (resolved)
24
+ return resolved;
25
+ const require = createRequire(import.meta.url);
26
+ const manifestPath = require.resolve(`${RENDERER_PACKAGE}/package.json`);
27
+ const { version } = JSON.parse(readFileSync(manifestPath, 'utf8'));
28
+ resolved = {
29
+ filePath: path.join(path.dirname(manifestPath), 'dist', RENDERER_FILE),
30
+ version,
31
+ route: `${RENDERER_ROUTE_PREFIX}${version}/${RENDERER_FILE}`,
32
+ };
33
+ return resolved;
34
+ }
35
+ //# sourceMappingURL=diagram-assets.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diagram-assets.js","sourceRoot":"","sources":["../../../src/core/browse/diagram-assets.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B;;;;;;;;GAQG;AACH,MAAM,gBAAgB,GAAG,kBAAkB,CAAC;AAC5C,MAAM,aAAa,GAAG,iBAAiB,CAAC;AAExC,sFAAsF;AACtF,MAAM,CAAC,MAAM,oBAAoB,GAAG,sBAAsB,CAAC;AAC3D,MAAM,CAAC,MAAM,mBAAmB,GAAG,cAAc,CAAC;AAElD,+FAA+F;AAC/F,MAAM,CAAC,MAAM,qBAAqB,GAAG,kBAAkB,CAAC;AAUxD,IAAI,QAAqC,CAAC;AAE1C,kGAAkG;AAClG,MAAM,UAAU,eAAe;IAC7B,IAAI,QAAQ;QAAE,OAAO,QAAQ,CAAC;IAC9B,MAAM,OAAO,GAAG,aAAa,CAAC,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC;IAC/C,MAAM,YAAY,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,gBAAgB,eAAe,CAAC,CAAC;IACzE,MAAM,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,YAAY,EAAE,MAAM,CAAC,CAAwB,CAAC;IAC1F,QAAQ,GAAG;QACT,QAAQ,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC,EAAE,MAAM,EAAE,aAAa,CAAC;QACtE,OAAO;QACP,KAAK,EAAE,GAAG,qBAAqB,GAAG,OAAO,IAAI,aAAa,EAAE;KAC7D,CAAC;IACF,OAAO,QAAQ,CAAC;AAClB,CAAC"}
@@ -7,6 +7,14 @@ import type { Store } from '../store.js';
7
7
  */
8
8
  export declare const PUBLISH_ROUTE_PREFIX = "/publish/";
9
9
  export declare const PREVIEW_ROUTE_PREFIX = "/preview/";
10
+ /**
11
+ * review-the-knowledge-diff (D6): the per-worktree review view. Spelled here
12
+ * beside the preview prefix because it addresses the same worktrees by the
13
+ * same names, and `serve.ts` slices it while `graph diff` reports it.
14
+ */
15
+ export declare const REVIEW_ROUTE_PREFIX = "/review/";
16
+ /** The query parameter carrying the head commit a report was computed for, so the view can tell when the branch moved on. */
17
+ export declare const REVIEW_HEAD_PARAM = "head";
10
18
  /**
11
19
  * `encodeURI`, never `encodeURIComponent`: a page path carries `/` separators
12
20
  * that must survive into the URL. The round trip is exact because `serve.ts`
@@ -65,4 +73,18 @@ export declare function pageServedAt(store: Store, storeRelativeFilePath: string
65
73
  * two addresses for one page would be the same guessing one level down.
66
74
  */
67
75
  export declare function servedAtSentence(served: ServedAt | null): string;
76
+ /** `worktree` is the session worktree's directory name — the key `listSessionWorktreeDirs` returns. */
77
+ export declare function reviewRoute(worktree: string): string;
78
+ /**
79
+ * review-the-knowledge-diff (D6, D7): where the review view of the session
80
+ * worktree `store.root` resolves to answers, carrying the head commit the
81
+ * caller computed its report for. Null outside a session worktree, and when
82
+ * the store declares `serve.previews: none` — that key records that
83
+ * worktree-served addresses do not reach this store's reviewers, and the
84
+ * review route has the same reachability as a preview.
85
+ *
86
+ * Detection and the base-URL join are `pageServedAt`'s own, so the two
87
+ * addresses a pull request body carries can never disagree about either.
88
+ */
89
+ export declare function reviewServedAt(store: Store, headCommit: string): ServedAtRoute | null;
68
90
  //# sourceMappingURL=page-url.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"page-url.d.ts","sourceRoot":"","sources":["../../../src/core/browse/page-url.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAEzC;;;;;GAKG;AACH,eAAO,MAAM,oBAAoB,cAAc,CAAC;AAChD,eAAO,MAAM,oBAAoB,cAAc,CAAC;AAEhD;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAErD;AAED,6FAA6F;AAC7F,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAEvE;AAED,MAAM,WAAW,aAAa;IAC5B,uFAAuF;IACvF,KAAK,EAAE,MAAM,CAAC;IACd,wFAAwF;IACxF,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;CACpB;AAED,MAAM,WAAW,QAAS,SAAQ,aAAa;IAC7C,IAAI,EAAE,SAAS,GAAG,SAAS,CAAC;IAC5B,4FAA4F;IAC5F,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB;;;;OAIG;IACH,aAAa,EAAE,aAAa,GAAG,IAAI,CAAC;CACrC;AAqBD;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,KAAK,EAAE,qBAAqB,EAAE,MAAM,GAAG,QAAQ,GAAG,IAAI,CAqBzF;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,QAAQ,GAAG,IAAI,GAAG,MAAM,CAMhE"}
1
+ {"version":3,"file":"page-url.d.ts","sourceRoot":"","sources":["../../../src/core/browse/page-url.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAEzC;;;;;GAKG;AACH,eAAO,MAAM,oBAAoB,cAAc,CAAC;AAChD,eAAO,MAAM,oBAAoB,cAAc,CAAC;AAChD;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,aAAa,CAAC;AAC9C,6HAA6H;AAC7H,eAAO,MAAM,iBAAiB,SAAS,CAAC;AAExC;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAErD;AAED,6FAA6F;AAC7F,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAEvE;AAED,MAAM,WAAW,aAAa;IAC5B,uFAAuF;IACvF,KAAK,EAAE,MAAM,CAAC;IACd,wFAAwF;IACxF,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;CACpB;AAED,MAAM,WAAW,QAAS,SAAQ,aAAa;IAC7C,IAAI,EAAE,SAAS,GAAG,SAAS,CAAC;IAC5B,4FAA4F;IAC5F,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB;;;;OAIG;IACH,aAAa,EAAE,aAAa,GAAG,IAAI,CAAC;CACrC;AAqBD;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,KAAK,EAAE,qBAAqB,EAAE,MAAM,GAAG,QAAQ,GAAG,IAAI,CAqBzF;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,QAAQ,GAAG,IAAI,GAAG,MAAM,CAMhE;AAED,uGAAuG;AACvG,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAEpD;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,GAAG,aAAa,GAAG,IAAI,CAKrF"}
@@ -8,6 +8,14 @@ import { isSessionWorktreePath } from '../session.js';
8
8
  */
9
9
  export const PUBLISH_ROUTE_PREFIX = '/publish/';
10
10
  export const PREVIEW_ROUTE_PREFIX = '/preview/';
11
+ /**
12
+ * review-the-knowledge-diff (D6): the per-worktree review view. Spelled here
13
+ * beside the preview prefix because it addresses the same worktrees by the
14
+ * same names, and `serve.ts` slices it while `graph diff` reports it.
15
+ */
16
+ export const REVIEW_ROUTE_PREFIX = '/review/';
17
+ /** The query parameter carrying the head commit a report was computed for, so the view can tell when the branch moved on. */
18
+ export const REVIEW_HEAD_PARAM = 'head';
11
19
  /**
12
20
  * `encodeURI`, never `encodeURIComponent`: a page path carries `/` separators
13
21
  * that must survive into the URL. The round trip is exact because `serve.ts`
@@ -98,4 +106,27 @@ export function servedAtSentence(served) {
98
106
  const landed = served.after_landing.url ?? served.after_landing.route;
99
107
  return ` Preview at ${here} (at ${landed} once it lands).`;
100
108
  }
109
+ /** `worktree` is the session worktree's directory name — the key `listSessionWorktreeDirs` returns. */
110
+ export function reviewRoute(worktree) {
111
+ return `${REVIEW_ROUTE_PREFIX}${encodeURIComponent(worktree)}/`;
112
+ }
113
+ /**
114
+ * review-the-knowledge-diff (D6, D7): where the review view of the session
115
+ * worktree `store.root` resolves to answers, carrying the head commit the
116
+ * caller computed its report for. Null outside a session worktree, and when
117
+ * the store declares `serve.previews: none` — that key records that
118
+ * worktree-served addresses do not reach this store's reviewers, and the
119
+ * review route has the same reachability as a preview.
120
+ *
121
+ * Detection and the base-URL join are `pageServedAt`'s own, so the two
122
+ * addresses a pull request body carries can never disagree about either.
123
+ */
124
+ export function reviewServedAt(store, headCommit) {
125
+ if (store.config.serve?.previews === 'none')
126
+ return null;
127
+ if (!isSessionWorktreePath(store.config, store.root))
128
+ return null;
129
+ const route = `${reviewRoute(path.basename(store.root))}?${REVIEW_HEAD_PARAM}=${encodeURIComponent(headCommit)}`;
130
+ return { route, url: joinBaseUrl(store.config.serve?.base_url, route) };
131
+ }
101
132
  //# sourceMappingURL=page-url.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"page-url.js","sourceRoot":"","sources":["../../../src/core/browse/page-url.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"page-url.js","sourceRoot":"","sources":["../../../src/core/browse/page-url.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAC;AAGtD;;;;;GAKG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,WAAW,CAAC;AAChD,MAAM,CAAC,MAAM,oBAAoB,GAAG,WAAW,CAAC;AAChD;;;;GAIG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,UAAU,CAAC;AAC9C,6HAA6H;AAC7H,MAAM,CAAC,MAAM,iBAAiB,GAAG,MAAM,CAAC;AAExC;;;;;GAKG;AACH,MAAM,UAAU,YAAY,CAAC,QAAgB;IAC3C,OAAO,GAAG,oBAAoB,GAAG,SAAS,CAAC,QAAQ,CAAC,EAAE,CAAC;AACzD,CAAC;AAED,6FAA6F;AAC7F,MAAM,UAAU,YAAY,CAAC,QAAgB,EAAE,QAAgB;IAC7D,OAAO,GAAG,oBAAoB,GAAG,SAAS,CAAC,GAAG,QAAQ,IAAI,QAAQ,EAAE,CAAC,EAAE,CAAC;AAC1E,CAAC;AAqBD;;;;;;;;GAQG;AACH,SAAS,WAAW,CAAC,OAA2B,EAAE,KAAa;IAC7D,IAAI,OAAO,KAAK,SAAS;QAAE,OAAO,IAAI,CAAC;IACvC,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,GAAG,KAAK,EAAE,CAAC;AAClD,CAAC;AAED,oFAAoF;AACpF,SAAS,eAAe,CAAC,WAAmB;IAC1C,OAAO,WAAW,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;AACnE,CAAC;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,UAAU,YAAY,CAAC,KAAY,EAAE,qBAA6B;IACtE,MAAM,MAAM,GAAG,eAAe,CAAC,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1D,IAAI,CAAC,qBAAqB,CAAC,UAAU,CAAC,GAAG,MAAM,GAAG,CAAC;QAAE,OAAO,IAAI,CAAC;IAEjE,MAAM,QAAQ,GAAG,qBAAqB,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IAChE,MAAM,OAAO,GAAG,KAAK,CAAC,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC;IAC7C,MAAM,SAAS,GAAG,YAAY,CAAC,QAAQ,CAAC,CAAC;IAEzC,IAAI,CAAC,qBAAqB,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;QACrD,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,EAAE,WAAW,CAAC,OAAO,EAAE,SAAS,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC;IAC1H,CAAC;IAED,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC3C,MAAM,OAAO,GAAG,YAAY,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;IACjD,OAAO;QACL,IAAI,EAAE,SAAS;QACf,KAAK,EAAE,OAAO;QACd,GAAG,EAAE,WAAW,CAAC,OAAO,EAAE,OAAO,CAAC;QAClC,QAAQ;QACR,aAAa,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,EAAE,WAAW,CAAC,OAAO,EAAE,SAAS,CAAC,EAAE;KAC1E,CAAC;AACJ,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,gBAAgB,CAAC,MAAuB;IACtD,IAAI,MAAM,KAAK,IAAI;QAAE,OAAO,EAAE,CAAC;IAC/B,MAAM,IAAI,GAAG,MAAM,CAAC,GAAG,IAAI,MAAM,CAAC,KAAK,CAAC;IACxC,IAAI,MAAM,CAAC,aAAa,KAAK,IAAI;QAAE,OAAO,cAAc,IAAI,GAAG,CAAC;IAChE,MAAM,MAAM,GAAG,MAAM,CAAC,aAAa,CAAC,GAAG,IAAI,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC;IACtE,OAAO,eAAe,IAAI,QAAQ,MAAM,kBAAkB,CAAC;AAC7D,CAAC;AAED,uGAAuG;AACvG,MAAM,UAAU,WAAW,CAAC,QAAgB;IAC1C,OAAO,GAAG,mBAAmB,GAAG,kBAAkB,CAAC,QAAQ,CAAC,GAAG,CAAC;AAClE,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,cAAc,CAAC,KAAY,EAAE,UAAkB;IAC7D,IAAI,KAAK,CAAC,MAAM,CAAC,KAAK,EAAE,QAAQ,KAAK,MAAM;QAAE,OAAO,IAAI,CAAC;IACzD,IAAI,CAAC,qBAAqB,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IAClE,MAAM,KAAK,GAAG,GAAG,WAAW,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,iBAAiB,IAAI,kBAAkB,CAAC,UAAU,CAAC,EAAE,CAAC;IACjH,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,WAAW,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,EAAE,QAAQ,EAAE,KAAK,CAAC,EAAE,CAAC;AAC1E,CAAC"}
@@ -1,5 +1,14 @@
1
1
  import type { LinkResolver } from './link-resolver.js';
2
2
  export declare function escapeHtml(text: string): string;
3
+ /**
4
+ * A rendered body, and whether it holds a diagram block. render-diagrams-in-notes
5
+ * design.md D5: the flag is set by the fence rule as it emits the block, never
6
+ * found by searching the HTML, which a code block quoting the class name would match.
7
+ */
8
+ export interface RenderedBody {
9
+ html: string;
10
+ hasDiagram: boolean;
11
+ }
3
12
  /** Renders a note's markdown body to HTML, with wikilinks resolved via `resolveLink` (design.md D3). */
4
- export declare function renderNoteBody(body: string, resolveLink: LinkResolver): string;
13
+ export declare function renderNoteBody(body: string, resolveLink: LinkResolver): RenderedBody;
5
14
  //# sourceMappingURL=render.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"render.d.ts","sourceRoot":"","sources":["../../../src/core/browse/render.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AA+CvD,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAM/C;AAuBD,wGAAwG;AACxG,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,YAAY,GAAG,MAAM,CAE9E"}
1
+ {"version":3,"file":"render.d.ts","sourceRoot":"","sources":["../../../src/core/browse/render.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AA+CvD,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAM/C;AAoDD;;;;GAIG;AACH,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,OAAO,CAAC;CACrB;AAED,wGAAwG;AACxG,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,YAAY,GAAG,YAAY,CAIpF"}