cognitive-modules-cli 2.2.5 → 2.2.8

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 (42) hide show
  1. package/CHANGELOG.md +7 -1
  2. package/README.md +25 -3
  3. package/dist/audit.d.ts +13 -0
  4. package/dist/audit.js +25 -0
  5. package/dist/cli.js +188 -3
  6. package/dist/commands/add.js +232 -7
  7. package/dist/commands/compose.d.ts +2 -0
  8. package/dist/commands/compose.js +60 -1
  9. package/dist/commands/core.d.ts +31 -0
  10. package/dist/commands/core.js +338 -0
  11. package/dist/commands/index.d.ts +1 -0
  12. package/dist/commands/index.js +1 -0
  13. package/dist/commands/pipe.js +45 -2
  14. package/dist/commands/run.d.ts +1 -0
  15. package/dist/commands/run.js +136 -31
  16. package/dist/commands/search.js +13 -3
  17. package/dist/commands/update.js +4 -1
  18. package/dist/errors/index.d.ts +7 -0
  19. package/dist/errors/index.js +48 -40
  20. package/dist/modules/composition.d.ts +15 -2
  21. package/dist/modules/composition.js +16 -6
  22. package/dist/modules/loader.d.ts +10 -0
  23. package/dist/modules/loader.js +168 -0
  24. package/dist/modules/runner.d.ts +10 -6
  25. package/dist/modules/runner.js +130 -16
  26. package/dist/profile.d.ts +8 -0
  27. package/dist/profile.js +59 -0
  28. package/dist/provenance.d.ts +50 -0
  29. package/dist/provenance.js +137 -0
  30. package/dist/registry/assets.d.ts +48 -0
  31. package/dist/registry/assets.js +723 -0
  32. package/dist/registry/client.d.ts +20 -5
  33. package/dist/registry/client.js +87 -30
  34. package/dist/registry/tar.d.ts +8 -0
  35. package/dist/registry/tar.js +353 -0
  36. package/dist/server/http.js +167 -42
  37. package/dist/server/index.d.ts +2 -0
  38. package/dist/server/index.js +1 -0
  39. package/dist/server/sse.d.ts +13 -0
  40. package/dist/server/sse.js +22 -0
  41. package/dist/types.d.ts +31 -0
  42. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -2,7 +2,13 @@
2
2
 
3
3
  All notable changes to this package are documented in this file.
4
4
 
5
- ## 2.2.5 - 2026-02-06
5
+ ## 2.2.8 - 2026-02-07
6
+
7
+ - Fix: `npx cogn` alias compatibility on newer Node (exports + ESM). (Alias fix ships in `cogn@2.2.8`.)
8
+ - Hardening: configurable registry index fetch limits (`--registry-timeout-ms`, `--registry-max-bytes`).
9
+ - Hardening: remote registry verification supports bounded concurrency (`--concurrency`).
10
+
11
+ ## 2.2.7 - 2026-02-06
6
12
 
7
13
  - Standardized v2.2 runtime behavior and cross-surface error envelope consistency (CLI/HTTP/MCP).
8
14
  - Clarified `compose` output contract: default/pretty output returns full v2.2 envelope, while `compose --trace` returns a debug wrapper object (`result/moduleResults/trace/totalTimeMs`) for diagnostics.
package/README.md CHANGED
@@ -10,12 +10,12 @@ Node.js/TypeScript 版本的 Cognitive Modules CLI,提供 `cog` 命令。
10
10
 
11
11
  ```bash
12
12
  # 全局安装(推荐)
13
- npm install -g cogn@2.2.5
13
+ npm install -g cogn@2.2.8
14
14
  # 或使用完整包名(同样提供 `cog` 命令)
15
- # npm install -g cognitive-modules-cli@2.2.5
15
+ # npm install -g cognitive-modules-cli@2.2.8
16
16
 
17
17
  # 或使用 npx 零安装
18
- npx cogn@2.2.5 --help
18
+ npx cogn@2.2.8 --help
19
19
  ```
20
20
 
21
21
  ## 快速开始
@@ -50,6 +50,18 @@ echo "review this code" | cog pipe --module code-reviewer
50
50
  ## 命令
51
51
 
52
52
  ```bash
53
+ # Core(单文件极简路径)
54
+ cog core new # 生成 demo.md
55
+ cog core run demo.md --args "..." # 运行单文件模块
56
+ cog core promote demo.md # 升级为 v2 模块目录
57
+
58
+ # 渐进复杂度(Profiles)
59
+ cog run code-reviewer --args "..." --profile core # 极简:跳过校验
60
+ cog run code-reviewer --args "..." --profile default # 默认:开启校验
61
+ cog run code-reviewer --args "..." --profile strict # 更严格:开启校验(更强门禁)
62
+ cog run code-reviewer --args "..." --profile certified # 最严格:v2.2 + 审计 + registry provenance/完整性门禁
63
+ # 覆盖开关:--validate auto|on|off,--audit(写入 ~/.cognitive/audit/)
64
+
53
65
  # 模块操作
54
66
  cog list # 列出模块
55
67
  cog run <module> --args "..." # 运行模块
@@ -76,6 +88,16 @@ cog mcp # 启动 MCP 服务(Claude Code / Cursor)
76
88
 
77
89
  # 环境检查
78
90
  cog doctor
91
+
92
+ # Registry(索引与分发)
93
+ # 默认 registry index(latest):
94
+ # https://github.com/Cognary/cognitive/releases/latest/download/cognitive-registry.v2.json
95
+ # 可通过环境变量或全局参数覆盖:
96
+ COGNITIVE_REGISTRY_URL=... cog search
97
+ COGNITIVE_REGISTRY_TIMEOUT_MS=15000 COGNITIVE_REGISTRY_MAX_BYTES=2097152 cog search
98
+ cog search --registry https://github.com/Cognary/cognitive/releases/download/v2.2.8/cognitive-registry.v2.json
99
+ cog registry verify --remote --index https://github.com/Cognary/cognitive/releases/latest/download/cognitive-registry.v2.json
100
+ cog registry verify --remote --concurrency 2
79
101
  ```
80
102
 
81
103
  ## 开发
@@ -0,0 +1,13 @@
1
+ export interface AuditRecord {
2
+ ts: string;
3
+ kind: 'run' | 'pipe' | 'compose';
4
+ policy?: unknown;
5
+ provider?: string;
6
+ module?: unknown;
7
+ input?: unknown;
8
+ result?: unknown;
9
+ notes?: string[];
10
+ }
11
+ export declare function writeAuditRecord(record: AuditRecord): Promise<{
12
+ path: string;
13
+ } | null>;
package/dist/audit.js ADDED
@@ -0,0 +1,25 @@
1
+ import * as fs from 'node:fs/promises';
2
+ import * as path from 'node:path';
3
+ import * as os from 'node:os';
4
+ function safeSlug(s) {
5
+ const out = s.trim().toLowerCase().replace(/\s+/g, '-').replace(/[^a-z0-9._-]/g, '-');
6
+ return out.length > 0 ? out.slice(0, 80) : 'unknown';
7
+ }
8
+ export async function writeAuditRecord(record) {
9
+ // Keep it simple and predictable: write under ~/.cognitive/audit/
10
+ const dir = path.join(os.homedir(), '.cognitive', 'audit');
11
+ const ts = record.ts.replace(/[:.]/g, '-');
12
+ const kind = record.kind;
13
+ const moduleName = safeSlug(typeof record.module?.name === 'string' ? record.module.name : 'module');
14
+ const filename = `${ts}-${kind}-${moduleName}-${Math.random().toString(16).slice(2, 10)}.json`;
15
+ try {
16
+ await fs.mkdir(dir, { recursive: true });
17
+ const outPath = path.join(dir, filename);
18
+ await fs.writeFile(outPath, JSON.stringify(record, null, 2) + '\n', 'utf-8');
19
+ return { path: outPath };
20
+ }
21
+ catch {
22
+ // Audit must never break execution.
23
+ return null;
24
+ }
25
+ }
package/dist/cli.js CHANGED
@@ -15,9 +15,12 @@
15
15
  */
16
16
  import { parseArgs } from 'node:util';
17
17
  import { getProvider, listProviders } from './providers/index.js';
18
- import { run, list, pipe, init, add, update, remove, versions, compose, composeInfo, validate, validateAll, migrate, migrateAll, test, testAll, search, listCategories, info } from './commands/index.js';
18
+ import { run, list, pipe, init, add, update, remove, versions, compose, composeInfo, validate, validateAll, migrate, migrateAll, test, testAll, search, listCategories, info, core } from './commands/index.js';
19
19
  import { listModules, getDefaultSearchPaths } from './modules/loader.js';
20
20
  import { VERSION } from './version.js';
21
+ import { resolveExecutionPolicy } from './profile.js';
22
+ import { buildRegistryAssets, verifyRegistryAssets } from './registry/assets.js';
23
+ import { DEFAULT_REGISTRY_URL } from './registry/client.js';
21
24
  async function main() {
22
25
  const args = process.argv.slice(2);
23
26
  const command = args[0];
@@ -33,6 +36,12 @@ async function main() {
33
36
  const { values, positionals } = parseArgs({
34
37
  args: args.slice(1),
35
38
  options: {
39
+ help: { type: 'boolean', short: 'h', default: false },
40
+ stdin: { type: 'boolean', default: false }, // core: read module prompt from stdin
41
+ force: { type: 'boolean', default: false }, // core promote: overwrite existing target dir
42
+ profile: { type: 'string' }, // progressive complexity profile
43
+ validate: { type: 'string' }, // auto|on|off (overrides --no-validate)
44
+ audit: { type: 'boolean', default: false }, // write audit record to ~/.cognitive/audit/
36
45
  args: { type: 'string', short: 'a' },
37
46
  input: { type: 'string', short: 'i' },
38
47
  module: { type: 'string', short: 'm' },
@@ -41,6 +50,7 @@ async function main() {
41
50
  pretty: { type: 'boolean', default: false },
42
51
  verbose: { type: 'boolean', short: 'V', default: false },
43
52
  'no-validate': { type: 'boolean', default: false },
53
+ stream: { type: 'boolean', default: false },
44
54
  // Add/update options
45
55
  name: { type: 'string', short: 'n' },
46
56
  tag: { type: 'string', short: 't' },
@@ -61,9 +71,59 @@ async function main() {
61
71
  format: { type: 'string', short: 'f' },
62
72
  // Search options
63
73
  category: { type: 'string', short: 'c' },
74
+ registry: { type: 'string' }, // override registry index URL (or use env COGNITIVE_REGISTRY_URL)
75
+ 'registry-timeout-ms': { type: 'string' },
76
+ 'registry-max-bytes': { type: 'string' },
77
+ // Registry build/verify options
78
+ 'modules-dir': { type: 'string' },
79
+ 'v1-registry': { type: 'string' },
80
+ 'out-dir': { type: 'string' },
81
+ 'registry-out': { type: 'string' },
82
+ namespace: { type: 'string' },
83
+ 'runtime-min': { type: 'string' },
84
+ repository: { type: 'string' },
85
+ homepage: { type: 'string' },
86
+ license: { type: 'string' },
87
+ timestamp: { type: 'string' },
88
+ only: { type: 'string', multiple: true },
89
+ index: { type: 'string' },
90
+ 'assets-dir': { type: 'string' },
91
+ 'tarball-base-url': { type: 'string' },
92
+ remote: { type: 'boolean', default: false }, // registry verify: fetch index + tarballs over network
93
+ 'fetch-timeout-ms': { type: 'string' },
94
+ 'max-index-bytes': { type: 'string' },
95
+ 'max-tarball-bytes': { type: 'string' },
96
+ concurrency: { type: 'string' },
64
97
  },
65
98
  allowPositionals: true,
66
99
  });
100
+ if (values.help) {
101
+ if (command === 'core') {
102
+ console.log(JSON.stringify({
103
+ usage: [
104
+ 'cog core new [file.md] [--dry-run]',
105
+ 'cog core schema <file.md> [--pretty]',
106
+ 'cog core run <file.md> [--args \"...\"] [--pretty] [--stream] [--no-validate]',
107
+ 'cog core run --stdin [--args \"...\"] [--pretty] [--stream] [--no-validate]',
108
+ 'cog core promote <file.md> [outDir] [--dry-run] [--force]',
109
+ ],
110
+ }, null, values.pretty ? 2 : 0));
111
+ process.exit(0);
112
+ }
113
+ printHelp();
114
+ process.exit(0);
115
+ }
116
+ // Guard Core-only flags so we don't silently ignore them on other commands.
117
+ if (command !== 'core') {
118
+ if (values.stdin) {
119
+ console.error('Error: --stdin is only supported for `cog core run --stdin`');
120
+ process.exit(1);
121
+ }
122
+ if (values.force) {
123
+ console.error('Error: --force is only supported for `cog core promote --force`');
124
+ process.exit(1);
125
+ }
126
+ }
67
127
  // Get provider
68
128
  let provider;
69
129
  try {
@@ -73,13 +133,64 @@ async function main() {
73
133
  console.error(`Error: ${e instanceof Error ? e.message : e}`);
74
134
  process.exit(1);
75
135
  }
136
+ let policy;
137
+ try {
138
+ policy = resolveExecutionPolicy({
139
+ profile: values.profile,
140
+ validate: values.validate,
141
+ noValidate: values['no-validate'],
142
+ audit: values.audit,
143
+ });
144
+ }
145
+ catch (e) {
146
+ console.error(`Error: ${e instanceof Error ? e.message : String(e)}`);
147
+ process.exit(1);
148
+ }
149
+ const parsePositive = (key, raw) => {
150
+ if (raw === undefined || raw === null || raw === '')
151
+ return undefined;
152
+ const n = Number(raw);
153
+ if (!Number.isFinite(n) || n <= 0) {
154
+ throw new Error(`Invalid --${key}: ${String(raw)} (expected a positive number)`);
155
+ }
156
+ return Math.floor(n);
157
+ };
76
158
  const ctx = {
77
159
  cwd: process.cwd(),
78
160
  provider,
79
161
  verbose: values.verbose,
162
+ policy,
163
+ registryUrl: values.registry ?? undefined,
164
+ registryTimeoutMs: parsePositive('registry-timeout-ms', values['registry-timeout-ms']),
165
+ registryMaxBytes: parsePositive('registry-max-bytes', values['registry-max-bytes']),
80
166
  };
81
167
  try {
82
168
  switch (command) {
169
+ case 'core': {
170
+ const sub = positionals[0];
171
+ const target = positionals[1];
172
+ const rest = positionals.slice(2);
173
+ const result = await core(sub, target, ctx, {
174
+ args: values.args,
175
+ input: values.input,
176
+ noValidate: values['no-validate'],
177
+ pretty: values.pretty,
178
+ verbose: values.verbose,
179
+ stream: values.stream,
180
+ dryRun: values['dry-run'],
181
+ stdin: values.stdin,
182
+ force: values.force,
183
+ }, rest);
184
+ if (!result.success) {
185
+ console.error(`Error: ${result.error}`);
186
+ process.exit(1);
187
+ }
188
+ // Stream mode prints events as NDJSON already (via `cog run`).
189
+ if (!(values.stream && sub === 'run')) {
190
+ console.log(JSON.stringify(result.data, null, values.pretty ? 2 : 0));
191
+ }
192
+ break;
193
+ }
83
194
  case 'run': {
84
195
  const moduleName = args[1];
85
196
  if (!moduleName || moduleName.startsWith('-')) {
@@ -89,9 +200,11 @@ async function main() {
89
200
  const result = await run(moduleName, ctx, {
90
201
  args: values.args,
91
202
  input: values.input,
203
+ // policy.validate is resolved in run(); keep legacy flag compatibility here.
92
204
  noValidate: values['no-validate'],
93
205
  pretty: values.pretty,
94
206
  verbose: values.verbose,
207
+ stream: values.stream,
95
208
  });
96
209
  if (!result.success) {
97
210
  if (result.data) {
@@ -102,7 +215,10 @@ async function main() {
102
215
  }
103
216
  process.exit(1);
104
217
  }
105
- console.log(JSON.stringify(result.data, null, values.pretty ? 2 : 0));
218
+ // Stream mode prints events as NDJSON already.
219
+ if (!values.stream) {
220
+ console.log(JSON.stringify(result.data, null, values.pretty ? 2 : 0));
221
+ }
106
222
  break;
107
223
  }
108
224
  case 'list': {
@@ -383,6 +499,7 @@ async function main() {
383
499
  const result = await compose(moduleName, ctx, {
384
500
  args: values.args,
385
501
  input: values.input,
502
+ noValidate: values['no-validate'],
386
503
  maxDepth: values['max-depth'] ? parseInt(values['max-depth'], 10) : undefined,
387
504
  timeout: values.timeout ? parseInt(values.timeout, 10) : undefined,
388
505
  trace: values.trace,
@@ -765,6 +882,52 @@ async function main() {
765
882
  await client.fetchRegistry(true);
766
883
  console.log('✓ Registry cache refreshed');
767
884
  }
885
+ else if (subCommand === 'build') {
886
+ const result = await buildRegistryAssets({
887
+ tag: values.tag ?? null,
888
+ tarballBaseUrl: values['tarball-base-url'] ?? null,
889
+ modulesDir: values['modules-dir'] ?? 'cognitive/modules',
890
+ v1RegistryPath: values['v1-registry'] ?? 'cognitive-registry.json',
891
+ outDir: values['out-dir'] ?? 'dist/registry-assets',
892
+ registryOut: values['registry-out'] ?? 'cognitive-registry.v2.json',
893
+ namespace: values.namespace ?? 'official',
894
+ runtimeMin: values['runtime-min'] ?? '2.2.0',
895
+ repository: values.repository ?? 'https://github.com/Cognary/cognitive',
896
+ homepage: values.homepage ?? 'https://cognary.github.io/cognitive/',
897
+ license: values.license ?? 'MIT',
898
+ timestamp: values.timestamp ?? null,
899
+ only: Array.isArray(values.only) ? values.only : (values.only ? [String(values.only)] : []),
900
+ });
901
+ console.log(JSON.stringify({ ok: true, ...result }, null, values.pretty ? 2 : 0));
902
+ }
903
+ else if (subCommand === 'verify') {
904
+ const remote = Boolean(values.remote);
905
+ const defaultIndex = (typeof process.env.COGNITIVE_REGISTRY_URL === 'string' && process.env.COGNITIVE_REGISTRY_URL.trim()
906
+ ? process.env.COGNITIVE_REGISTRY_URL.trim()
907
+ : undefined) ??
908
+ ctx.registryUrl ??
909
+ DEFAULT_REGISTRY_URL;
910
+ const indexPath = values.index ??
911
+ (remote ? defaultIndex : 'cognitive-registry.v2.json');
912
+ const assetsDir = values['assets-dir'] ?? (remote ? undefined : 'dist/registry-assets');
913
+ const fetchTimeoutMs = parsePositive('fetch-timeout-ms', values['fetch-timeout-ms']);
914
+ const maxIndexBytes = parsePositive('max-index-bytes', values['max-index-bytes']);
915
+ const maxTarballBytes = parsePositive('max-tarball-bytes', values['max-tarball-bytes']);
916
+ const concurrency = parsePositive('concurrency', values.concurrency);
917
+ const verified = await verifyRegistryAssets({
918
+ registryIndexPath: indexPath,
919
+ assetsDir,
920
+ remote,
921
+ fetchTimeoutMs,
922
+ maxIndexBytes,
923
+ maxTarballBytes,
924
+ concurrency,
925
+ });
926
+ console.log(JSON.stringify(verified, null, values.pretty ? 2 : 0));
927
+ if (!verified.ok) {
928
+ process.exit(1);
929
+ }
930
+ }
768
931
  else {
769
932
  console.error(`Unknown registry subcommand: ${subCommand}`);
770
933
  console.error('');
@@ -773,6 +936,9 @@ async function main() {
773
936
  console.error(' cog registry categories List categories');
774
937
  console.error(' cog registry info <mod> Show module details');
775
938
  console.error(' cog registry refresh Refresh cache');
939
+ console.error(' cog registry build Build registry tarballs + v2 index (local)');
940
+ console.error(' cog registry verify Verify local tarballs against v2 index');
941
+ console.error(' cog registry verify --remote --index <url> Verify remote index+tarballs');
776
942
  process.exit(1);
777
943
  }
778
944
  break;
@@ -800,6 +966,7 @@ USAGE:
800
966
  cog <command> [options]
801
967
 
802
968
  COMMANDS:
969
+ core <cmd> Minimal "one-file" workflow (new, schema, run)
803
970
  run <module> Run a Cognitive Module
804
971
  test <module> Run golden tests for a module
805
972
  compose <module> Execute a composed module workflow
@@ -810,7 +977,7 @@ COMMANDS:
810
977
  remove <module> Remove installed module
811
978
  versions <url> List available versions
812
979
  search [query] Search modules in registry
813
- registry <cmd> Registry commands (list, categories, info, refresh)
980
+ registry <cmd> Registry commands (list, categories, info, refresh, build, verify)
814
981
  validate <module> Validate module structure
815
982
  migrate <module> Migrate module to v2.2 format
816
983
  pipe Pipe mode (stdin/stdout)
@@ -820,6 +987,9 @@ COMMANDS:
820
987
  doctor Check environment and configuration
821
988
 
822
989
  OPTIONS:
990
+ --profile <name> Progressive complexity profile: core|default|strict|certified
991
+ --validate <mode> Validation mode: auto|on|off (overrides --no-validate)
992
+ --audit Write an audit record to ~/.cognitive/audit/ (stderr prints path)
823
993
  -a, --args <str> Arguments to pass to module
824
994
  -i, --input <json> JSON input for module
825
995
  -m, --module <name> Module path within repo (for add)
@@ -831,6 +1001,8 @@ OPTIONS:
831
1001
  --pretty Pretty-print JSON output
832
1002
  -V, --verbose Verbose output
833
1003
  --no-validate Skip schema validation
1004
+ --stdin Read module prompt from stdin (for core run)
1005
+ --force Overwrite target directory (for core promote)
834
1006
  -H, --host <host> Server host (default: 0.0.0.0)
835
1007
  -P, --port <port> Server port (default: 8000)
836
1008
  -d, --max-depth <n> Max composition depth (default: 5)
@@ -842,11 +1014,21 @@ OPTIONS:
842
1014
  --all Process all modules (for validate/migrate)
843
1015
  -f, --format <fmt> Output format: text or json (for validate)
844
1016
  -c, --category <cat> Filter by category (for search)
1017
+ --registry <url> Override registry index URL (or set env COGNITIVE_REGISTRY_URL)
1018
+ --registry-timeout-ms <ms> Registry index fetch timeout (overrides env COGNITIVE_REGISTRY_TIMEOUT_MS)
1019
+ --registry-max-bytes <n> Registry index max bytes (overrides env COGNITIVE_REGISTRY_MAX_BYTES)
845
1020
  -l, --limit <n> Limit results (for search, versions)
846
1021
  -v, --version Show version
847
1022
  -h, --help Show this help
848
1023
 
849
1024
  EXAMPLES:
1025
+ # One-file Core (no registry required)
1026
+ cog core new demo.md
1027
+ cog core run demo.md --args "hello" --pretty
1028
+ cog core schema demo.md --pretty
1029
+ cog core promote demo.md
1030
+ cog core promote demo.md ./cognitive/modules/demo
1031
+
850
1032
  # Search and discover modules
851
1033
  cog search code review # Search by keywords
852
1034
  cog search # List all available modules
@@ -905,6 +1087,9 @@ ENVIRONMENT:
905
1087
  DASHSCOPE_API_KEY Alibaba Qwen (通义千问)
906
1088
  OLLAMA_HOST Ollama local (default: localhost:11434)
907
1089
  COG_MODEL Override default model for any provider
1090
+ COGNITIVE_REGISTRY_URL Override registry index URL
1091
+ COGNITIVE_REGISTRY_TIMEOUT_MS Registry index fetch timeout (ms)
1092
+ COGNITIVE_REGISTRY_MAX_BYTES Registry index max bytes
908
1093
  `);
909
1094
  }
910
1095
  main().catch(e => {