@coldtea/pr-lens-cli 0.1.1 → 0.1.3

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.
package/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2026 Ohans Emmanuel
3
+ Copyright (c) 2026 Coldtea AI
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
package/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  PR Lens on the command line. It reads a diff with your own model key, checks the result against the contract, and hands you the pull request comment.
4
4
 
5
- MIT © Ohans Emmanuel.
5
+ MIT © Coldtea AI.
6
6
 
7
7
  ```bash
8
8
  npx @coldtea/pr-lens-cli analyze --base origin/main
@@ -10,10 +10,10 @@ npx @coldtea/pr-lens-cli analyze --base origin/main
10
10
 
11
11
  ## Bring your own key
12
12
 
13
- The key is read from the environment, never from a flag: a flag lands in shell history and in the log of whatever CI runs it. The diff goes to the provider you name and nowhere else: there is no PR Lens service in this path.
13
+ Only `analyze` talks to a model; `render`, `comment`, `validate` and `export` never do. Its key is read from the environment, never from a flag: a flag lands in shell history and in the log of whatever CI runs it. The diff goes to the provider you name and nowhere else: there is no PR Lens service in this path.
14
14
 
15
15
  ```bash
16
- export GEMINI_API_KEY=…
16
+ export GEMINI_API_KEY=… # Gemini is the default, not a requirement
17
17
  pr-lens analyze --base origin/main --head HEAD
18
18
  ```
19
19
 
@@ -35,6 +35,14 @@ pr-lens analyze --base origin/main \
35
35
  --api-key-env OLLAMA_KEY
36
36
  ```
37
37
 
38
+ ## Where the files go
39
+
40
+ `analyze` and `render` write to `.pr-lens/` in the current directory, and the first write adds `.pr-lens/` to the repository's `.gitignore` alongside a README saying what the directory holds.
41
+
42
+ None of it is meant to be committed. The SVGs, the document and the manifest are rebuilt from the diff whenever anyone wants them, and a diagram of a pull request that merged months ago is worse than no diagram. What is meant to last is the comment on the pull request, and the map `export` writes.
43
+
44
+ `--out` overrides the location on every command that writes. Point it somewhere else and PR Lens leaves your `.gitignore` alone: that directory is yours to decide about.
45
+
38
46
  ## The commands
39
47
 
40
48
  ### `analyze`
@@ -42,9 +50,11 @@ pr-lens analyze --base origin/main \
42
50
  Diff in, graph document out.
43
51
 
44
52
  ```bash
45
- pr-lens analyze --base origin/main --pr 42 -o pr-lens/graph.json
53
+ pr-lens analyze --base origin/main --pr 42
46
54
  ```
47
55
 
56
+ The document lands in `.pr-lens/graph.json` unless `--out` says otherwise.
57
+
48
58
  The base is the merge base of the two refs, not the tip of the base branch: a diff against the tip would blame this pull request for every change made on the base branch since it forked.
49
59
 
50
60
  The commit shas, the repository, the pull request number and the line counts are filled in from the repository itself, and anything the model writes there is discarded. A fact the model is free to restate is a fact that eventually disagrees with itself.
@@ -54,7 +64,7 @@ The answer is parsed against the contract. If it fails, the validation errors, p
54
64
  ### `render`
55
65
 
56
66
  ```bash
57
- pr-lens render pr-lens/graph.json -o pr-lens/
67
+ pr-lens render .pr-lens/graph.json
58
68
  ```
59
69
 
60
70
  Draws the document as self-contained light and dark SVGs (one pair per drill-down section per lens, or one pair per lens when the document has no sections), and writes two files beside them: `manifest.json`, which says what was drawn and under which file name, and `drawn.graph.json`, the document those pictures actually show.
@@ -66,7 +76,7 @@ The SVGs carry no script and no external reference, and the same document render
66
76
  ### `comment`
67
77
 
68
78
  ```bash
69
- pr-lens comment --graph pr-lens/drawn.graph.json --manifest pr-lens/manifest.json \
79
+ pr-lens comment --graph .pr-lens/drawn.graph.json --manifest .pr-lens/manifest.json \
70
80
  --asset-base-url https://raw.githubusercontent.com/owner/repo/pr-lens/42
71
81
  ```
72
82
 
@@ -75,7 +85,7 @@ Composes the markdown (the `<picture>` pairs that read in both GitHub themes, th
75
85
  ### `validate`
76
86
 
77
87
  ```bash
78
- pr-lens validate pr-lens/graph.json .github/pr-lens.yml
88
+ pr-lens validate .pr-lens/graph.json .github/pr-lens.yml
79
89
  ```
80
90
 
81
91
  Parses graph documents, patch documents, render manifests and configs, JSON or YAML, and reports every problem in each rather than only the first. A file with no `kind` field is read as a config, because a config is the only one of the four a person writes by hand.
@@ -83,7 +93,7 @@ Parses graph documents, patch documents, render manifests and configs, JSON or Y
83
93
  ### `export`
84
94
 
85
95
  ```bash
86
- pr-lens export pr-lens/graph.json -o .github/pr-lens.map.json
96
+ pr-lens export .pr-lens/graph.json -o .github/pr-lens.map.json
87
97
  ```
88
98
 
89
99
  Turns a pull-request document into the map of the system once that pull request has merged: elements the change deletes are dropped, along with the edges and flow steps that hung from them; the rest stops being annotated, and the result is stamped with the single commit it reflects.
@@ -1 +1 @@
1
- {"version":3,"file":"analyze.d.ts","sourceRoot":"","sources":["../../src/commands/analyze.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAO/C,eAAO,MAAM,KAAK,QAsB+D,CAAC;AAyBlF,eAAO,MAAM,cAAc,SACnB,SAAS,MAAM,EAAE,YACb,QAAQ,OACb,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,KACtC,OAAO,CAAC,IAAI,CAyId,CAAC"}
1
+ {"version":3,"file":"analyze.d.ts","sourceRoot":"","sources":["../../src/commands/analyze.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAQ/C,eAAO,MAAM,KAAK,QAsB+D,CAAC;AAyBlF,eAAO,MAAM,cAAc,SACnB,SAAS,MAAM,EAAE,YACb,QAAQ,OACb,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,KACtC,OAAO,CAAC,IAAI,CA2Id,CAAC"}
@@ -1,5 +1,6 @@
1
1
  import { LENSES } from "@coldtea/pr-lens-schema";
2
2
  import { createRequire } from "node:module";
3
+ import { dirname } from "node:path";
3
4
  import { parseOptions, readBoolean, readInt, readList, readString } from "../args.js";
4
5
  import { discoverConfig, loadConfig } from "../config-file.js";
5
6
  import { PrLensCliError, usageError } from "../errors.js";
@@ -9,7 +10,8 @@ import { readTextFile, writeJsonFile } from "../io.js";
9
10
  import { buildExtractionPrompt, SYSTEM_PROMPT } from "../prompt.js";
10
11
  import { completeJson, isProviderId, PROVIDER_IDS, resolveProvider } from "../providers/index.js";
11
12
  import { CLI_VERSION, GENERATOR_NAME } from "../version.js";
12
- const DEFAULT_OUT = "pr-lens/graph.json";
13
+ import { prepareWorkspace, WORKSPACE_DIR } from "../workspace.js";
14
+ const DEFAULT_OUT = `${WORKSPACE_DIR}/graph.json`;
13
15
  const DEFAULT_MAX_OUTPUT_TOKENS = 32_768;
14
16
  const DEFAULT_MAX_DIFF_BYTES = 400_000;
15
17
  export const USAGE = `pr-lens analyze --base <ref> [options]
@@ -152,7 +154,9 @@ export const analyzeCommand = async (args, terminal, env) => {
152
154
  terminal.err(`the document did not validate — asking for a correction`);
153
155
  },
154
156
  }, (request) => completeJson(provider, request));
155
- const written = await writeJsonFile(readString(values.out, "out") ?? DEFAULT_OUT, document);
157
+ const outPath = readString(values.out, "out") ?? DEFAULT_OUT;
158
+ await prepareWorkspace(dirname(outPath), terminal);
159
+ const written = await writeJsonFile(outPath, document);
156
160
  terminal.out(`✓ ${written} — ${document.nodes.length} nodes, ${document.edges.length} edges, ${document.flows.length} flows${attempts > 1 ? ` (${attempts} attempts)` : ""}`);
157
161
  };
158
162
  //# sourceMappingURL=analyze.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"analyze.js","sourceRoot":"","sources":["../../src/commands/analyze.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"analyze.js","sourceRoot":"","sources":["../../src/commands/analyze.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,4 @@
1
1
  import type { Terminal } from "../terminal.js";
2
- export declare const USAGE = "pr-lens render <graph.json> [options]\n\nDraws the document as self-contained SVGs \u2014 one per drill-down section per\nlens, in light and dark \u2014 and writes the manifest describing them. A document\nwith no sections gets one diagram per lens it declares.\n\n -o, --out <dir> where the SVGs and the manifest go (default pr-lens/)\n --theme <theme> light | dark | both (default both)\n --config <file> corrections to draw with (default the repository's, if any)\n --no-config ignore the repository's corrections";
2
+ export declare const USAGE = "pr-lens render <graph.json> [options]\n\nDraws the document as self-contained SVGs \u2014 one per drill-down section per\nlens, in light and dark \u2014 and writes the manifest describing them. A document\nwith no sections gets one diagram per lens it declares.\n\n -o, --out <dir> where the SVGs and the manifest go (default .pr-lens/)\n --theme <theme> light | dark | both (default both)\n --config <file> corrections to draw with (default the repository's, if any)\n --no-config ignore the repository's corrections";
3
3
  export declare const renderCommand: (args: readonly string[], terminal: Terminal) => Promise<void>;
4
4
  //# sourceMappingURL=render.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"render.d.ts","sourceRoot":"","sources":["../../src/commands/render.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAgB/C,eAAO,MAAM,KAAK,qiBASyC,CAAC;AA6B5D,eAAO,MAAM,aAAa,SAAgB,SAAS,MAAM,EAAE,YAAY,QAAQ,KAAG,OAAO,CAAC,IAAI,CA4D7F,CAAC"}
1
+ {"version":3,"file":"render.d.ts","sourceRoot":"","sources":["../../src/commands/render.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAiB/C,eAAO,MAAM,KAAK,siBASyC,CAAC;AA6B5D,eAAO,MAAM,aAAa,SAAgB,SAAS,MAAM,EAAE,YAAY,QAAQ,KAAG,OAAO,CAAC,IAAI,CA8D7F,CAAC"}
@@ -8,7 +8,8 @@ import { readGraphDoc } from "../document.js";
8
8
  import { PrLensCliError, usageError } from "../errors.js";
9
9
  import { repositoryRoot } from "../git.js";
10
10
  import { writeJsonFile, writeTextFile } from "../io.js";
11
- const DEFAULT_OUT = "pr-lens";
11
+ import { prepareWorkspace, WORKSPACE_DIR } from "../workspace.js";
12
+ const DEFAULT_OUT = WORKSPACE_DIR;
12
13
  const MANIFEST = "manifest.json";
13
14
  /**
14
15
  * The document as it was drawn, written beside the manifest.
@@ -94,6 +95,7 @@ export const renderCommand = async (args, terminal) => {
94
95
  throw new PrLensCliError("RENDER_FAILED", `${error.message} [${error.code}]`);
95
96
  }
96
97
  })();
98
+ await prepareWorkspace(out, terminal);
97
99
  for (const drawing of rendered.assets) {
98
100
  const { id, path } = drawing.asset;
99
101
  if (path === undefined)
@@ -1 +1 @@
1
- {"version":3,"file":"render.js","sourceRoot":"","sources":["../../src/commands/render.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"render.js","sourceRoot":"","sources":["../../src/commands/render.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"prompt.d.ts","sourceRoot":"","sources":["../src/prompt.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AACvE,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AAErC,MAAM,MAAM,aAAa,GAAG;IAC1B,IAAI,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IACtC,IAAI,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,GAAG,SAAS,CAAA;KAAE,CAAC;IAC/C,IAAI,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,GAAG,SAAS,CAAA;KAAE,CAAC;IAC/C,IAAI,EAAE,IAAI,CAAC;IACX,MAAM,EAAE,SAAS,IAAI,EAAE,CAAC;CACzB,CAAC;AAEF,eAAO,MAAM,aAAa,QA0Bd,CAAC;AAWb,eAAO,MAAM,qBAAqB,YAAa,aAAa,cAAc,MAAM,KAAG,MAsBrE,CAAC;AAEf,eAAO,MAAM,qBAAqB,WAAY,MAAM,KAAG,MAKzC,CAAC;AAEf,eAAO,MAAM,iBAAiB,UAAW,iBAAiB,KAAG,MAO/C,CAAC"}
1
+ {"version":3,"file":"prompt.d.ts","sourceRoot":"","sources":["../src/prompt.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AACvE,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AAErC,MAAM,MAAM,aAAa,GAAG;IAC1B,IAAI,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IACtC,IAAI,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,GAAG,SAAS,CAAA;KAAE,CAAC;IAC/C,IAAI,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,GAAG,SAAS,CAAA;KAAE,CAAC;IAC/C,IAAI,EAAE,IAAI,CAAC;IACX,MAAM,EAAE,SAAS,IAAI,EAAE,CAAC;CACzB,CAAC;AAEF,eAAO,MAAM,aAAa,QA8Bd,CAAC;AAWb,eAAO,MAAM,qBAAqB,YAAa,aAAa,cAAc,MAAM,KAAG,MAsBrE,CAAC;AAEf,eAAO,MAAM,qBAAqB,WAAY,MAAM,KAAG,MAKzC,CAAC;AAEf,eAAO,MAAM,iBAAiB,UAAW,iBAAiB,KAAG,MAO/C,CAAC"}
package/dist/prompt.js CHANGED
@@ -20,7 +20,11 @@ export const SYSTEM_PROMPT = [
20
20
  "- Give the document a title a reviewer would recognise, and a summary that answers 'what does this change do?' in a short paragraph.",
21
21
  "- Attach file refs to nodes, edges and steps wherever the diff shows where they live: they become the permalinks a reader clicks.",
22
22
  "- Add a data flow only when the change actually has an ordered sequence worth animating. One good flow beats three thin ones.",
23
- "- Build the drill-down tree: a view over the whole document, and a focused view for each part of the change that deserves its own section. Views are what a reader expands in the comment, so a document without them renders as one picture and nothing else.",
23
+ "- Choose architecture views as a C4-inspired decision tree, not a quota. A small change may need only one useful view.",
24
+ "- Start at the highest useful level: use system context when the change affects a user, an external system or a system boundary; otherwise start with containers. Container views cover affected applications, services, jobs, data stores and runtimes. Add a component child only when an affected container's internals matter. Do not add code-level views by default.",
25
+ "- Each architecture child moves down one level and materially narrows the scope. Skip empty, repetitive or speculative levels, and never create views with substantially the same nodes and edges. Infer boundaries from behavior and dependencies, not folder names alone.",
26
+ "- Keep data-flow views as separate roots, outside the architecture hierarchy. Set the highest useful architecture view `defaultOpen: true`; lower architecture views should normally stay collapsed.",
27
+ "- Views are expandable comment sections. Without views, each requested lens renders once.",
24
28
  "- Stat chips carry the numbers that make the change legible, e.g. label 'Postmark calls' value '500x fewer'. Leave out files changed and line counts — those are filled in for you.",
25
29
  "",
26
30
  "Answer with the JSON document alone. No prose, no markdown fence.",
@@ -1 +1 @@
1
- {"version":3,"file":"prompt.js","sourceRoot":"","sources":["../src/prompt.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"prompt.js","sourceRoot":"","sources":["../src/prompt.ts"],"names":[],"mappings":"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"}
package/dist/version.d.ts CHANGED
@@ -1,4 +1,4 @@
1
1
  /** Recorded on every document this CLI produces, as the generator's version. */
2
- export declare const CLI_VERSION = "0.1.1";
2
+ export declare const CLI_VERSION = "0.1.3";
3
3
  export declare const GENERATOR_NAME = "pr-lens-cli";
4
4
  //# sourceMappingURL=version.d.ts.map
package/dist/version.js CHANGED
@@ -1,4 +1,4 @@
1
1
  /** Recorded on every document this CLI produces, as the generator's version. */
2
- export const CLI_VERSION = "0.1.1";
2
+ export const CLI_VERSION = "0.1.3";
3
3
  export const GENERATOR_NAME = "pr-lens-cli";
4
4
  //# sourceMappingURL=version.js.map
@@ -0,0 +1,36 @@
1
+ import type { Terminal } from "./terminal.js";
2
+ /**
3
+ * Where the CLI leaves what it makes, unless someone says otherwise.
4
+ *
5
+ * A dot-directory, and ignored by git from the first write, because none of it
6
+ * is source. The SVGs, the document they were drawn from and the manifest are
7
+ * a preview of the comment, rebuilt from the diff whenever anyone wants it
8
+ * again. A working tree that fills with them leaves the user deciding what to
9
+ * commit, and the answer is always none of it.
10
+ */
11
+ export declare const WORKSPACE_DIR = ".pr-lens";
12
+ /**
13
+ * Adds the workspace to the repository's .gitignore, and says so. Answers with
14
+ * the file it wrote, or nothing when there was nothing to do. Call it once the
15
+ * workspace directory exists, so git can see that it is one.
16
+ *
17
+ * Nothing is written when git already ignores the previews, or when the
18
+ * repository un-ignores this workspace on purpose: a user who chose to track
19
+ * these files has chosen.
20
+ *
21
+ * The entry is normally unanchored, so it holds wherever in the tree the CLI is
22
+ * run. It is narrowed to this one workspace when the repository un-ignores a
23
+ * different one, since an unanchored line lands last and would overrule that
24
+ * choice on its way past.
25
+ */
26
+ export declare const ignoreWorkspace: (workspace: string) => Promise<string | undefined>;
27
+ /**
28
+ * Prepares the workspace on the way to writing in it: the README that says
29
+ * what the directory is, and the .gitignore entry that keeps anyone from
30
+ * having to ask.
31
+ *
32
+ * Both are skipped when --out named somewhere else. That directory is the
33
+ * user's, and so is the question of what to do with it.
34
+ */
35
+ export declare const prepareWorkspace: (out: string, terminal: Terminal) => Promise<void>;
36
+ //# sourceMappingURL=workspace.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workspace.d.ts","sourceRoot":"","sources":["../src/workspace.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAE9C;;;;;;;;GAQG;AACH,eAAO,MAAM,aAAa,aAAa,CAAC;AA+GxC;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,eAAe,cAAqB,MAAM,KAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAenF,CAAC;AAgBF;;;;;;;GAOG;AACH,eAAO,MAAM,gBAAgB,QAAe,MAAM,YAAY,QAAQ,KAAG,OAAO,CAAC,IAAI,CAUpF,CAAC"}
@@ -0,0 +1,158 @@
1
+ import { assertNever } from "@coldtea/pr-lens-schema";
2
+ import { dirname, join, resolve } from "node:path";
3
+ import { git } from "./git.js";
4
+ import { readTextFile, writeTextFile } from "./io.js";
5
+ /**
6
+ * Where the CLI leaves what it makes, unless someone says otherwise.
7
+ *
8
+ * A dot-directory, and ignored by git from the first write, because none of it
9
+ * is source. The SVGs, the document they were drawn from and the manifest are
10
+ * a preview of the comment, rebuilt from the diff whenever anyone wants it
11
+ * again. A working tree that fills with them leaves the user deciding what to
12
+ * commit, and the answer is always none of it.
13
+ */
14
+ export const WORKSPACE_DIR = ".pr-lens";
15
+ const README_NAME = "README.md";
16
+ /**
17
+ * A path written into a .gitignore is read as a pattern, not as a name. A
18
+ * directory called `sub[1]` spells a character class that matches neither
19
+ * bracket; one beginning with `#` turns the line into a comment and one
20
+ * beginning with `!` turns it into another negation. Each leaves the previews
21
+ * visible under an entry that looks like it was written correctly.
22
+ *
23
+ * Trailing spaces want no escape here. git strips them from the end of a
24
+ * pattern, and every pattern this writes ends in a slash.
25
+ */
26
+ const asPattern = (path) => path.replace(/[\\*?[\]]/g, (character) => `\\${character}`).replace(/^([#!])/, "\\$1");
27
+ /** The name a pattern stands for, with the escapes git reads taken back off. */
28
+ const asLiteral = (pattern) => pattern.replace(/\\(.)/g, "$1");
29
+ const ignoreEntry = (path) => `# PR Lens writes its previews here. They are rebuilt on demand.\n${asPattern(path)}/\n`;
30
+ /**
31
+ * Asked of git rather than computed from the two paths, because on macOS the
32
+ * root comes back through /private and the working directory usually does not,
33
+ * and subtracting one from the other then yields a climb out of the repository.
34
+ *
35
+ * Only the record terminator comes off each line. A directory may legitimately
36
+ * begin or end with a space, and trimming one writes a rule for a directory
37
+ * nobody has.
38
+ */
39
+ const locate = async (from) => {
40
+ const [root = "", prefix = ""] = (await git(from, ["rev-parse", "--show-toplevel", "--show-prefix"]))
41
+ .split("\n")
42
+ .map((line) => line.replace(/\r$/, ""));
43
+ return { root, prefix };
44
+ };
45
+ /**
46
+ * Whether git already ignores this workspace. Asked of git rather than worked
47
+ * out from the file, because a pattern that looks right often is not: at the
48
+ * root of a repository `/.pr-lens/` covers the root and nothing below it, and
49
+ * two leading spaces are part of the pattern and so cover nothing at all.
50
+ * Reading the entry back and deciding it means what we would have meant is how
51
+ * a run leaves the previews visible while reporting them handled.
52
+ *
53
+ * The question is about the directory, and nothing standing in for it. A rule
54
+ * covering one file inside — `README.md` is a common one to carry — answers
55
+ * for that file and for nothing beside it, and taking it as settled leaves
56
+ * every SVG and both documents in the working tree.
57
+ *
58
+ * The directory has to exist to be recognised as one, since a pattern ending
59
+ * in a slash matches directories only. It does: the caller writes into it
60
+ * first, for this reason.
61
+ */
62
+ const alreadyIgnored = (root, workspace) => git(root, ["check-ignore", "-q", "--", workspace]).then(() => true, () => false);
63
+ /**
64
+ * The negations a .gitignore makes about a PR Lens workspace.
65
+ *
66
+ * git will not answer this one. When a negation wins, `check-ignore` reports
67
+ * the path as matching nothing at all — the same answer it gives for a path
68
+ * nobody has mentioned — so the file has to be read, and read the way git reads
69
+ * it. `!/.pr-lens/` at the root is a choice about the root's own previews and
70
+ * says nothing about a workspace inside a subdirectory.
71
+ *
72
+ * Only literal names are recognised. A negation written with wildcards is not,
73
+ * and the entry is added despite it — a line in a .gitignore is visible, the
74
+ * CLI names the file it wrote, and the user can take it back.
75
+ */
76
+ const negations = (gitignore) => gitignore.split("\n").flatMap((line) => {
77
+ const pattern = line.trimEnd();
78
+ if (!pattern.startsWith("!"))
79
+ return [];
80
+ const body = asLiteral(pattern.slice(1)).replace(/\/+$/, "");
81
+ if (!body.includes("/"))
82
+ return body === WORKSPACE_DIR ? [{ kind: "anywhere" }] : [];
83
+ const workspace = body.replace(/^\//, "");
84
+ return workspace.endsWith(WORKSPACE_DIR) ? [{ kind: "one", workspace }] : [];
85
+ });
86
+ const spares = (negation, workspace) => {
87
+ switch (negation.kind) {
88
+ case "anywhere":
89
+ return true;
90
+ case "one":
91
+ return negation.workspace === workspace;
92
+ default:
93
+ return assertNever(negation, "Unhandled negation");
94
+ }
95
+ };
96
+ /**
97
+ * Adds the workspace to the repository's .gitignore, and says so. Answers with
98
+ * the file it wrote, or nothing when there was nothing to do. Call it once the
99
+ * workspace directory exists, so git can see that it is one.
100
+ *
101
+ * Nothing is written when git already ignores the previews, or when the
102
+ * repository un-ignores this workspace on purpose: a user who chose to track
103
+ * these files has chosen.
104
+ *
105
+ * The entry is normally unanchored, so it holds wherever in the tree the CLI is
106
+ * run. It is narrowed to this one workspace when the repository un-ignores a
107
+ * different one, since an unanchored line lands last and would overrule that
108
+ * choice on its way past.
109
+ */
110
+ export const ignoreWorkspace = async (workspace) => {
111
+ const location = await locate(dirname(workspace)).catch(() => undefined);
112
+ if (location === undefined)
113
+ return undefined;
114
+ if (await alreadyIgnored(location.root, workspace))
115
+ return undefined;
116
+ const path = join(location.root, ".gitignore");
117
+ const existing = (await readTextFile(path).catch(() => undefined)) ?? "";
118
+ const mine = `${location.prefix}${WORKSPACE_DIR}`;
119
+ const spared = negations(existing);
120
+ if (spared.some((negation) => spares(negation, mine)))
121
+ return undefined;
122
+ const before = existing === "" || existing.endsWith("\n") ? existing : `${existing}\n`;
123
+ const entry = ignoreEntry(spared.length > 0 ? mine : WORKSPACE_DIR);
124
+ return writeTextFile(path, `${before}${before === "" ? "" : "\n"}${entry}`);
125
+ };
126
+ const README = `# .pr-lens
127
+
128
+ PR Lens writes its previews here: the diagrams as light and dark SVGs, the
129
+ document they were drawn from, and the manifest describing them.
130
+
131
+ None of it belongs in a commit. Every file is rebuilt from the diff by
132
+ \`pr-lens analyze\` and \`pr-lens render\`, so a stale copy in the history is
133
+ worth less than nothing — it is a diagram of a pull request somebody already
134
+ merged. What readers are meant to see is the comment on the pull request, or
135
+ the share page it links to.
136
+
137
+ Delete the directory whenever you like. Nothing reads it back.
138
+ `;
139
+ /**
140
+ * Prepares the workspace on the way to writing in it: the README that says
141
+ * what the directory is, and the .gitignore entry that keeps anyone from
142
+ * having to ask.
143
+ *
144
+ * Both are skipped when --out named somewhere else. That directory is the
145
+ * user's, and so is the question of what to do with it.
146
+ */
147
+ export const prepareWorkspace = async (out, terminal) => {
148
+ const directory = resolve(out);
149
+ if (directory !== resolve(WORKSPACE_DIR))
150
+ return;
151
+ // The README first, which is what puts the directory on disk: git is asked
152
+ // whether a directory is ignored, and one that is not there cannot be.
153
+ await writeTextFile(join(directory, README_NAME), README);
154
+ const ignored = await ignoreWorkspace(directory);
155
+ if (ignored !== undefined)
156
+ terminal.err(`✓ ${ignored} — ${WORKSPACE_DIR}/ is ignored`);
157
+ };
158
+ //# sourceMappingURL=workspace.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workspace.js","sourceRoot":"","sources":["../src/workspace.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "name": "@coldtea/pr-lens-cli",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "description": "The PR Lens command line: turn a pull request diff into a schema-valid graph with your own model key, render it, and compose the comment.",
5
5
  "license": "MIT",
6
- "author": "Ohans Emmanuel",
6
+ "author": "Coldtea AI",
7
7
  "repository": {
8
8
  "type": "git",
9
9
  "url": "git+https://github.com/coldteadotai/pr-lens.git",
@@ -40,8 +40,8 @@
40
40
  "dependencies": {
41
41
  "yaml": "^2.8.1",
42
42
  "zod": "^4.4.3",
43
- "@coldtea/pr-lens-schema": "^0.1.1",
44
- "@coldtea/pr-lens-renderer": "^0.1.1"
43
+ "@coldtea/pr-lens-renderer": "^0.1.2",
44
+ "@coldtea/pr-lens-schema": "^0.1.2"
45
45
  },
46
46
  "devDependencies": {
47
47
  "@types/node": "^20.19.0",
@@ -1,5 +1,6 @@
1
1
  import { LENSES, type GraphDocInput, type Lens } from "@coldtea/pr-lens-schema";
2
2
  import { createRequire } from "node:module";
3
+ import { dirname } from "node:path";
3
4
  import { parseOptions, readBoolean, readInt, readList, readString } from "../args.js";
4
5
  import { discoverConfig, loadConfig, type LoadedConfig } from "../config-file.js";
5
6
  import { PrLensCliError, usageError } from "../errors.js";
@@ -10,8 +11,9 @@ import { buildExtractionPrompt, SYSTEM_PROMPT } from "../prompt.js";
10
11
  import { completeJson, isProviderId, PROVIDER_IDS, resolveProvider } from "../providers/index.js";
11
12
  import type { Terminal } from "../terminal.js";
12
13
  import { CLI_VERSION, GENERATOR_NAME } from "../version.js";
14
+ import { prepareWorkspace, WORKSPACE_DIR } from "../workspace.js";
13
15
 
14
- const DEFAULT_OUT = "pr-lens/graph.json";
16
+ const DEFAULT_OUT = `${WORKSPACE_DIR}/graph.json`;
15
17
  const DEFAULT_MAX_OUTPUT_TOKENS = 32_768;
16
18
  const DEFAULT_MAX_DIFF_BYTES = 400_000;
17
19
 
@@ -199,7 +201,9 @@ export const analyzeCommand = async (
199
201
  (request) => completeJson(provider, request),
200
202
  );
201
203
 
202
- const written = await writeJsonFile(readString(values.out, "out") ?? DEFAULT_OUT, document);
204
+ const outPath = readString(values.out, "out") ?? DEFAULT_OUT;
205
+ await prepareWorkspace(dirname(outPath), terminal);
206
+ const written = await writeJsonFile(outPath, document);
203
207
  terminal.out(
204
208
  `✓ ${written} — ${document.nodes.length} nodes, ${document.edges.length} edges, ${document.flows.length} flows${attempts > 1 ? ` (${attempts} attempts)` : ""}`,
205
209
  );
@@ -9,8 +9,9 @@ import { PrLensCliError, usageError } from "../errors.js";
9
9
  import { repositoryRoot } from "../git.js";
10
10
  import { writeJsonFile, writeTextFile } from "../io.js";
11
11
  import type { Terminal } from "../terminal.js";
12
+ import { prepareWorkspace, WORKSPACE_DIR } from "../workspace.js";
12
13
 
13
- const DEFAULT_OUT = "pr-lens";
14
+ const DEFAULT_OUT = WORKSPACE_DIR;
14
15
  const MANIFEST = "manifest.json";
15
16
 
16
17
  /**
@@ -109,6 +110,8 @@ export const renderCommand = async (args: readonly string[], terminal: Terminal)
109
110
  }
110
111
  })();
111
112
 
113
+ await prepareWorkspace(out, terminal);
114
+
112
115
  for (const drawing of rendered.assets) {
113
116
  const { id, path } = drawing.asset;
114
117
  if (path === undefined)
package/src/prompt.ts CHANGED
@@ -31,7 +31,11 @@ export const SYSTEM_PROMPT = [
31
31
  "- Give the document a title a reviewer would recognise, and a summary that answers 'what does this change do?' in a short paragraph.",
32
32
  "- Attach file refs to nodes, edges and steps wherever the diff shows where they live: they become the permalinks a reader clicks.",
33
33
  "- Add a data flow only when the change actually has an ordered sequence worth animating. One good flow beats three thin ones.",
34
- "- Build the drill-down tree: a view over the whole document, and a focused view for each part of the change that deserves its own section. Views are what a reader expands in the comment, so a document without them renders as one picture and nothing else.",
34
+ "- Choose architecture views as a C4-inspired decision tree, not a quota. A small change may need only one useful view.",
35
+ "- Start at the highest useful level: use system context when the change affects a user, an external system or a system boundary; otherwise start with containers. Container views cover affected applications, services, jobs, data stores and runtimes. Add a component child only when an affected container's internals matter. Do not add code-level views by default.",
36
+ "- Each architecture child moves down one level and materially narrows the scope. Skip empty, repetitive or speculative levels, and never create views with substantially the same nodes and edges. Infer boundaries from behavior and dependencies, not folder names alone.",
37
+ "- Keep data-flow views as separate roots, outside the architecture hierarchy. Set the highest useful architecture view `defaultOpen: true`; lower architecture views should normally stay collapsed.",
38
+ "- Views are expandable comment sections. Without views, each requested lens renders once.",
35
39
  "- Stat chips carry the numbers that make the change legible, e.g. label 'Postmark calls' value '500x fewer'. Leave out files changed and line counts — those are filled in for you.",
36
40
  "",
37
41
  "Answer with the JSON document alone. No prose, no markdown fence.",
package/src/version.ts CHANGED
@@ -1,4 +1,4 @@
1
1
  /** Recorded on every document this CLI produces, as the generator's version. */
2
- export const CLI_VERSION = "0.1.1";
2
+ export const CLI_VERSION = "0.1.3";
3
3
 
4
4
  export const GENERATOR_NAME = "pr-lens-cli";
@@ -0,0 +1,190 @@
1
+ import { assertNever } from "@coldtea/pr-lens-schema";
2
+ import { dirname, join, resolve } from "node:path";
3
+ import { git } from "./git.js";
4
+ import { readTextFile, writeTextFile } from "./io.js";
5
+ import type { Terminal } from "./terminal.js";
6
+
7
+ /**
8
+ * Where the CLI leaves what it makes, unless someone says otherwise.
9
+ *
10
+ * A dot-directory, and ignored by git from the first write, because none of it
11
+ * is source. The SVGs, the document they were drawn from and the manifest are
12
+ * a preview of the comment, rebuilt from the diff whenever anyone wants it
13
+ * again. A working tree that fills with them leaves the user deciding what to
14
+ * commit, and the answer is always none of it.
15
+ */
16
+ export const WORKSPACE_DIR = ".pr-lens";
17
+
18
+ const README_NAME = "README.md";
19
+
20
+ /**
21
+ * A path written into a .gitignore is read as a pattern, not as a name. A
22
+ * directory called `sub[1]` spells a character class that matches neither
23
+ * bracket; one beginning with `#` turns the line into a comment and one
24
+ * beginning with `!` turns it into another negation. Each leaves the previews
25
+ * visible under an entry that looks like it was written correctly.
26
+ *
27
+ * Trailing spaces want no escape here. git strips them from the end of a
28
+ * pattern, and every pattern this writes ends in a slash.
29
+ */
30
+ const asPattern = (path: string): string =>
31
+ path.replace(/[\\*?[\]]/g, (character) => `\\${character}`).replace(/^([#!])/, "\\$1");
32
+
33
+ /** The name a pattern stands for, with the escapes git reads taken back off. */
34
+ const asLiteral = (pattern: string): string => pattern.replace(/\\(.)/g, "$1");
35
+
36
+ const ignoreEntry = (path: string): string =>
37
+ `# PR Lens writes its previews here. They are rebuilt on demand.\n${asPattern(path)}/\n`;
38
+
39
+ /** Where a directory sits in its repository: the root, and its path below it. */
40
+ type Location = { root: string; prefix: string };
41
+
42
+ /**
43
+ * Asked of git rather than computed from the two paths, because on macOS the
44
+ * root comes back through /private and the working directory usually does not,
45
+ * and subtracting one from the other then yields a climb out of the repository.
46
+ *
47
+ * Only the record terminator comes off each line. A directory may legitimately
48
+ * begin or end with a space, and trimming one writes a rule for a directory
49
+ * nobody has.
50
+ */
51
+ const locate = async (from: string): Promise<Location> => {
52
+ const [root = "", prefix = ""] = (
53
+ await git(from, ["rev-parse", "--show-toplevel", "--show-prefix"])
54
+ )
55
+ .split("\n")
56
+ .map((line) => line.replace(/\r$/, ""));
57
+
58
+ return { root, prefix };
59
+ };
60
+
61
+ /**
62
+ * Whether git already ignores this workspace. Asked of git rather than worked
63
+ * out from the file, because a pattern that looks right often is not: at the
64
+ * root of a repository `/.pr-lens/` covers the root and nothing below it, and
65
+ * two leading spaces are part of the pattern and so cover nothing at all.
66
+ * Reading the entry back and deciding it means what we would have meant is how
67
+ * a run leaves the previews visible while reporting them handled.
68
+ *
69
+ * The question is about the directory, and nothing standing in for it. A rule
70
+ * covering one file inside — `README.md` is a common one to carry — answers
71
+ * for that file and for nothing beside it, and taking it as settled leaves
72
+ * every SVG and both documents in the working tree.
73
+ *
74
+ * The directory has to exist to be recognised as one, since a pattern ending
75
+ * in a slash matches directories only. It does: the caller writes into it
76
+ * first, for this reason.
77
+ */
78
+ const alreadyIgnored = (root: string, workspace: string): Promise<boolean> =>
79
+ git(root, ["check-ignore", "-q", "--", workspace]).then(
80
+ () => true,
81
+ () => false,
82
+ );
83
+
84
+ /**
85
+ * A line that un-ignores a workspace, and how far its choice reaches: a bare
86
+ * name holds at any depth, while a pattern carrying a slash anywhere but its
87
+ * end is anchored to the root and speaks for one directory only.
88
+ */
89
+ type Negation = { kind: "anywhere" } | { kind: "one"; workspace: string };
90
+
91
+ /**
92
+ * The negations a .gitignore makes about a PR Lens workspace.
93
+ *
94
+ * git will not answer this one. When a negation wins, `check-ignore` reports
95
+ * the path as matching nothing at all — the same answer it gives for a path
96
+ * nobody has mentioned — so the file has to be read, and read the way git reads
97
+ * it. `!/.pr-lens/` at the root is a choice about the root's own previews and
98
+ * says nothing about a workspace inside a subdirectory.
99
+ *
100
+ * Only literal names are recognised. A negation written with wildcards is not,
101
+ * and the entry is added despite it — a line in a .gitignore is visible, the
102
+ * CLI names the file it wrote, and the user can take it back.
103
+ */
104
+ const negations = (gitignore: string): Negation[] =>
105
+ gitignore.split("\n").flatMap((line): Negation[] => {
106
+ const pattern = line.trimEnd();
107
+ if (!pattern.startsWith("!")) return [];
108
+
109
+ const body = asLiteral(pattern.slice(1)).replace(/\/+$/, "");
110
+ if (!body.includes("/")) return body === WORKSPACE_DIR ? [{ kind: "anywhere" }] : [];
111
+
112
+ const workspace = body.replace(/^\//, "");
113
+ return workspace.endsWith(WORKSPACE_DIR) ? [{ kind: "one", workspace }] : [];
114
+ });
115
+
116
+ const spares = (negation: Negation, workspace: string): boolean => {
117
+ switch (negation.kind) {
118
+ case "anywhere":
119
+ return true;
120
+ case "one":
121
+ return negation.workspace === workspace;
122
+ default:
123
+ return assertNever(negation, "Unhandled negation");
124
+ }
125
+ };
126
+
127
+ /**
128
+ * Adds the workspace to the repository's .gitignore, and says so. Answers with
129
+ * the file it wrote, or nothing when there was nothing to do. Call it once the
130
+ * workspace directory exists, so git can see that it is one.
131
+ *
132
+ * Nothing is written when git already ignores the previews, or when the
133
+ * repository un-ignores this workspace on purpose: a user who chose to track
134
+ * these files has chosen.
135
+ *
136
+ * The entry is normally unanchored, so it holds wherever in the tree the CLI is
137
+ * run. It is narrowed to this one workspace when the repository un-ignores a
138
+ * different one, since an unanchored line lands last and would overrule that
139
+ * choice on its way past.
140
+ */
141
+ export const ignoreWorkspace = async (workspace: string): Promise<string | undefined> => {
142
+ const location = await locate(dirname(workspace)).catch(() => undefined);
143
+ if (location === undefined) return undefined;
144
+ if (await alreadyIgnored(location.root, workspace)) return undefined;
145
+
146
+ const path = join(location.root, ".gitignore");
147
+ const existing = (await readTextFile(path).catch(() => undefined)) ?? "";
148
+
149
+ const mine = `${location.prefix}${WORKSPACE_DIR}`;
150
+ const spared = negations(existing);
151
+ if (spared.some((negation) => spares(negation, mine))) return undefined;
152
+
153
+ const before = existing === "" || existing.endsWith("\n") ? existing : `${existing}\n`;
154
+ const entry = ignoreEntry(spared.length > 0 ? mine : WORKSPACE_DIR);
155
+ return writeTextFile(path, `${before}${before === "" ? "" : "\n"}${entry}`);
156
+ };
157
+
158
+ const README = `# .pr-lens
159
+
160
+ PR Lens writes its previews here: the diagrams as light and dark SVGs, the
161
+ document they were drawn from, and the manifest describing them.
162
+
163
+ None of it belongs in a commit. Every file is rebuilt from the diff by
164
+ \`pr-lens analyze\` and \`pr-lens render\`, so a stale copy in the history is
165
+ worth less than nothing — it is a diagram of a pull request somebody already
166
+ merged. What readers are meant to see is the comment on the pull request, or
167
+ the share page it links to.
168
+
169
+ Delete the directory whenever you like. Nothing reads it back.
170
+ `;
171
+
172
+ /**
173
+ * Prepares the workspace on the way to writing in it: the README that says
174
+ * what the directory is, and the .gitignore entry that keeps anyone from
175
+ * having to ask.
176
+ *
177
+ * Both are skipped when --out named somewhere else. That directory is the
178
+ * user's, and so is the question of what to do with it.
179
+ */
180
+ export const prepareWorkspace = async (out: string, terminal: Terminal): Promise<void> => {
181
+ const directory = resolve(out);
182
+ if (directory !== resolve(WORKSPACE_DIR)) return;
183
+
184
+ // The README first, which is what puts the directory on disk: git is asked
185
+ // whether a directory is ignored, and one that is not there cannot be.
186
+ await writeTextFile(join(directory, README_NAME), README);
187
+
188
+ const ignored = await ignoreWorkspace(directory);
189
+ if (ignored !== undefined) terminal.err(`✓ ${ignored} — ${WORKSPACE_DIR}/ is ignored`);
190
+ };