@xhulz/nina 0.39.0 → 0.40.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.
- package/package.json +1 -1
- package/releases/0.40.0/core/GAPS.md +125 -0
- package/releases/0.40.0/core/answered.json +32 -0
- package/releases/0.40.0/core/defaults/tree/.claude/agents/architect.md +1 -0
- package/releases/0.40.0/core/defaults/tree/.claude/agents/dba.md +3 -0
- package/releases/0.40.0/core/defaults/tree/.claude/agents/devops.md +1 -0
- package/releases/0.40.0/core/defaults/tree/.claude/agents/implementer.md +1 -0
- package/releases/0.40.0/core/defaults/tree/.claude/agents/integration-tester.md +3 -0
- package/releases/0.40.0/core/defaults/tree/.claude/agents/qa.md +2 -0
- package/releases/0.40.0/core/defaults/tree/.claude/agents/reviewer.md +3 -0
- package/releases/0.40.0/core/defaults/tree/.claude/agents/secops.md +3 -0
- package/releases/0.40.0/core/defaults/tree/.claude/agents/solidity-auditor.md +3 -0
- package/releases/0.40.0/core/defaults/tree/.claude/agents/solidity-dev.md +3 -0
- package/releases/0.40.0/core/tree/.claude/agents/architect.md +127 -0
- package/releases/0.40.0/core/tree/.claude/agents/dba.md +110 -0
- package/releases/0.40.0/core/tree/.claude/agents/devops.md +114 -0
- package/releases/0.40.0/core/tree/.claude/agents/implementer.md +156 -0
- package/releases/0.40.0/core/tree/.claude/agents/integration-tester.md +168 -0
- package/releases/0.40.0/core/tree/.claude/agents/planner.md +132 -0
- package/releases/0.40.0/core/tree/.claude/agents/qa.md +152 -0
- package/releases/0.40.0/core/tree/.claude/agents/reviewer.md +183 -0
- package/releases/0.40.0/core/tree/.claude/agents/secops.md +121 -0
- package/releases/0.40.0/core/tree/.claude/agents/solidity-auditor.md +126 -0
- package/releases/0.40.0/core/tree/.claude/agents/solidity-dev.md +123 -0
- package/releases/0.40.0/core/tree/.claude/agents-overview.md +64 -0
- package/releases/0.40.0/core/tree/.claude/frontend.md +10 -0
- package/releases/0.40.0/core/tree/.claude/graph.md +75 -0
- package/releases/0.40.0/core/tree/.claude/patterns.md +213 -0
- package/releases/0.40.0/core/tree/.claude/pills/README.md +147 -0
- package/releases/0.40.0/core/tree/.claude/pipeline.md +101 -0
- package/releases/0.40.0/core/tree/.claude/retrieval.md +103 -0
- package/releases/0.40.0/core/tree/.claude/router.md +198 -0
- package/releases/0.40.0/core/tree/.claude/templates/integration.md +45 -0
- package/releases/0.40.0/core/tree/CLAUDE.md +163 -0
- package/releases/0.40.0/core/tree/scripts/cost-watch.mjs +25 -0
- package/releases/0.40.0/core/tree/scripts/edit-guard.mjs +24 -0
- package/releases/0.40.0/core/tree/scripts/harness-check.mjs +71 -0
- package/releases/0.40.0/core/tree/scripts/loop-gate.mjs +19 -0
- package/releases/0.40.0/core/vocabulary.json +13 -0
- package/releases/0.40.0/surfaces/blockchain/tree/.claude/agents/architect.md +5 -0
- package/releases/0.40.0/surfaces/blockchain/tree/.claude/agents/devops.md +5 -0
- package/releases/0.40.0/surfaces/blockchain/tree/.claude/agents/reviewer.md +5 -0
- package/releases/0.40.0/surfaces/blockchain/tree/.claude/agents/solidity-auditor.md +18 -0
- package/releases/0.40.0/surfaces/blockchain/tree/.claude/agents/solidity-dev.md +16 -0
- package/releases/0.40.0/surfaces/blockchain/tree/.claude/agents-overview.md +6 -0
- package/releases/0.40.0/surfaces/blockchain/tree/.claude/graph.md +11 -0
- package/releases/0.40.0/surfaces/blockchain/tree/.claude/router.md +6 -0
- package/releases/0.40.0/surfaces/blockchain/tree/CLAUDE.md +12 -0
- package/releases/0.40.0/surfaces/db/tree/.claude/agents/architect.md +5 -0
- package/releases/0.40.0/surfaces/db/tree/.claude/agents/dba.md +50 -0
- package/releases/0.40.0/surfaces/db/tree/.claude/agents/devops.md +5 -0
- package/releases/0.40.0/surfaces/db/tree/.claude/agents/implementer.md +2 -0
- package/releases/0.40.0/surfaces/db/tree/.claude/agents/integration-tester.md +10 -0
- package/releases/0.40.0/surfaces/db/tree/.claude/agents/planner.md +2 -0
- package/releases/0.40.0/surfaces/db/tree/.claude/agents/reviewer.md +22 -0
- package/releases/0.40.0/surfaces/db/tree/.claude/agents/secops.md +2 -0
- package/releases/0.40.0/surfaces/db/tree/.claude/agents-overview.md +5 -0
- package/releases/0.40.0/surfaces/db/tree/.claude/graph.md +8 -0
- package/releases/0.40.0/surfaces/db/tree/.claude/patterns.md +19 -0
- package/releases/0.40.0/surfaces/db/tree/.claude/pipeline.md +13 -0
- package/releases/0.40.0/surfaces/db/tree/.claude/retrieval.md +5 -0
- package/releases/0.40.0/surfaces/db/tree/.claude/router.md +4 -0
- package/releases/0.40.0/surfaces/db/tree/CLAUDE.md +17 -0
- package/releases/0.40.0/surfaces/edge-cf/tree/.claude/agents/architect.md +14 -0
- package/releases/0.40.0/surfaces/edge-cf/tree/.claude/agents/dba.md +2 -0
- package/releases/0.40.0/surfaces/edge-cf/tree/.claude/agents/devops.md +32 -0
- package/releases/0.40.0/surfaces/edge-cf/tree/.claude/agents/implementer.md +14 -0
- package/releases/0.40.0/surfaces/edge-cf/tree/.claude/agents/integration-tester.md +11 -0
- package/releases/0.40.0/surfaces/edge-cf/tree/.claude/agents/qa.md +3 -0
- package/releases/0.40.0/surfaces/edge-cf/tree/.claude/agents/reviewer.md +8 -0
- package/releases/0.40.0/surfaces/edge-cf/tree/.claude/agents/secops.md +8 -0
- package/releases/0.40.0/surfaces/edge-cf/tree/.claude/patterns.md +17 -0
- package/releases/0.40.0/surfaces/edge-cf/tree/.claude/retrieval.md +8 -0
- package/releases/0.40.0/surfaces/edge-cf/tree/CLAUDE.md +27 -0
- package/releases/0.40.0/surfaces/frontend/tree/.claude/agents/architect.md +20 -0
- package/releases/0.40.0/surfaces/frontend/tree/.claude/agents/devops.md +28 -0
- package/releases/0.40.0/surfaces/frontend/tree/.claude/agents/implementer.md +25 -0
- package/releases/0.40.0/surfaces/frontend/tree/.claude/agents/qa.md +17 -0
- package/releases/0.40.0/surfaces/frontend/tree/.claude/agents/reviewer.md +56 -0
- package/releases/0.40.0/surfaces/frontend/tree/.claude/patterns.md +8 -0
- package/releases/0.40.0/surfaces/frontend/tree/.claude/retrieval.md +2 -0
- package/releases/0.40.0/surfaces/frontend/tree/.claude/router.md +14 -0
- package/releases/0.40.0/surfaces/frontend/tree/CLAUDE.md +5 -0
- package/releases/0.40.0/surfaces/integrations/tree/.claude/agents/architect.md +16 -0
- package/releases/0.40.0/surfaces/integrations/tree/.claude/agents/implementer.md +12 -0
- package/releases/0.40.0/surfaces/integrations/tree/.claude/agents/integration-tester.md +20 -0
- package/releases/0.40.0/surfaces/integrations/tree/.claude/agents/planner.md +2 -0
- package/releases/0.40.0/surfaces/integrations/tree/.claude/agents/reviewer.md +21 -0
- package/releases/0.40.0/surfaces/integrations/tree/.claude/agents/secops.md +2 -0
- package/releases/0.40.0/surfaces/integrations/tree/.claude/agents-overview.md +8 -0
- package/releases/0.40.0/surfaces/integrations/tree/.claude/graph.md +10 -0
- package/releases/0.40.0/surfaces/integrations/tree/.claude/patterns.md +38 -0
- package/releases/0.40.0/surfaces/integrations/tree/.claude/pipeline.md +16 -0
- package/releases/0.40.0/surfaces/integrations/tree/.claude/retrieval.md +16 -0
- package/releases/0.40.0/surfaces/integrations/tree/.claude/router.md +6 -0
- package/releases/0.40.0/surfaces/integrations/tree/CLAUDE.md +17 -0
- package/releases/0.40.0/surfaces/money/tree/.claude/agents/architect.md +12 -0
- package/releases/0.40.0/surfaces/money/tree/.claude/agents/dba.md +14 -0
- package/releases/0.40.0/surfaces/money/tree/.claude/agents/implementer.md +11 -0
- package/releases/0.40.0/surfaces/money/tree/.claude/agents/integration-tester.md +3 -0
- package/releases/0.40.0/surfaces/money/tree/.claude/agents/reviewer.md +23 -0
- package/releases/0.40.0/surfaces/money/tree/.claude/agents/secops.md +5 -0
- package/releases/0.40.0/surfaces/money/tree/.claude/agents/solidity-auditor.md +4 -0
- package/releases/0.40.0/surfaces/money/tree/.claude/agents/solidity-dev.md +4 -0
- package/releases/0.40.0/surfaces/money/tree/.claude/graph.md +2 -0
- package/releases/0.40.0/surfaces/money/tree/.claude/patterns.md +49 -0
- package/releases/0.40.0/surfaces/money/tree/.claude/pipeline.md +2 -0
- package/releases/0.40.0/surfaces/money/tree/.claude/retrieval.md +2 -0
- package/releases/0.40.0/surfaces/money/tree/CLAUDE.md +11 -0
- package/releases/0.40.0/surfaces/pii/tree/.claude/agents/dba.md +2 -0
- package/releases/0.40.0/surfaces/pii/tree/.claude/agents/devops.md +8 -0
- package/releases/0.40.0/surfaces/pii/tree/.claude/agents/reviewer.md +8 -0
- package/releases/0.40.0/surfaces/pii/tree/.claude/agents/secops.md +2 -0
- package/releases/0.40.0/surfaces/pii/tree/.claude/agents/solidity-auditor.md +5 -0
- package/releases/0.40.0/surfaces/pii/tree/CLAUDE.md +5 -0
- package/releases/0.40.0/surfaces/prisma/tree/.claude/agents/architect.md +2 -0
- package/releases/0.40.0/surfaces/prisma/tree/.claude/agents/dba.md +39 -0
- package/releases/0.40.0/surfaces/prisma/tree/.claude/agents/devops.md +11 -0
- package/releases/0.40.0/surfaces/prisma/tree/.claude/agents/implementer.md +2 -0
- package/releases/0.40.0/surfaces/prisma/tree/.claude/agents/integration-tester.md +2 -0
- package/releases/0.40.0/surfaces/prisma/tree/.claude/agents/reviewer.md +2 -0
- package/releases/0.40.0/surfaces/prisma/tree/.claude/patterns.md +15 -0
- package/releases/0.40.0/surfaces/prisma/tree/CLAUDE.md +5 -0
- package/src/commands/check.mjs +15 -28
- package/src/commands/compose.mjs +43 -61
- package/src/commands/eval.mjs +1 -1
- package/src/commands/export.mjs +4 -34
- package/src/commands/gate.mjs +4 -11
- package/src/commands/init.mjs +21 -29
- package/src/commands/langfuse.mjs +1 -1
- package/src/commands/learn.mjs +10 -12
- package/src/commands/pills.mjs +5 -5
- package/src/commands/pipeline.mjs +4 -8
- package/src/commands/release.mjs +2 -3
- package/src/commands/runs.mjs +1 -1
- package/src/commands/snapshot.mjs +12 -50
- package/src/commands/stats.mjs +7 -8
- package/src/commands/status.mjs +4 -5
- package/src/commands/upgrade.mjs +9 -12
- package/src/commands/where.mjs +9 -18
- package/src/commands/wire.mjs +8 -19
- package/src/deep.mjs +3 -3
- package/src/gate.mjs +5 -6
- package/src/graph.mjs +1 -1
- package/src/guard.mjs +7 -8
- package/src/langfuse.mjs +9 -8
- package/src/lock.mjs +82 -0
- package/src/paths.mjs +65 -0
- package/src/shell.mjs +3 -3
- package/src/steps.mjs +5 -19
- package/src/store.mjs +2 -2
- package/src/wiring.mjs +17 -6
package/src/paths.mjs
CHANGED
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
11
|
import { existsSync, readFileSync } from 'node:fs';
|
|
12
|
+
import { readdir } from 'node:fs/promises';
|
|
12
13
|
import { homedir } from 'node:os';
|
|
13
14
|
import { join, resolve } from 'node:path';
|
|
14
15
|
|
|
@@ -101,6 +102,70 @@ export function legacyHint(target) {
|
|
|
101
102
|
: '';
|
|
102
103
|
}
|
|
103
104
|
|
|
105
|
+
/**
|
|
106
|
+
* A project's profile, read the one way every command reads it: `{profile, path}`, or `{path, error}` — one
|
|
107
|
+
* line saying what is wrong, with `missing` when there is no profile at all. Commands that parsed it on
|
|
108
|
+
* their own answered a stray comma with a stack trace, and each that did not said so differently.
|
|
109
|
+
*
|
|
110
|
+
* @param {string} target - The project.
|
|
111
|
+
* @returns {{path: string, profile?: object, error?: string, missing?: boolean}}
|
|
112
|
+
*/
|
|
113
|
+
export function readProfile(target) {
|
|
114
|
+
const path = join(target, HARNESS, 'profile.json');
|
|
115
|
+
if (!existsSync(path)) {
|
|
116
|
+
const hint = legacyHint(target) || ' — run `nina init` first, or name the project with --project';
|
|
117
|
+
return { path, missing: true, error: `no ${HARNESS}/profile.json under ${target}${hint}` };
|
|
118
|
+
}
|
|
119
|
+
try {
|
|
120
|
+
const profile = JSON.parse(readFileSync(path, 'utf8'));
|
|
121
|
+
if (profile === null || typeof profile !== 'object' || Array.isArray(profile)) return { path, error: `${path} is not a JSON object` };
|
|
122
|
+
return { path, profile };
|
|
123
|
+
} catch (error) {
|
|
124
|
+
return { path, error: `${path} cannot be read — ${error.message}` };
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Where a project's layers are read from.
|
|
130
|
+
*
|
|
131
|
+
* A project pins a frozen release, or tracks the working tree with "dev". A pinned release
|
|
132
|
+
* that is missing is an error, never a silent fall back to whatever the harness happens to
|
|
133
|
+
* look like right now: that would compose an unreviewed core into a project that asked for
|
|
134
|
+
* a reviewed one, and nothing downstream would say so. Every reader asks this one: the commands,
|
|
135
|
+
* and the hooks that ask whether the pin ships them.
|
|
136
|
+
*
|
|
137
|
+
* @param {string} root - The NINA install directory.
|
|
138
|
+
* @param {string|undefined} core - The profile's `core` field.
|
|
139
|
+
* @returns {{dir: string}|{error: string}}
|
|
140
|
+
*/
|
|
141
|
+
export function layerRootFor(root, core) {
|
|
142
|
+
if (!core || core === 'dev') {
|
|
143
|
+
// `dev` means "track the layers as they are being worked on", which only exists in a
|
|
144
|
+
// checkout of this repo. An installed package ships frozen releases and nothing else,
|
|
145
|
+
// so say that rather than composing an empty tree and reporting nothing wrong.
|
|
146
|
+
if (!existsSync(join(root, 'core'))) {
|
|
147
|
+
return { error: `profile pins core "dev", which tracks the NINA working tree — ${root} is an installed package and has only releases` };
|
|
148
|
+
}
|
|
149
|
+
return { dir: root };
|
|
150
|
+
}
|
|
151
|
+
// A name, never a path: `../x` would read layers from outside the releases.
|
|
152
|
+
if (typeof core !== 'string' || !/^[A-Za-z0-9][A-Za-z0-9._-]*$/.test(core)) return { error: `profile pins core ${JSON.stringify(core)}, which is not a release name` };
|
|
153
|
+
const dir = join(root, 'releases', core);
|
|
154
|
+
if (!existsSync(dir)) return { error: `profile pins core ${core}, which is not in ${join(root, 'releases')}` };
|
|
155
|
+
return { dir };
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* The surfaces a layer root offers, by name, in order. Seven commands listed the directory each on its own.
|
|
160
|
+
*
|
|
161
|
+
* @param {string} layerRoot - From {@link layerRootFor}.
|
|
162
|
+
* @returns {Promise<string[]>}
|
|
163
|
+
*/
|
|
164
|
+
export async function surfacesIn(layerRoot) {
|
|
165
|
+
const entries = await readdir(join(layerRoot, 'surfaces'), { withFileTypes: true }).catch(() => []);
|
|
166
|
+
return entries.filter((e) => e.isDirectory()).map((e) => e.name).sort();
|
|
167
|
+
}
|
|
168
|
+
|
|
104
169
|
/**
|
|
105
170
|
* Where `nina upgrade --apply` writes down a move while it is in flight: the versions it moves between, the
|
|
106
171
|
* files it composes for the first time, and — under {@link movedFrom} — every file it can touch, as it was.
|
package/src/shell.mjs
CHANGED
|
@@ -13,8 +13,9 @@ import { spawnSync } from 'node:child_process';
|
|
|
13
13
|
import { appendFileSync, mkdirSync, readFileSync } from 'node:fs';
|
|
14
14
|
import { dirname } from 'node:path';
|
|
15
15
|
import { createInterface } from 'node:readline';
|
|
16
|
-
import {
|
|
16
|
+
import { printBanner } from './banner.mjs';
|
|
17
17
|
import { shellHistoryFile } from './paths.mjs';
|
|
18
|
+
import { dim, pink } from './look.mjs';
|
|
18
19
|
|
|
19
20
|
/** Words the session answers itself rather than handing to a command. */
|
|
20
21
|
const LEAVE = new Set(['exit', 'quit', 'q']);
|
|
@@ -87,8 +88,7 @@ function keep(line) {
|
|
|
87
88
|
*/
|
|
88
89
|
export function shell({ bin, version, commands }) {
|
|
89
90
|
const terminal = Boolean(process.stdin.isTTY && process.stdout.isTTY);
|
|
90
|
-
const
|
|
91
|
-
const prompt = useColor() ? `\x1b[38;2;${PINK.join(';')}mnina ›\x1b[0m ` : 'nina › ';
|
|
91
|
+
const prompt = `${pink('nina ›')} `;
|
|
92
92
|
|
|
93
93
|
printBanner(version);
|
|
94
94
|
console.log(dim(' type a command — stats, check, upgrade --to <version> — `help` lists them, `clear` starts the screen over, `exit` leaves\n'));
|
package/src/steps.mjs
CHANGED
|
@@ -6,16 +6,13 @@
|
|
|
6
6
|
* project forward was six commands in a fixed order, where getting the order wrong quietly
|
|
7
7
|
* overwrote the project's own file — so the order belongs in the tool, not in a message.
|
|
8
8
|
*
|
|
9
|
-
*
|
|
10
|
-
* so a log, a CI run and a pipe
|
|
9
|
+
* On a terminal the step running shows as `...` until its line replaces it. Not animated: a step runs
|
|
10
|
+
* synchronously, so a timer would never fire while it works. A log, a CI run and a pipe read like the
|
|
11
|
+
* terminal does, minus that line.
|
|
11
12
|
*/
|
|
12
13
|
|
|
13
|
-
/** Frames of the ellipsis, slow enough to read and fast enough to look alive. */
|
|
14
|
-
const FRAMES = ['. ', '.. ', '...'];
|
|
15
|
-
const TICK = 220;
|
|
16
|
-
|
|
17
14
|
/**
|
|
18
|
-
* Whether to
|
|
15
|
+
* Whether to show the step running — a pipe, a CI log and a test all get plain lines instead.
|
|
19
16
|
*
|
|
20
17
|
* @param {NodeJS.WriteStream} stream
|
|
21
18
|
* @returns {boolean}
|
|
@@ -46,24 +43,13 @@ export function runSteps(steps, options = {}) {
|
|
|
46
43
|
continue;
|
|
47
44
|
}
|
|
48
45
|
|
|
49
|
-
|
|
50
|
-
let timer = null;
|
|
51
|
-
if (live) {
|
|
52
|
-
stream.write(` ${FRAMES[0]} ${step.label}`);
|
|
53
|
-
timer = setInterval(() => {
|
|
54
|
-
frame = (frame + 1) % FRAMES.length;
|
|
55
|
-
stream.write(`\r ${FRAMES[frame]} ${step.label}`);
|
|
56
|
-
}, TICK);
|
|
57
|
-
timer.unref?.();
|
|
58
|
-
}
|
|
59
|
-
|
|
46
|
+
if (live) stream.write(` ... ${step.label}`);
|
|
60
47
|
let result;
|
|
61
48
|
try {
|
|
62
49
|
result = step.run();
|
|
63
50
|
} catch (error) {
|
|
64
51
|
result = { ok: false, log: String(error?.stack ?? error) };
|
|
65
52
|
} finally {
|
|
66
|
-
if (timer) clearInterval(timer);
|
|
67
53
|
// `\r` alone leaves the tail of the longest line behind when the next one is shorter.
|
|
68
54
|
if (live) stream.write('\r\u001b[K');
|
|
69
55
|
}
|
package/src/store.mjs
CHANGED
|
@@ -21,7 +21,7 @@ const UNREAD = new Set(['UNCLEAR', 'NONE', null, undefined]);
|
|
|
21
21
|
* @param {string} text - The file.
|
|
22
22
|
* @returns {object[]}
|
|
23
23
|
*/
|
|
24
|
-
|
|
24
|
+
function parseStore(text) {
|
|
25
25
|
return String(text)
|
|
26
26
|
.split('\n')
|
|
27
27
|
.filter((l) => l.trim())
|
|
@@ -74,7 +74,7 @@ export function readStoreFile(file, { raw = false } = {}) {
|
|
|
74
74
|
* @param {string} dir - The project.
|
|
75
75
|
* @returns {string[]}
|
|
76
76
|
*/
|
|
77
|
-
|
|
77
|
+
function storeNamesOf(dir) {
|
|
78
78
|
const names = new Set([slugFor(dir)]);
|
|
79
79
|
try {
|
|
80
80
|
names.add(slugFor(realpathSync(dir)));
|
package/src/wiring.mjs
CHANGED
|
@@ -22,11 +22,11 @@ import { join } from 'node:path';
|
|
|
22
22
|
/** The composed scripts the hooks run. */
|
|
23
23
|
export const CHECK = 'scripts/harness-check.mjs';
|
|
24
24
|
export const GATE = 'scripts/loop-gate.mjs';
|
|
25
|
-
|
|
26
|
-
|
|
25
|
+
const GUARD = 'scripts/edit-guard.mjs';
|
|
26
|
+
const COST = 'scripts/cost-watch.mjs';
|
|
27
27
|
|
|
28
28
|
/** The npm scripts the detectors hang off: the reviewer runs one, the other is a detector itself. */
|
|
29
|
-
|
|
29
|
+
const SCRIPTS = {
|
|
30
30
|
'harness:check': 'node scripts/harness-check.mjs',
|
|
31
31
|
'harness:compose:check': 'nina compose --check --quiet',
|
|
32
32
|
};
|
|
@@ -73,7 +73,7 @@ export function packageInstalled(target) {
|
|
|
73
73
|
* @param {string} module - `gate`, `guard`, …
|
|
74
74
|
* @returns {boolean}
|
|
75
75
|
*/
|
|
76
|
-
|
|
76
|
+
function packageExports(target, module) {
|
|
77
77
|
try {
|
|
78
78
|
createRequire(join(target, 'package.json')).resolve(`@xhulz/nina/${module}`);
|
|
79
79
|
return true;
|
|
@@ -111,7 +111,7 @@ const previousCommands = (h) => [command(h.script, h.mode), ...EARLIER_CANNOT_ST
|
|
|
111
111
|
* loop gate has four, one per fact it keeps: a verdict, a dispatch, the owner speaking, and the
|
|
112
112
|
* decision itself; and a fifth, as each stage starts, that hands the stage its lessons (`src/lessons.mjs`).
|
|
113
113
|
*/
|
|
114
|
-
|
|
114
|
+
const HOOKS = [
|
|
115
115
|
{
|
|
116
116
|
event: 'Stop', script: CHECK, mode: '--hook', timeout: 30, statusMessage: 'Checking the harness...', why: 'nobody is told what a turn left behind',
|
|
117
117
|
crash: (cannot) => ({ systemMessage: `NINA: the harness check could not start — ${cannot}` }),
|
|
@@ -308,6 +308,17 @@ function settingsHooks(hooks) {
|
|
|
308
308
|
return out;
|
|
309
309
|
}
|
|
310
310
|
|
|
311
|
+
/** How {@link missingWiring} opens the sentence that says the package is missing. */
|
|
312
|
+
const NOT_INSTALLED = '@xhulz/nina is not installed in this project';
|
|
313
|
+
|
|
314
|
+
/**
|
|
315
|
+
* Whether what {@link missingWiring} found includes the package itself: the one thing `wire` cannot do.
|
|
316
|
+
*
|
|
317
|
+
* @param {string[]} unwired - Its sentences.
|
|
318
|
+
* @returns {boolean}
|
|
319
|
+
*/
|
|
320
|
+
export const lacksPackage = (unwired) => unwired.some((w) => w.startsWith(NOT_INSTALLED));
|
|
321
|
+
|
|
311
322
|
/**
|
|
312
323
|
* Whatever of the wiring a project lacks, one sentence each.
|
|
313
324
|
*
|
|
@@ -320,7 +331,7 @@ export async function missingWiring(target, shipped) {
|
|
|
320
331
|
// First, because nothing below matters without it: the composed scripts import the package.
|
|
321
332
|
if ((shipped.has(CHECK) || shipped.has(GATE) || shipped.has(GUARD)) && !packageInstalled(target)) {
|
|
322
333
|
out.push(
|
|
323
|
-
|
|
334
|
+
`${NOT_INSTALLED}, so the composed scripts cannot load and every hook fails — ` +
|
|
324
335
|
'pnpm add -D -E @xhulz/nina',
|
|
325
336
|
);
|
|
326
337
|
} else {
|