@mmnto/cli 1.94.0 → 1.96.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/build-lite.test.d.ts +14 -0
- package/dist/build-lite.test.d.ts.map +1 -0
- package/dist/build-lite.test.js +61 -0
- package/dist/build-lite.test.js.map +1 -0
- package/dist/commands/compile-cloud-model.test.d.ts +2 -0
- package/dist/commands/compile-cloud-model.test.d.ts.map +1 -0
- package/dist/commands/compile-cloud-model.test.js +91 -0
- package/dist/commands/compile-cloud-model.test.js.map +1 -0
- package/dist/commands/compile.d.ts.map +1 -1
- package/dist/commands/compile.js +10 -1
- package/dist/commands/compile.js.map +1 -1
- package/dist/commands/docs.test.js +1 -0
- package/dist/commands/docs.test.js.map +1 -1
- package/dist/commands/init-detect.d.ts +39 -1
- package/dist/commands/init-detect.d.ts.map +1 -1
- package/dist/commands/init-detect.js +102 -77
- package/dist/commands/init-detect.js.map +1 -1
- package/dist/commands/init-detect.test.d.ts +2 -0
- package/dist/commands/init-detect.test.d.ts.map +1 -0
- package/dist/commands/init-detect.test.js +183 -0
- package/dist/commands/init-detect.test.js.map +1 -0
- package/dist/commands/mail.d.ts.map +1 -1
- package/dist/commands/mail.js +29 -3
- package/dist/commands/mail.js.map +1 -1
- package/dist/commands/mail.test.js +53 -0
- package/dist/commands/mail.test.js.map +1 -1
- package/dist/commands/shield-learn.test.js +1 -0
- package/dist/commands/shield-learn.test.js.map +1 -1
- package/dist/description.d.ts +14 -0
- package/dist/description.d.ts.map +1 -0
- package/dist/description.js +14 -0
- package/dist/description.js.map +1 -0
- package/dist/description.test.d.ts +2 -0
- package/dist/description.test.d.ts.map +1 -0
- package/dist/description.test.js +28 -0
- package/dist/description.test.js.map +1 -0
- package/dist/git.d.ts +7 -0
- package/dist/git.d.ts.map +1 -1
- package/dist/git.js +31 -3
- package/dist/git.js.map +1 -1
- package/dist/git.test.js +49 -0
- package/dist/git.test.js.map +1 -1
- package/dist/help-freeze.d.ts +40 -0
- package/dist/help-freeze.d.ts.map +1 -0
- package/dist/help-freeze.js +53 -0
- package/dist/help-freeze.js.map +1 -0
- package/dist/help-freeze.test.d.ts +2 -0
- package/dist/help-freeze.test.d.ts.map +1 -0
- package/dist/help-freeze.test.js +67 -0
- package/dist/help-freeze.test.js.map +1 -0
- package/dist/help.d.ts +26 -7
- package/dist/help.d.ts.map +1 -1
- package/dist/help.js +93 -64
- package/dist/help.js.map +1 -1
- package/dist/help.test.js +78 -54
- package/dist/help.test.js.map +1 -1
- package/dist/index.js +79 -3
- package/dist/index.js.map +1 -1
- package/dist/orchestrators/anthropic-orchestrator.d.ts.map +1 -1
- package/dist/orchestrators/anthropic-orchestrator.js +21 -3
- package/dist/orchestrators/anthropic-orchestrator.js.map +1 -1
- package/dist/orchestrators/anthropic-orchestrator.test.js +43 -0
- package/dist/orchestrators/anthropic-orchestrator.test.js.map +1 -1
- package/dist/orchestrators/openai-orchestrator.d.ts.map +1 -1
- package/dist/orchestrators/openai-orchestrator.js +17 -3
- package/dist/orchestrators/openai-orchestrator.js.map +1 -1
- package/dist/orchestrators/openai-orchestrator.test.js +37 -0
- package/dist/orchestrators/openai-orchestrator.test.js.map +1 -1
- package/dist/utils/pilot.test.js +1 -0
- package/dist/utils/pilot.test.js.map +1 -1
- package/dist/utils.test.js +1 -0
- package/dist/utils.test.js.map +1 -1
- package/package.json +3 -3
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
|
-
/**
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
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
|
|
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
|
|
39
|
-
|
|
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
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
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":"AAAA,OAAO,EAAW,IAAI,EAAE,MAAM,WAAW,CAAC;
|
|
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 {
|
|
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.
|
|
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('
|
|
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
|
|
21
|
-
expect(output).toContain('
|
|
22
|
-
|
|
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('
|
|
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('
|
|
29
|
-
expect(output).
|
|
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('
|
|
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('
|
|
36
|
-
expect(output).toContain('unknown-cmd');
|
|
64
|
+
expect(output).toContain('review [LLM]');
|
|
37
65
|
});
|
|
38
|
-
it('
|
|
66
|
+
it('prefixes the lesson compile line with [frozen] only when a freeze is active', () => {
|
|
39
67
|
const program = createMockProgram();
|
|
40
|
-
const
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
const
|
|
44
|
-
|
|
45
|
-
expect(
|
|
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('
|
|
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
|
-
|
|
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('
|
|
61
|
-
const program =
|
|
62
|
-
program.
|
|
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(
|
|
68
|
-
|
|
69
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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('
|
|
85
|
-
|
|
86
|
-
|
|
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
|
package/dist/help.test.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"help.test.js","sourceRoot":"","sources":["../src/help.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAE9C,OAAO,EAAE,
|
|
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(
|
|
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
|
|
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 {
|