@illuminis/comprism 0.1.0 → 0.1.2

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.
@@ -0,0 +1,30 @@
1
+ export interface Requirement {
2
+ /** What it is for, said as the work it makes possible. */
3
+ purpose: string;
4
+ /** Any one of these being present is enough. */
5
+ anyOf: string[];
6
+ /** Work that cannot be done without it, for the message. */
7
+ without: string;
8
+ /** True when the tool cannot function at all without this. */
9
+ essential: boolean;
10
+ }
11
+ export declare const REQUIREMENTS: Requirement[];
12
+ /** Is this program on the machine, by name, without running anything of theirs. */
13
+ export declare function present(program: string): boolean;
14
+ /**
15
+ * The one command that installs what is missing, for the machine it is on.
16
+ *
17
+ * Named per platform rather than guessed: telling somebody on Ubuntu to run a
18
+ * Homebrew command is worse than saying nothing, because they now have to work
19
+ * out that the instruction was wrong before they can work out what is right.
20
+ */
21
+ export declare function howToInstall(missing: string[]): string;
22
+ export interface Readiness {
23
+ ready: boolean;
24
+ /** One line per requirement, ready to print. */
25
+ lines: string[];
26
+ /** The command to run, empty when nothing is missing. */
27
+ fix: string;
28
+ }
29
+ /** What this machine can and cannot do, and how to close the gap. */
30
+ export declare function check(): Readiness;
@@ -0,0 +1,107 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.REQUIREMENTS = void 0;
7
+ exports.present = present;
8
+ exports.howToInstall = howToInstall;
9
+ exports.check = check;
10
+ /**
11
+ * What this machine needs before the work can be done on it, and what to type
12
+ * when something is missing.
13
+ *
14
+ * ── Why this is short, and why that is the right answer ───────────────────
15
+ *
16
+ * Almost everything people expect to need here is not needed at all, because it
17
+ * happens on our servers. A Word document, a slide deck and a PDF are BUILT
18
+ * there and arrive as bytes; the tool only writes them to disk. Nothing on a
19
+ * customer's machine has to know what a .docx is.
20
+ *
21
+ * What genuinely has to be local is the work that touches their own files:
22
+ *
23
+ * - `git`, so a repository can be read, branched and committed.
24
+ * - A PDF reader, so a specification they already have can be read back.
25
+ *
26
+ * That is the whole list, and it stays that way deliberately. Every program
27
+ * added here is one more thing that can be absent, the wrong version, or
28
+ * refused by somebody's security team.
29
+ *
30
+ * ── Why the install does not simply install them ──────────────────────────
31
+ *
32
+ * It would have to install system software, unasked, from a package manager, as
33
+ * a side effect of `npm install`. Any security team that found that would ban
34
+ * the product, and rightly: a tool that quietly runs a system installer on a
35
+ * laptop is indistinguishable from one that does something worse. So this
36
+ * reports and gives the exact command, and the person runs it. One line to copy
37
+ * is not friction worth trading a customer's trust for.
38
+ */
39
+ const node_child_process_1 = require("node:child_process");
40
+ const node_os_1 = __importDefault(require("node:os"));
41
+ exports.REQUIREMENTS = [
42
+ {
43
+ purpose: 'working with a repository',
44
+ anyOf: ['git'],
45
+ without: 'reading, branching and committing a project',
46
+ essential: false,
47
+ },
48
+ {
49
+ purpose: 'reading a PDF you already have',
50
+ // Three ways to do the same job. The first keeps the layout, the second is
51
+ // close, the third is usually there on any machine with Python at all.
52
+ anyOf: ['pdftotext', 'mutool', 'python3'],
53
+ without: 'reading a specification or a contract that arrived as a PDF',
54
+ essential: false,
55
+ },
56
+ ];
57
+ /** Is this program on the machine, by name, without running anything of theirs. */
58
+ function present(program) {
59
+ try {
60
+ (0, node_child_process_1.execFileSync)('/usr/bin/env', ['which', program], { stdio: 'ignore' });
61
+ return true;
62
+ }
63
+ catch {
64
+ return false;
65
+ }
66
+ }
67
+ /**
68
+ * The one command that installs what is missing, for the machine it is on.
69
+ *
70
+ * Named per platform rather than guessed: telling somebody on Ubuntu to run a
71
+ * Homebrew command is worse than saying nothing, because they now have to work
72
+ * out that the instruction was wrong before they can work out what is right.
73
+ */
74
+ function howToInstall(missing) {
75
+ if (missing.length === 0)
76
+ return '';
77
+ const platform = node_os_1.default.platform();
78
+ const parts = missing.map((m) => (m === 'pdftotext' ? 'poppler' : m));
79
+ if (platform === 'darwin')
80
+ return `brew install ${parts.join(' ')}`;
81
+ if (platform === 'linux') {
82
+ const apt = missing.map((m) => (m === 'pdftotext' ? 'poppler-utils' : m));
83
+ return `sudo apt-get install -y ${apt.join(' ')}`;
84
+ }
85
+ if (platform === 'win32')
86
+ return `winget install ${parts.join(' ')}`;
87
+ return `install: ${parts.join(', ')}`;
88
+ }
89
+ /** What this machine can and cannot do, and how to close the gap. */
90
+ function check() {
91
+ const lines = [];
92
+ const missing = [];
93
+ for (const req of exports.REQUIREMENTS) {
94
+ const found = req.anyOf.find(present);
95
+ if (found) {
96
+ lines.push(` ready ${req.purpose}`);
97
+ }
98
+ else {
99
+ // The FIRST of the alternatives is the one named, because a list of three
100
+ // equivalent programs is a decision nobody wants to make about a thing
101
+ // they did not know they needed.
102
+ missing.push(req.anyOf[0]);
103
+ lines.push(` missing ${req.purpose}, so ${req.without} will not work`);
104
+ }
105
+ }
106
+ return { ready: missing.length === 0, lines, fix: howToInstall(missing) };
107
+ }
@@ -6,8 +6,7 @@
6
6
  * behavior behind them changes, never on a whim, because consumers select by
7
7
  * version and old records keep meaning what they meant.
8
8
  */
9
- /** The package version. Stamped on every row the Companion writes. */
10
- export declare const COMPRISM_VERSION = "0.1.0";
9
+ export declare const COMPRISM_VERSION: string;
11
10
  /** The structural classifier. Bump when a signal is added, removed or retuned. */
12
11
  export declare const CLASSIFIER_VERSION = "structural-v1";
13
12
  /**
@@ -9,8 +9,27 @@
9
9
  */
10
10
  Object.defineProperty(exports, "__esModule", { value: true });
11
11
  exports.ESTIMATOR_VERSION = exports.POLICY_VERSION = exports.CLASSIFIER_VERSION = exports.COMPRISM_VERSION = void 0;
12
- /** The package version. Stamped on every row the Companion writes. */
13
- exports.COMPRISM_VERSION = '0.1.0';
12
+ /**
13
+ * The package version. Stamped on every row the Companion writes.
14
+ *
15
+ * Read from the package's own manifest rather than typed here. It was typed
16
+ * here once, and a published 0.1.1 went on reporting itself as 0.1.0 to every
17
+ * customer and onto every record it wrote, which is the one number a version
18
+ * stamp exists to get right. A literal drifts the moment `npm version` runs;
19
+ * the manifest cannot.
20
+ */
21
+ function packageVersion() {
22
+ try {
23
+ // Two levels up from out/lib, which is where the manifest sits in both the
24
+ // built package and a checkout.
25
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
26
+ return String(require('../../package.json').version || '0.0.0');
27
+ }
28
+ catch {
29
+ return '0.0.0';
30
+ }
31
+ }
32
+ exports.COMPRISM_VERSION = packageVersion();
14
33
  /** The structural classifier. Bump when a signal is added, removed or retuned. */
15
34
  exports.CLASSIFIER_VERSION = 'structural-v1';
16
35
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@illuminis/comprism",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "CompletionPrism Companion. Records what finishing a piece of work actually costs - every attempt, and the human time spent noticing and repairing the ones that failed.",
5
5
  "license": "UNLICENSED",
6
6
  "private": false,
@@ -24,6 +24,8 @@
24
24
  "out/lib/gateway.d.ts",
25
25
  "out/lib/prompt.js",
26
26
  "out/lib/prompt.d.ts",
27
+ "out/lib/readiness.js",
28
+ "out/lib/readiness.d.ts",
27
29
  "out/lib/types.js",
28
30
  "out/lib/types.d.ts",
29
31
  "out/lib/ui.js",