@mmnto/cli 1.93.0 → 1.95.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/dist/help.d.ts CHANGED
@@ -1,13 +1,32 @@
1
1
  import { Command, Help } from 'commander';
2
- export interface CommandGroup {
3
- readonly name: string;
4
- readonly commands: readonly string[];
5
- }
6
- /** Commands that require an LLM orchestrator */
2
+ /** Commands that require an LLM orchestrator (rendered with an [LLM] badge). */
7
3
  export declare const LLM_COMMANDS: Set<string>;
8
- /** Command grouping for root help */
9
- export declare const COMMAND_GROUPS: readonly CommandGroup[];
4
+ /**
5
+ * The ONE declared consumer tier (mmnto-ai/totem#2336 D2, panel-ruled; ADR-094
6
+ * "operator memory cliff"). Default `totem --help` renders EXACTLY these entries
7
+ * plus a pointer to the full surface; every other command is the advanced tier,
8
+ * enumerable via `totem help --all`. This single exported surface is the source
9
+ * of truth — tiering must NEVER be scattered as per-command flags (a per-command
10
+ * flag re-opens the drift this consolidates). Entries may be subcommand paths
11
+ * ('lesson add'); the renderer resolves them against the LIVE command tree so
12
+ * their descriptions never drift from the registration.
13
+ *
14
+ * `status` is a panel addition — the first-hour health check.
15
+ *
16
+ * Hiding is an information surface, never a gate (Tenet 12/13): every advanced
17
+ * command stays 100% functional and is one `totem help --all` away.
18
+ */
19
+ export declare const CONSUMER_TIER: readonly string[];
20
+ export interface TotemHelpOptions {
21
+ /** `totem help --all` — render the full command surface, tiered. */
22
+ readonly all?: boolean;
23
+ /** A rule-compilation freeze is visible → badge the `lesson compile` line. */
24
+ readonly freezeActive?: boolean;
25
+ }
10
26
  export declare class TotemHelp extends Help {
27
+ private readonly totemOpts;
28
+ constructor(totemOpts?: TotemHelpOptions);
11
29
  formatHelp(cmd: Command, helper: Help): string;
30
+ private renderSection;
12
31
  }
13
32
  //# sourceMappingURL=help.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"help.d.ts","sourceRoot":"","sources":["../src/help.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAE1C,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;CACtC;AAED,gDAAgD;AAChD,eAAO,MAAM,YAAY,aASvB,CAAC;AAEH,qCAAqC;AACrC,eAAO,MAAM,cAAc,EAAE,SAAS,YAAY,EAiBjD,CAAC;AAEF,qBAAa,SAAU,SAAQ,IAAI;IACjC,UAAU,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,GAAG,MAAM;CAmE/C"}
1
+ {"version":3,"file":"help.d.ts","sourceRoot":"","sources":["../src/help.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAE1C,gFAAgF;AAChF,eAAO,MAAM,YAAY,aASvB,CAAC;AAEH;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,aAAa,EAAE,SAAS,MAAM,EAQ1C,CAAC;AAgBF,MAAM,WAAW,gBAAgB;IAC/B,oEAAoE;IACpE,QAAQ,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC;IACvB,8EAA8E;IAC9E,QAAQ,CAAC,YAAY,CAAC,EAAE,OAAO,CAAC;CACjC;AAOD,qBAAa,SAAU,SAAQ,IAAI;IACrB,OAAO,CAAC,QAAQ,CAAC,SAAS;gBAAT,SAAS,GAAE,gBAAqB;IAI7D,UAAU,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,GAAG,MAAM;IAmE9C,OAAO,CAAC,aAAa;CAStB"}
package/dist/help.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { Help } from 'commander';
2
- /** Commands that require an LLM orchestrator */
2
+ /** Commands that require an LLM orchestrator (rendered with an [LLM] badge). */
3
3
  export const LLM_COMMANDS = new Set([
4
4
  'review',
5
5
  'spec',
@@ -10,83 +10,112 @@ export const LLM_COMMANDS = new Set([
10
10
  'triage',
11
11
  'triage-pr',
12
12
  ]);
13
- /** Command grouping for root help */
14
- export const COMMAND_GROUPS = [
15
- {
16
- name: 'Core',
17
- commands: ['lint', 'review', 'check', 'spec'],
18
- },
19
- {
20
- name: 'Entities',
21
- commands: ['rule', 'lesson', 'exemption', 'config'],
22
- },
23
- {
24
- name: 'Workflow',
25
- commands: ['wrap', 'triage', 'triage-pr', 'review-learn'],
26
- },
27
- {
28
- name: 'Setup',
29
- commands: ['init', 'sync', 'hooks', 'doctor', 'status', 'orient', 'eject'],
30
- },
13
+ /**
14
+ * The ONE declared consumer tier (mmnto-ai/totem#2336 D2, panel-ruled; ADR-094
15
+ * "operator memory cliff"). Default `totem --help` renders EXACTLY these entries
16
+ * plus a pointer to the full surface; every other command is the advanced tier,
17
+ * enumerable via `totem help --all`. This single exported surface is the source
18
+ * of truth — tiering must NEVER be scattered as per-command flags (a per-command
19
+ * flag re-opens the drift this consolidates). Entries may be subcommand paths
20
+ * ('lesson add'); the renderer resolves them against the LIVE command tree so
21
+ * their descriptions never drift from the registration.
22
+ *
23
+ * `status` is a panel addition — the first-hour health check.
24
+ *
25
+ * Hiding is an information surface, never a gate (Tenet 12/13): every advanced
26
+ * command stays 100% functional and is one `totem help --all` away.
27
+ */
28
+ export const CONSUMER_TIER = [
29
+ 'init',
30
+ 'lint',
31
+ 'lesson add',
32
+ 'lesson compile',
33
+ 'doctor',
34
+ 'search',
35
+ 'status',
31
36
  ];
37
+ /**
38
+ * Render-time freeze badge (mmnto-ai/totem#2336 D2.4). Prefixes the frozen
39
+ * command's help line. Derived from the freeze primitive by the caller
40
+ * (see help-freeze.ts) and passed in as a boolean — NEVER hardcoded here
41
+ * (Tenet 20): the freeze is a cohort fact, not a product fact, so a consumer
42
+ * with no freeze.json/doctrine pin renders the plain line.
43
+ */
44
+ const FROZEN_BADGE = '[frozen] ';
45
+ /** The command whose help line the rule-compilation freeze decorates. */
46
+ const FREEZE_BADGED_COMMAND = 'lesson compile';
47
+ const COLUMN_PADDING = 2;
32
48
  export class TotemHelp extends Help {
49
+ totemOpts;
50
+ constructor(totemOpts = {}) {
51
+ super();
52
+ this.totemOpts = totemOpts;
53
+ }
33
54
  formatHelp(cmd, helper) {
34
- // Only override root command help
55
+ // Only override ROOT help; subcommand help uses Commander's default.
35
56
  if (cmd.parent) {
36
57
  return super.formatHelp(cmd, helper);
37
58
  }
38
- const visible = helper
39
- .visibleCommands(cmd)
40
- .filter((c) => c.name() !== 'help')
41
- .map((c) => ({
42
- name: c.name(),
43
- description: helper.subcommandDescription(c),
44
- }));
45
- const visibleByName = new Map(visible.map((c) => [c.name, c]));
46
- const usedNames = new Set();
59
+ const all = this.totemOpts.all === true;
60
+ const freezeActive = this.totemOpts.freezeActive === true;
47
61
  const cliName = cmd.name();
48
62
  const cliDescription = cmd.description() || 'Totem';
63
+ // Resolve a declared tier entry (possibly a subcommand path like
64
+ // 'lesson add') to its live description. Unresolvable entries are skipped
65
+ // so a partial program (e.g. a test harness) degrades gracefully.
66
+ const resolve = (entryPath) => {
67
+ const parts = entryPath.split(' ');
68
+ let current = cmd;
69
+ for (const part of parts) {
70
+ current = current?.commands.find((c) => c.name() === part);
71
+ if (current === undefined)
72
+ return undefined;
73
+ }
74
+ const base = current.description();
75
+ const description = freezeActive && entryPath === FREEZE_BADGED_COMMAND ? FROZEN_BADGE + base : base;
76
+ return { name: entryPath, description };
77
+ };
78
+ const consumerEntries = CONSUMER_TIER.map(resolve).filter((e) => e !== undefined);
49
79
  let output = `${cliDescription}\n\n`;
50
80
  output += `Usage: ${cliName} [command]\n\n`;
51
- const COLUMN_PADDING = 2;
52
- // Render each group
53
- for (const group of COMMAND_GROUPS) {
54
- const groupCmds = group.commands
55
- .filter((name) => visibleByName.has(name))
56
- .map((name) => {
57
- usedNames.add(name);
58
- const entry = visibleByName.get(name);
59
- const badge = LLM_COMMANDS.has(name) ? ' [LLM]' : '';
60
- return { displayName: name + badge, description: entry.description };
61
- });
62
- if (groupCmds.length === 0)
63
- continue;
64
- output += `${group.name}:\n`;
65
- const pad = Math.max(...groupCmds.map((c) => c.displayName.length)) + COLUMN_PADDING;
66
- for (const c of groupCmds) {
67
- output += ` ${c.displayName.padEnd(pad)}${c.description}\n`;
68
- }
69
- output += '\n';
70
- }
71
- // Fallback: any commands not in a group
72
- const ungrouped = visible.filter((c) => !usedNames.has(c.name));
73
- if (ungrouped.length > 0) {
74
- output += `Other:\n`;
75
- const allNames = ungrouped.map((c) => {
76
- const badge = LLM_COMMANDS.has(c.name) ? ' [LLM]' : '';
77
- return c.name + badge;
78
- });
79
- const pad = Math.max(...allNames.map((n) => n.length)) + COLUMN_PADDING;
80
- for (let i = 0; i < ungrouped.length; i++) {
81
- const c = ungrouped[i];
82
- const displayName = allNames[i];
83
- output += ` ${displayName.padEnd(pad)}${c.description}\n`;
84
- }
85
- output += '\n';
81
+ if (!all) {
82
+ output += this.renderSection('Commands:', consumerEntries);
83
+ output += `Run '${cliName} help --all' for the full command surface.\n`;
84
+ output += `Run '${cliName} <command> --help' for details on a specific command.\n`;
85
+ output += `Version: ${cmd.version()}\n`;
86
+ return output;
86
87
  }
88
+ // --all: consumer tier + everything else (advanced), tiered. Advanced is
89
+ // derived from the LIVE command tree (visibleCommands respects `hidden`),
90
+ // so it can never drift from the registration. A top-level command whose
91
+ // full name is itself a consumer entry (init/lint/doctor/search/status) is
92
+ // omitted from advanced; a noun like `lesson` STAYS in advanced so its
93
+ // other verbs remain discoverable even though `lesson add`/`lesson compile`
94
+ // are promoted to the consumer tier.
95
+ output += this.renderSection('Consumer commands:', consumerEntries);
96
+ const consumerTopLevel = new Set(CONSUMER_TIER.filter((p) => !p.includes(' ')));
97
+ const advancedEntries = helper
98
+ .visibleCommands(cmd)
99
+ .filter((c) => c.name() !== 'help' && !consumerTopLevel.has(c.name()))
100
+ .map((c) => ({
101
+ name: LLM_COMMANDS.has(c.name()) ? `${c.name()} [LLM]` : c.name(),
102
+ description: c.description(),
103
+ }))
104
+ .sort((a, b) => a.name.localeCompare(b.name));
105
+ output += this.renderSection('Advanced commands:', advancedEntries);
87
106
  output += `Run '${cliName} <command> --help' for details on a specific command.\n`;
88
107
  output += `Version: ${cmd.version()}\n`;
89
108
  return output;
90
109
  }
110
+ renderSection(title, entries) {
111
+ if (entries.length === 0)
112
+ return '';
113
+ const pad = Math.max(...entries.map((e) => e.name.length)) + COLUMN_PADDING;
114
+ let s = `${title}\n`;
115
+ for (const e of entries) {
116
+ s += ` ${e.name.padEnd(pad)}${e.description}\n`;
117
+ }
118
+ return s + '\n';
119
+ }
91
120
  }
92
121
  //# sourceMappingURL=help.js.map
package/dist/help.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"help.js","sourceRoot":"","sources":["../src/help.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"help.js","sourceRoot":"","sources":["../src/help.ts"],"names":[],"mappings":"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"}
package/dist/help.test.js CHANGED
@@ -1,95 +1,119 @@
1
1
  import { Command } from 'commander';
2
2
  import { describe, expect, it } from 'vitest';
3
- import { COMMAND_GROUPS, LLM_COMMANDS, TotemHelp } from './help.js';
4
- describe('TotemHelp', () => {
3
+ import { CONSUMER_TIER, LLM_COMMANDS, TotemHelp } from './help.js';
4
+ describe('TotemHelp (tiered — mmnto-ai/totem#2336 D2)', () => {
5
5
  function createMockProgram() {
6
6
  const program = new Command('totem');
7
7
  program.version('1.0.0');
8
- program.configureHelp(new TotemHelp());
8
+ program.description('Totem — test description');
9
+ // Consumer tier (top-level)
10
+ program.command('init').description('Initialize Totem');
9
11
  program.command('lint').description('Run compiled rules');
12
+ program.command('doctor').description('Run workspace health diagnostics');
13
+ program.command('search <query>').description('Search the knowledge index');
14
+ program.command('status').description('Show current project health');
15
+ // Consumer tier entries that are subcommand paths under `lesson`
16
+ const lesson = program.command('lesson').description('Manage project lessons');
17
+ lesson.command('add <text>').description('Add a lesson to project memory');
18
+ lesson.command('compile').description('Compile lesson files into deterministic lint rules');
19
+ lesson.command('list').description('List all lessons');
20
+ // Advanced-only commands (must NOT appear in default help)
21
+ program.command('mail').description('Show unread cross-repo mail');
22
+ program.command('orient').description('Derive session orientation');
23
+ program.command('handoff').description('Scaffold a journal entry for handoff');
10
24
  program.command('review').description('AI-powered code review');
11
- program.command('rule').description('Manage compiled rules');
12
- program.command('init').description('Initialize Totem');
13
- program.command('unknown-cmd').description('Some new command');
14
25
  return program;
15
26
  }
16
- it('groups commands under defined categories', () => {
27
+ it('default help renders exactly the consumer tier plus the pointer', () => {
17
28
  const program = createMockProgram();
18
29
  const help = new TotemHelp();
19
30
  const output = help.formatHelp(program, help);
20
- expect(output).toContain('Core:');
21
- expect(output).toContain('Entities:');
22
- expect(output).toContain('Setup:');
31
+ expect(output.startsWith('Totem — test description')).toBe(true);
32
+ expect(output).toContain('Commands:');
33
+ for (const entry of CONSUMER_TIER) {
34
+ expect(output).toContain(entry);
35
+ }
36
+ expect(output).toContain("Run 'totem help --all' for the full command surface.");
37
+ // Advanced commands are hidden from the default surface
38
+ expect(output).not.toContain('mail');
39
+ expect(output).not.toContain('orient');
40
+ // No --all section headers in the default view
41
+ expect(output).not.toContain('Advanced commands:');
23
42
  });
24
- it('adds [LLM] badge to LLM-dependent commands', () => {
43
+ it('--all lists both tiers and includes advanced + continuity commands', () => {
25
44
  const program = createMockProgram();
26
- const help = new TotemHelp();
45
+ const help = new TotemHelp({ all: true });
27
46
  const output = help.formatHelp(program, help);
28
- expect(output).toContain('review [LLM]');
29
- expect(output).not.toContain('lint [LLM]');
47
+ expect(output).toContain('Consumer commands:');
48
+ expect(output).toContain('Advanced commands:');
49
+ // Known advanced command surfaces under --all
50
+ expect(output).toContain('mail');
51
+ expect(output).toContain('orient');
52
+ // Continuity primitives (D5 caveat) stay visibly present in advanced
53
+ expect(output).toContain('handoff');
54
+ // Consumer entries still render
55
+ expect(output).toContain('lesson compile');
56
+ // The `lesson` NOUN stays discoverable in advanced even though two of its
57
+ // verbs are promoted to the consumer tier
58
+ expect(output).toMatch(/Advanced commands:[\s\S]*\blesson\b/);
30
59
  });
31
- it('puts uncategorized commands in Other group', () => {
60
+ it('badges LLM commands in the advanced tier', () => {
32
61
  const program = createMockProgram();
33
- const help = new TotemHelp();
62
+ const help = new TotemHelp({ all: true });
34
63
  const output = help.formatHelp(program, help);
35
- expect(output).toContain('Other:');
36
- expect(output).toContain('unknown-cmd');
64
+ expect(output).toContain('review [LLM]');
37
65
  });
38
- it('uses default help for subcommands', () => {
66
+ it('prefixes the lesson compile line with [frozen] only when a freeze is active', () => {
39
67
  const program = createMockProgram();
40
- const rule = program.commands.find((c) => c.name() === 'rule');
41
- rule.command('list').description('List all rules');
42
- const help = new TotemHelp();
43
- const output = help.formatHelp(rule, help);
44
- // Subcommand help should use Commander default — contains 'list'
45
- expect(output).toContain('list');
46
- // Should NOT contain our custom group headers
47
- expect(output).not.toContain('Core:');
68
+ const frozen = new TotemHelp({ freezeActive: true });
69
+ const frozenOut = frozen.formatHelp(program, frozen);
70
+ expect(frozenOut).toContain('[frozen] Compile lesson files into deterministic lint rules');
71
+ const plain = new TotemHelp({ freezeActive: false });
72
+ const plainOut = plain.formatHelp(program, plain);
73
+ expect(plainOut).not.toContain('[frozen]');
48
74
  });
49
- it('does not show help command in Other group', () => {
75
+ it('the freeze badge is present under --all too', () => {
50
76
  const program = createMockProgram();
51
- const help = new TotemHelp();
77
+ const help = new TotemHelp({ all: true, freezeActive: true });
52
78
  const output = help.formatHelp(program, help);
53
- // 'help' is a built-in Commander command should be excluded from Other
54
- // Extract the Other section lines (between "Other:" and the next blank line)
55
- const otherMatch = output.match(/Other:\n([\s\S]*?)\n\n/);
56
- if (otherMatch) {
57
- expect(otherMatch[1]).not.toMatch(/^\s+help\b/m);
58
- }
79
+ expect(output).toContain('[frozen] Compile lesson files into deterministic lint rules');
59
80
  });
60
- it('skips empty groups', () => {
61
- const program = new Command('totem');
62
- program.version('1.0.0');
63
- program.configureHelp(new TotemHelp());
64
- program.command('lint').description('Run compiled rules');
65
- // Only lint exists — Workflow group should not appear
81
+ it('uses default Commander help for subcommands', () => {
82
+ const program = createMockProgram();
83
+ const lesson = program.commands.find((c) => c.name() === 'lesson');
66
84
  const help = new TotemHelp();
67
- const output = help.formatHelp(program, help);
68
- expect(output).toContain('Core:');
69
- expect(output).not.toContain('Workflow:');
85
+ const output = help.formatHelp(lesson, help);
86
+ // Subcommand help lists the noun's subcommands and does NOT use the tiered
87
+ // root render.
88
+ expect(output).toContain('add');
89
+ expect(output).not.toContain('Consumer commands:');
70
90
  });
71
91
  it('includes version in output', () => {
72
92
  const program = createMockProgram();
73
93
  const help = new TotemHelp();
74
- const output = help.formatHelp(program, help);
75
- expect(output).toContain('Version: 1.0.0');
94
+ expect(help.formatHelp(program, help)).toContain('Version: 1.0.0');
76
95
  });
77
- it('does not show hidden commands', () => {
96
+ it('does not surface hidden commands under --all', () => {
78
97
  const program = createMockProgram();
79
98
  program.command('secret-cmd', { hidden: true }).description('Should not appear');
80
- const help = new TotemHelp();
81
- const output = help.formatHelp(program, help);
82
- expect(output).not.toContain('secret-cmd');
99
+ const help = new TotemHelp({ all: true });
100
+ expect(help.formatHelp(program, help)).not.toContain('secret-cmd');
83
101
  });
84
- it('COMMAND_GROUPS covers expected categories', () => {
85
- const groupNames = COMMAND_GROUPS.map((g) => g.name);
86
- expect(groupNames).toEqual(['Core', 'Entities', 'Workflow', 'Setup']);
102
+ it('CONSUMER_TIER is the declared consumer surface (order-stable)', () => {
103
+ expect([...CONSUMER_TIER]).toEqual([
104
+ 'init',
105
+ 'lint',
106
+ 'lesson add',
107
+ 'lesson compile',
108
+ 'doctor',
109
+ 'search',
110
+ 'status',
111
+ ]);
87
112
  });
88
113
  it('LLM_COMMANDS contains expected entries', () => {
89
114
  expect(LLM_COMMANDS.has('review')).toBe(true);
90
115
  expect(LLM_COMMANDS.has('lint')).toBe(false);
91
116
  expect(LLM_COMMANDS.has('spec')).toBe(true);
92
- expect(LLM_COMMANDS.has('wrap')).toBe(true);
93
117
  });
94
118
  });
95
119
  //# sourceMappingURL=help.test.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"help.test.js","sourceRoot":"","sources":["../src/help.test.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"help.test.js","sourceRoot":"","sources":["../src/help.test.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -4,6 +4,7 @@ import { createRequire } from 'node:module';
4
4
  import { Command } from 'commander';
5
5
  import { z } from 'zod';
6
6
  import { initCommand } from './commands/init.js';
7
+ import { TOTEM_DESCRIPTION } from './description.js';
7
8
  import { REVIEW_DIFF_TRUNCATION_THRESHOLD } from './git.js';
8
9
  import { TotemHelp } from './help.js';
9
10
  import { reapOrphanedTempFiles } from './utils.js';
@@ -72,13 +73,22 @@ function handleError(err) {
72
73
  process.exit(1);
73
74
  }
74
75
  const program = new Command();
76
+ // Root-help tier state (mmnto-ai/totem#2336 D2). Mutated before help renders
77
+ // (the `--help` option path precomputes below; the `help` command action sets
78
+ // it directly) and read back by the configured formatHelp via this closure —
79
+ // the bridge between commander's SYNCHRONOUS help render and the ASYNC freeze
80
+ // read that derives the `[frozen]` badge.
81
+ const helpState = { all: false, freezeActive: false };
75
82
  program
76
83
  .name('totem')
77
- .description('Totem — persistent memory and context layer for AI agents')
84
+ .description(TOTEM_DESCRIPTION)
78
85
  .version(version)
79
86
  .option('--json', 'Output structured JSON to stdout')
87
+ // Disable commander's built-in help command so our tiered `help [command...]
88
+ // --all` command (registered below) owns `totem help`.
89
+ .helpCommand(false)
80
90
  .configureHelp({
81
- formatHelp: (cmd, helper) => new TotemHelp().formatHelp(cmd, helper),
91
+ formatHelp: (cmd, helper) => new TotemHelp({ all: helpState.all, freezeActive: helpState.freezeActive }).formatHelp(cmd, helper),
82
92
  });
83
93
  // Set JSON mode early — preAction may not fire on parse errors
84
94
  if (process.argv.includes('--json')) {
@@ -1200,7 +1210,7 @@ lessonCmd
1200
1210
  });
1201
1211
  lessonCmd
1202
1212
  .command('compile')
1203
- .description('Compile lessons into deterministic regex rules')
1213
+ .description('Compile lesson files into deterministic lint rules')
1204
1214
  .option('--raw', 'Output compiler prompts without LLM synthesis')
1205
1215
  .option('--out <path>', 'Write output to a file instead of stdout')
1206
1216
  .option('--model <name>', 'Override the default model for the orchestrator')
@@ -1625,6 +1635,72 @@ windtunnelCmd
1625
1635
  throw err;
1626
1636
  }
1627
1637
  });
1638
+ // Derive the `[frozen]` badge state for root help (mmnto-ai/totem#2336 D2.4)
1639
+ // from the canonical freeze primitive. Only ever called on a help render, so
1640
+ // ordinary commands never pay for the freeze read.
1641
+ async function computeFreezeActive() {
1642
+ const { deriveRuleCompilationFrozen } = await import('./help-freeze.js');
1643
+ return deriveRuleCompilationFrozen(process.cwd());
1644
+ }
1645
+ // Tiered help surface (mmnto-ai/totem#2336 D2). Replaces commander's built-in
1646
+ // help command (disabled via .helpCommand(false)) so `totem help --all` renders
1647
+ // the FULL command surface, tiered, while `totem help <command>` still delegates
1648
+ // to the default per-command help. Bare `totem help` / `totem --help` show only
1649
+ // the consumer tier plus the pointer to `--all` (partially addresses the
1650
+ // progressive-disclosure ask in mmnto-ai/totem#1722; grouping is left to it).
1651
+ program
1652
+ .command('help [command...]')
1653
+ .description('Show help; add --all for the full command surface (consumer + advanced tiers)')
1654
+ .option('--all', 'List every command, grouped into consumer and advanced tiers')
1655
+ .action(async (commandPath, opts) => {
1656
+ try {
1657
+ if (commandPath.length > 0) {
1658
+ let target = program;
1659
+ for (const part of commandPath) {
1660
+ target = target?.commands.find((c) => c.name() === part);
1661
+ }
1662
+ if (target !== undefined && target !== program) {
1663
+ target.outputHelp();
1664
+ return;
1665
+ }
1666
+ const { TotemConfigError } = await import('@mmnto/totem');
1667
+ throw new TotemConfigError(`Unknown command: ${commandPath.join(' ')}`, "Run 'totem help --all' to list every command.", 'CONFIG_INVALID');
1668
+ }
1669
+ helpState.all = opts.all === true;
1670
+ helpState.freezeActive = await computeFreezeActive();
1671
+ program.outputHelp();
1672
+ }
1673
+ catch (err) {
1674
+ handleError(err);
1675
+ // handleError returns `never` (process.exit); the throw is unreachable but
1676
+ // required to satisfy the Tenet 4 fail-loud rule that bans bare-catch
1677
+ // silent-degrade. Mirrors the stats/mail command pattern in this file.
1678
+ throw err;
1679
+ }
1680
+ });
1681
+ // Precompute root-help tier state for the `--help`/`-h` OPTION path (the `help`
1682
+ // COMMAND path sets it in its own action above). `--all` is cheap to read
1683
+ // always. The freeze read fires ONLY for ROOT help (`totem --help`), never for
1684
+ // subcommand help (`totem lint --help`) — the badge renders only on the root
1685
+ // surface, and gating on isRootHelpInvocation keeps a corrupt freeze.json from
1686
+ // breaking unrelated `totem <command> --help`. A corrupt freeze on the root
1687
+ // path still surfaces loudly via handleError (no fail-open).
1688
+ helpState.all = process.argv.includes('--all');
1689
+ if (process.argv.includes('--help') || process.argv.includes('-h')) {
1690
+ const { isRootHelpInvocation } = await import('./help-freeze.js');
1691
+ if (isRootHelpInvocation(process.argv.slice(2))) {
1692
+ try {
1693
+ helpState.freezeActive = await computeFreezeActive();
1694
+ }
1695
+ catch (err) {
1696
+ handleError(err);
1697
+ // handleError returns `never` (process.exit); the throw is unreachable
1698
+ // but required to satisfy the Tenet 4 fail-loud rule that bans bare-catch
1699
+ // silent-degrade. Mirrors the stats/mail command pattern in this file.
1700
+ throw err;
1701
+ }
1702
+ }
1703
+ }
1628
1704
  // Fire-and-forget: reap orphaned temp files from previous crashed runs
1629
1705
  reapOrphanedTempFiles(process.cwd(), '.totem').catch(() => { });
1630
1706
  try {