@notis_ai/cli 0.2.0-beta.76.1 → 0.2.0-beta.92.1

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@notis_ai/cli",
3
- "version": "0.2.0-beta.76.1",
3
+ "version": "0.2.0-beta.92.1",
4
4
  "description": "Agent-first Notis CLI for apps and generic tool execution",
5
5
  "type": "module",
6
6
  "bin": {
@@ -22,6 +22,7 @@
22
22
  "prepack": "npm run build",
23
23
  "release:prepare": "npm run build && node ./scripts/prepare-publish.js --apply",
24
24
  "cli:set-mode": "node ./scripts/set-cli-mode.js",
25
+ "smoke": "node ./scripts/smoke-package.js",
25
26
  "test": "node --test"
26
27
  },
27
28
  "engines": {
package/src/cli.js CHANGED
@@ -1,10 +1,29 @@
1
+ import { readFileSync } from 'node:fs';
2
+ import { dirname, join } from 'node:path';
3
+ import { fileURLToPath } from 'node:url';
1
4
  import { Command } from 'commander';
2
5
  import { COMMAND_SPECS, GROUP_SUMMARIES } from './command-specs/index.js';
3
6
  import { OutputManager } from './runtime/output.js';
4
7
  import { asCliError } from './runtime/errors.js';
5
8
  import { resolveRuntimeProfile, workspacePath } from './runtime/profiles.js';
6
9
 
7
- const CLI_VERSION = '0.2.0';
10
+ // Read the version from package.json: the publish pipeline bumps the manifest
11
+ // (scripts/release-utils.js applyVersion), so a hardcoded string here goes
12
+ // stale on every release.
13
+ function readCliVersion() {
14
+ try {
15
+ const manifestPath = join(dirname(fileURLToPath(import.meta.url)), '..', 'package.json');
16
+ const version = JSON.parse(readFileSync(manifestPath, 'utf-8')).version;
17
+ if (typeof version === 'string' && version.trim()) {
18
+ return version.trim();
19
+ }
20
+ } catch {
21
+ // Fall through to the placeholder below.
22
+ }
23
+ return '0.0.0';
24
+ }
25
+
26
+ const CLI_VERSION = readCliVersion();
8
27
 
9
28
  function buildHelpFooter(spec) {
10
29
  const lines = [
@@ -40,20 +40,50 @@ const IGNORED_SOURCE_DIRS = new Set([
40
40
  'coverage',
41
41
  ]);
42
42
 
43
- function loadBoundaryRules() {
44
- return JSON.parse(readFileSync(resolveRulesPath(), 'utf-8'));
45
- }
46
-
47
43
  function compileRules(entries) {
48
- return (entries || []).map((entry) => ({
44
+ // Tolerate a rules object whose javascript/css field is a non-array (a corrupt
45
+ // file can parse to {"javascript":"x"}); coerce anything non-array to [] so
46
+ // getCompiledRules degrades to an empty rule set instead of throwing on .map.
47
+ return (Array.isArray(entries) ? entries : []).map((entry) => ({
49
48
  regex: new RegExp(entry.pattern, 'm'),
50
49
  message: entry.message,
51
50
  }));
52
51
  }
53
52
 
54
- const boundaryRules = loadBoundaryRules();
55
- const javascriptRules = compileRules(boundaryRules.javascript);
56
- const cssRules = compileRules(boundaryRules.css);
53
+ // Loaded lazily on first validation rather than at module import time: a
54
+ // missing rules file must not prevent the whole CLI from booting (every
55
+ // command imports this module transitively). The server re-validates on
56
+ // save/deploy, so an empty client-side rule set degrades gracefully.
57
+ let compiledRules = null;
58
+
59
+ function getCompiledRules() {
60
+ if (compiledRules) {
61
+ return compiledRules;
62
+ }
63
+ let boundaryRules = { javascript: [], css: [] };
64
+ try {
65
+ const parsed = JSON.parse(readFileSync(resolveRulesPath(), 'utf-8'));
66
+ // Keep the safe default unless the file is a real rules object: a valid but
67
+ // non-object payload (null, a number, an array) would otherwise throw on the
68
+ // `.javascript`/`.css` deref below, reintroducing the boot crash this guards.
69
+ if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) {
70
+ boundaryRules = parsed;
71
+ } else {
72
+ process.stderr.write(
73
+ 'Warning: Notis app boundary rules are not a rules object; skipping local boundary checks.\n',
74
+ );
75
+ }
76
+ } catch (error) {
77
+ process.stderr.write(
78
+ `Warning: could not load Notis app boundary rules (${error.message}); skipping local boundary checks.\n`,
79
+ );
80
+ }
81
+ compiledRules = {
82
+ javascript: compileRules(boundaryRules.javascript),
83
+ css: compileRules(boundaryRules.css),
84
+ };
85
+ return compiledRules;
86
+ }
57
87
 
58
88
  function collectProjectFiles(projectDir, dir, results) {
59
89
  if (!existsSync(dir)) {
@@ -101,11 +131,12 @@ function applyRules(content, rules, relPath) {
101
131
 
102
132
  function validateTextFile(relPath, content) {
103
133
  const extension = extname(relPath);
134
+ const rules = getCompiledRules();
104
135
  if (extension === '.css' || extension === '.scss' || extension === '.sass' || extension === '.pcss') {
105
- return applyRules(content, cssRules, relPath);
136
+ return applyRules(content, rules.css, relPath);
106
137
  }
107
138
  if (extension === '.js' || extension === '.jsx' || extension === '.ts' || extension === '.tsx') {
108
- return applyRules(content, javascriptRules, relPath);
139
+ return applyRules(content, rules.javascript, relPath);
109
140
  }
110
141
  return [];
111
142
  }