@polymorphism-tech/morph-spec 4.2.0 → 4.3.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/bin/morph-spec.js +283 -8
- package/bin/validate.js +4 -4
- package/docs/{v3.0 → next-generation}/AGENTS.md +1 -1
- package/docs/next-generation/CONTEXT-OPTIMIZATION.md +267 -0
- package/docs/next-generation/EXECUTION-FLOW.md +274 -0
- package/docs/next-generation/META-PROMPTS.md +235 -0
- package/docs/next-generation/MIGRATION-GUIDE.md +253 -0
- package/docs/next-generation/THREAD-MANAGEMENT.md +240 -0
- package/package.json +5 -5
- package/src/commands/agents/agents-fuse.js +96 -0
- package/src/commands/agents/micro-agent.js +112 -0
- package/src/commands/agents/spawn-team.js +69 -4
- package/src/commands/agents/squad-template.js +146 -0
- package/src/commands/analytics/analytics.js +176 -0
- package/src/commands/context/context-prime.js +63 -0
- package/src/commands/context/core-four.js +54 -0
- package/src/commands/mcp/mcp.js +102 -0
- package/src/commands/project/detect-agents.js +1 -1
- package/src/commands/project/doctor.js +573 -356
- package/src/commands/project/init.js +1 -1
- package/src/commands/project/update.js +1 -1
- package/src/commands/state/advance-phase.js +433 -416
- package/src/commands/templates/template-render.js +80 -1
- package/src/commands/threads/thread-template.js +103 -0
- package/src/commands/threads/threads.js +261 -0
- package/src/commands/trust/trust.js +205 -0
- package/src/{orchestrator.js → core/orchestrator.js} +8 -8
- package/src/core/state/state-manager.js +18 -2
- package/src/core/workflows/workflow-detector.js +100 -2
- package/src/lib/agents/micro-agent-factory.js +161 -0
- package/src/lib/analytics/analytics-engine.js +345 -0
- package/src/lib/checkpoints/checkpoint-hooks.js +293 -258
- package/src/lib/context/context-bundler.js +240 -0
- package/src/lib/context/context-optimizer.js +212 -0
- package/src/lib/context/context-tracker.js +273 -0
- package/src/lib/context/core-four-tracker.js +201 -0
- package/src/lib/context/mcp-optimizer.js +200 -0
- package/src/lib/execution/fusion-executor.js +304 -0
- package/src/lib/execution/parallel-executor.js +270 -0
- package/src/lib/generators/context-generator.js +3 -3
- package/src/lib/generators/recap-generator.js +2 -2
- package/src/lib/hooks/hook-executor.js +169 -0
- package/src/lib/hooks/stop-hook-executor.js +286 -0
- package/src/lib/hops/hop-composer.js +221 -0
- package/src/lib/threads/thread-coordinator.js +238 -0
- package/src/lib/threads/thread-manager.js +317 -0
- package/src/lib/tracking/artifact-trail.js +202 -0
- package/src/lib/trust/trust-manager.js +269 -0
- package/src/lib/validators/design-system/design-system-validator.js +2 -2
- package/src/lib/validators/validation-runner.js +6 -6
- package/stacks/blazor-azure/.morph/config/agents.json +72 -3
- package/stacks/nextjs-supabase/.morph/config/agents.json +3 -3
- package/CLAUDE.md +0 -993
- package/docs/llm-interaction-config.md +0 -735
- package/docs/v3.0/EXECUTION-FLOW.md +0 -1304
- package/src/commands/utils/migrate-state.js +0 -158
- package/src/commands/utils/upgrade.js +0 -346
- package/src/lib/validators/architecture-validator.js +0 -60
- package/src/lib/validators/content-validator.js +0 -164
- package/src/lib/validators/package-validator.js +0 -61
- package/src/lib/validators/ui-contrast-validator.js +0 -44
- package/stacks/blazor-azure/.claude/commands/morph-apply.md +0 -221
- package/stacks/blazor-azure/.claude/commands/morph-archive.md +0 -79
- package/stacks/blazor-azure/.claude/commands/morph-deploy.md +0 -529
- package/stacks/blazor-azure/.claude/commands/morph-infra.md +0 -209
- package/stacks/blazor-azure/.claude/commands/morph-preflight.md +0 -227
- package/stacks/blazor-azure/.claude/commands/morph-proposal.md +0 -122
- package/stacks/blazor-azure/.claude/commands/morph-status.md +0 -86
- package/stacks/blazor-azure/.claude/commands/morph-troubleshoot.md +0 -122
- package/stacks/blazor-azure/.claude/skills/level-0-meta/README.md +0 -7
- package/stacks/blazor-azure/.claude/skills/level-0-meta/code-review.md +0 -226
- package/stacks/blazor-azure/.claude/skills/level-0-meta/morph-checklist.md +0 -117
- package/stacks/blazor-azure/.claude/skills/level-0-meta/simulation-checklist.md +0 -77
- package/stacks/blazor-azure/.claude/skills/level-1-workflows/README.md +0 -7
- package/stacks/blazor-azure/.claude/skills/level-1-workflows/morph-replicate.md +0 -213
- package/stacks/blazor-azure/.claude/skills/level-1-workflows/phase-clarify.md +0 -131
- package/stacks/blazor-azure/.claude/skills/level-1-workflows/phase-design.md +0 -213
- package/stacks/blazor-azure/.claude/skills/level-1-workflows/phase-setup.md +0 -106
- package/stacks/blazor-azure/.claude/skills/level-1-workflows/phase-tasks.md +0 -164
- package/stacks/blazor-azure/.claude/skills/level-1-workflows/phase-uiux.md +0 -169
- package/stacks/blazor-azure/.claude/skills/level-2-domains/README.md +0 -14
- package/stacks/blazor-azure/.claude/skills/level-2-domains/ai-agents/ai-system-architect.md +0 -192
- package/stacks/blazor-azure/.claude/skills/level-2-domains/architecture/po-pm-advisor.md +0 -197
- package/stacks/blazor-azure/.claude/skills/level-2-domains/architecture/prompt-engineer.md +0 -189
- package/stacks/blazor-azure/.claude/skills/level-2-domains/architecture/seo-growth-hacker.md +0 -320
- package/stacks/blazor-azure/.claude/skills/level-2-domains/architecture/standards-architect.md +0 -156
- package/stacks/blazor-azure/.claude/skills/level-2-domains/backend/api-designer.md +0 -59
- package/stacks/blazor-azure/.claude/skills/level-2-domains/backend/dotnet-senior.md +0 -77
- package/stacks/blazor-azure/.claude/skills/level-2-domains/backend/ef-modeler.md +0 -58
- package/stacks/blazor-azure/.claude/skills/level-2-domains/backend/hangfire-orchestrator.md +0 -126
- package/stacks/blazor-azure/.claude/skills/level-2-domains/backend/ms-agent-expert.md +0 -45
- package/stacks/blazor-azure/.claude/skills/level-2-domains/frontend/blazor-builder.md +0 -210
- package/stacks/blazor-azure/.claude/skills/level-2-domains/frontend/nextjs-expert.md +0 -154
- package/stacks/blazor-azure/.claude/skills/level-2-domains/frontend/ui-ux-designer.md +0 -191
- package/stacks/blazor-azure/.claude/skills/level-2-domains/infrastructure/azure-architect.md +0 -142
- package/stacks/blazor-azure/.claude/skills/level-2-domains/infrastructure/azure-deploy-specialist.md +0 -699
- package/stacks/blazor-azure/.claude/skills/level-2-domains/infrastructure/bicep-architect.md +0 -126
- package/stacks/blazor-azure/.claude/skills/level-2-domains/infrastructure/container-specialist.md +0 -131
- package/stacks/blazor-azure/.claude/skills/level-2-domains/infrastructure/devops-engineer.md +0 -119
- package/stacks/blazor-azure/.claude/skills/level-2-domains/integrations/asaas-financial.md +0 -130
- package/stacks/blazor-azure/.claude/skills/level-2-domains/integrations/azure-identity.md +0 -142
- package/stacks/blazor-azure/.claude/skills/level-2-domains/integrations/clerk-auth.md +0 -108
- package/stacks/blazor-azure/.claude/skills/level-2-domains/integrations/hangfire-orchestrator.md +0 -64
- package/stacks/blazor-azure/.claude/skills/level-2-domains/integrations/resend-email.md +0 -119
- package/stacks/blazor-azure/.claude/skills/level-2-domains/quality/code-analyzer.md +0 -235
- package/stacks/blazor-azure/.claude/skills/level-2-domains/quality/testing-specialist.md +0 -126
- package/stacks/blazor-azure/.claude/skills/level-3-technologies/README.md +0 -7
- package/stacks/blazor-azure/.claude/skills/level-4-patterns/README.md +0 -7
- package/stacks/blazor-azure/.morph/archive/.gitkeep +0 -25
- package/stacks/blazor-azure/.morph/features/.gitkeep +0 -25
- package/stacks/blazor-azure/.morph/schemas/agent.schema.json +0 -296
- package/stacks/blazor-azure/.morph/schemas/tasks.schema.json +0 -220
- package/stacks/blazor-azure/.morph/specs/.gitkeep +0 -20
- package/stacks/blazor-azure/.morph/test-infra/example.bicep +0 -59
- package/stacks/nextjs-supabase/.claude/commands/morph-apply.md +0 -221
- package/stacks/nextjs-supabase/.claude/commands/morph-archive.md +0 -79
- package/stacks/nextjs-supabase/.claude/commands/morph-deploy.md +0 -529
- package/stacks/nextjs-supabase/.claude/commands/morph-infra.md +0 -209
- package/stacks/nextjs-supabase/.claude/commands/morph-preflight.md +0 -227
- package/stacks/nextjs-supabase/.claude/commands/morph-proposal.md +0 -122
- package/stacks/nextjs-supabase/.claude/commands/morph-status.md +0 -86
- package/stacks/nextjs-supabase/.claude/commands/morph-troubleshoot.md +0 -122
- package/stacks/nextjs-supabase/.claude/settings.local.json +0 -6
- package/stacks/nextjs-supabase/.claude/skills/level-2-domains/backend/dotnet-supabase.md +0 -244
- package/stacks/nextjs-supabase/.claude/skills/level-2-domains/frontend/nextjs-supabase.md +0 -335
- package/stacks/nextjs-supabase/.claude/skills/level-2-domains/infrastructure/easypanel-deployer.md +0 -189
- package/stacks/nextjs-supabase/.claude/skills/level-2-domains/integrations/supabase-expert.md +0 -50
- /package/docs/{v3.0 → next-generation}/ANALYSIS.md +0 -0
- /package/docs/{v3.0 → next-generation}/ARCHITECTURE.md +0 -0
- /package/docs/{v3.0 → next-generation}/FEATURES.md +0 -0
- /package/docs/{v3.0 → next-generation}/README.md +0 -0
- /package/docs/{v3.0 → next-generation}/ROADMAP.md +0 -0
|
@@ -3,11 +3,90 @@
|
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
import { writeFileSync, mkdirSync } from 'fs';
|
|
6
|
-
import { dirname } from 'path';
|
|
6
|
+
import { dirname, join } from 'path';
|
|
7
7
|
import chalk from 'chalk';
|
|
8
8
|
import { logger } from '../../utils/logger.js';
|
|
9
9
|
import { getTemplateById, resolveTemplatePathById } from '../../core/templates/template-registry.js';
|
|
10
10
|
import { renderTemplate } from '../../core/templates/template-renderer.js';
|
|
11
|
+
import { renderHOP, listAvailableHOPs } from '../../lib/hops/hop-composer.js';
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Render HOP (Higher-Order Prompt) template command
|
|
15
|
+
*/
|
|
16
|
+
export async function hopRenderCommand(hopId, outputPath, variablesJson, options) {
|
|
17
|
+
logger.header(`Rendering HOP: ${hopId}`);
|
|
18
|
+
logger.blank();
|
|
19
|
+
|
|
20
|
+
try {
|
|
21
|
+
// Parse variables
|
|
22
|
+
let variables = {};
|
|
23
|
+
try {
|
|
24
|
+
variables = JSON.parse(variablesJson || '{}');
|
|
25
|
+
} catch (error) {
|
|
26
|
+
logger.error('Invalid JSON in variables argument');
|
|
27
|
+
logger.dim(` ${error.message}`);
|
|
28
|
+
process.exit(1);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// Add defaults
|
|
32
|
+
variables.DATE = variables.DATE || new Date().toISOString().split('T')[0];
|
|
33
|
+
variables.YEAR = variables.YEAR || new Date().getFullYear().toString();
|
|
34
|
+
variables.TIMESTAMP = variables.TIMESTAMP || new Date().toISOString();
|
|
35
|
+
|
|
36
|
+
// Render via hop-composer
|
|
37
|
+
const frameworkRoot = join(process.cwd(), 'framework');
|
|
38
|
+
const rendered = renderHOP(hopId, variables, { frameworkRoot });
|
|
39
|
+
|
|
40
|
+
if (options?.dryRun || !outputPath) {
|
|
41
|
+
logger.info(chalk.cyan('📋 HOP Preview:'));
|
|
42
|
+
logger.blank();
|
|
43
|
+
console.log(rendered);
|
|
44
|
+
logger.blank();
|
|
45
|
+
if (outputPath) logger.dim(`Would be written to: ${outputPath}`);
|
|
46
|
+
} else {
|
|
47
|
+
mkdirSync(dirname(outputPath), { recursive: true });
|
|
48
|
+
writeFileSync(outputPath, rendered, 'utf-8');
|
|
49
|
+
logger.success(`✅ HOP rendered: ${chalk.cyan(outputPath)}`);
|
|
50
|
+
}
|
|
51
|
+
} catch (error) {
|
|
52
|
+
logger.error(`Failed to render HOP: ${error.message}`);
|
|
53
|
+
process.exit(1);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* List available HOPs
|
|
59
|
+
*/
|
|
60
|
+
export async function hopListCommand(options) {
|
|
61
|
+
logger.header('Available HOPs (Higher-Order Prompts)');
|
|
62
|
+
logger.blank();
|
|
63
|
+
|
|
64
|
+
const frameworkRoot = join(process.cwd(), 'framework');
|
|
65
|
+
const hops = listAvailableHOPs(frameworkRoot);
|
|
66
|
+
|
|
67
|
+
if (hops.length === 0) {
|
|
68
|
+
logger.warn('No HOPs found in framework/templates/meta-prompts/');
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const byType = {};
|
|
73
|
+
for (const hop of hops) {
|
|
74
|
+
const type = hop.type || 'other';
|
|
75
|
+
if (!byType[type]) byType[type] = [];
|
|
76
|
+
byType[type].push(hop);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
for (const [type, list] of Object.entries(byType)) {
|
|
80
|
+
console.log(chalk.cyan(`\n ${type.toUpperCase()}`));
|
|
81
|
+
for (const hop of list) {
|
|
82
|
+
console.log(` ${chalk.white(hop.id.padEnd(30))} ${chalk.gray(hop.description || hop.path)}`);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
logger.blank();
|
|
87
|
+
logger.dim(`Total: ${hops.length} HOPs`);
|
|
88
|
+
logger.dim(`Render: morph-spec hop render <hop-id> <output-file> '<variables-json>'`);
|
|
89
|
+
}
|
|
11
90
|
|
|
12
91
|
/**
|
|
13
92
|
* Render template command
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Thread Template CLI command — Thread type management
|
|
3
|
+
*
|
|
4
|
+
* Usage:
|
|
5
|
+
* morph-spec thread-template list
|
|
6
|
+
* morph-spec thread-template use <type> --feature=<feature>
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import chalk from 'chalk';
|
|
10
|
+
import { THREAD_TYPES } from '../../lib/threads/thread-manager.js';
|
|
11
|
+
|
|
12
|
+
const THREAD_TYPE_INFO = {
|
|
13
|
+
[THREAD_TYPES.BASE]: {
|
|
14
|
+
name: 'B-Thread (Base)',
|
|
15
|
+
description: 'Standard single-agent thread. Sequential execution, all approval gates required.',
|
|
16
|
+
useCase: 'Default for simple and medium features',
|
|
17
|
+
phases: 'All standard phases',
|
|
18
|
+
approvalGates: 'Manual (all)',
|
|
19
|
+
maxConcurrent: 1
|
|
20
|
+
},
|
|
21
|
+
[THREAD_TYPES.PARALLEL]: {
|
|
22
|
+
name: 'P-Thread (Parallel)',
|
|
23
|
+
description: 'Multiple agents run simultaneously on different feature domains.',
|
|
24
|
+
useCase: 'Full-stack features with independent backend/frontend/infra work',
|
|
25
|
+
phases: 'All phases (parallel IMPLEMENT)',
|
|
26
|
+
approvalGates: 'Manual (all)',
|
|
27
|
+
maxConcurrent: 5
|
|
28
|
+
},
|
|
29
|
+
[THREAD_TYPES.FUSION]: {
|
|
30
|
+
name: 'F-Thread (Fusion)',
|
|
31
|
+
description: 'N agents independently generate solutions; best-of-N result is selected.',
|
|
32
|
+
useCase: 'High-uncertainty decisions, critical architecture choices, prototype evaluation',
|
|
33
|
+
phases: 'DESIGN → parallel IMPLEMENT → AGGREGATE → SYNC',
|
|
34
|
+
approvalGates: 'Manual select (or auto best-of-n)',
|
|
35
|
+
maxConcurrent: 3
|
|
36
|
+
},
|
|
37
|
+
[THREAD_TYPES.LONG_RUNNING]: {
|
|
38
|
+
name: 'L-Thread (Long-Running)',
|
|
39
|
+
description: 'Autonomous agent with stop hooks every 30 minutes for validation.',
|
|
40
|
+
useCase: 'Large scope features (>10 files), autonomous implementation without interruption',
|
|
41
|
+
phases: 'IMPLEMENT (continuous) with periodic validation',
|
|
42
|
+
approvalGates: 'Auto (stop hooks validate)',
|
|
43
|
+
maxConcurrent: 1
|
|
44
|
+
},
|
|
45
|
+
[THREAD_TYPES.ZERO_TOUCH]: {
|
|
46
|
+
name: 'Z-Thread (Zero-Touch)',
|
|
47
|
+
description: 'Fully autonomous execution. Auto-approves all gates, auto-commits on success.',
|
|
48
|
+
useCase: 'Maximum-trust features with >95% checkpoint pass rate',
|
|
49
|
+
phases: 'All phases (auto-approved)',
|
|
50
|
+
approvalGates: 'Auto (trust-based)',
|
|
51
|
+
maxConcurrent: 1
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
export async function threadTemplateListCommand(options) {
|
|
56
|
+
console.log(chalk.cyan('\n Thread Types (v3.0)\n'));
|
|
57
|
+
console.log(' ' + '─'.repeat(70));
|
|
58
|
+
|
|
59
|
+
for (const [type, info] of Object.entries(THREAD_TYPE_INFO)) {
|
|
60
|
+
console.log(`\n ${chalk.bold(info.name)}`);
|
|
61
|
+
console.log(` ${info.description}`);
|
|
62
|
+
console.log(` ${chalk.gray('Use case:')} ${info.useCase}`);
|
|
63
|
+
console.log(` ${chalk.gray('Phases:')} ${info.phases}`);
|
|
64
|
+
console.log(` ${chalk.gray('Gates:')} ${info.approvalGates}`);
|
|
65
|
+
console.log(` ${chalk.gray('Max concurrent:')} ${info.maxConcurrent}`);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
console.log('\n ' + '─'.repeat(70));
|
|
69
|
+
console.log(chalk.gray('\n Set thread type: morph-spec thread-template use <type> --feature=<feature>\n'));
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export async function threadTemplateUseCommand(type, options) {
|
|
73
|
+
if (!options.feature) {
|
|
74
|
+
console.error(chalk.red('--feature is required'));
|
|
75
|
+
process.exit(1);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
if (!THREAD_TYPE_INFO[type]) {
|
|
79
|
+
console.error(chalk.red(`Unknown thread type: ${type}`));
|
|
80
|
+
console.error(chalk.gray(`Valid types: ${Object.keys(THREAD_TYPE_INFO).join(', ')}`));
|
|
81
|
+
process.exit(1);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const info = THREAD_TYPE_INFO[type];
|
|
85
|
+
|
|
86
|
+
// Special checks
|
|
87
|
+
if (type === THREAD_TYPES.ZERO_TOUCH) {
|
|
88
|
+
console.log(chalk.yellow('\n ⚠ Z-Thread requires maximum trust level (>95% checkpoint pass rate)'));
|
|
89
|
+
console.log(chalk.gray(' Check trust: morph-spec trust status\n'));
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// Update feature state with thread type
|
|
93
|
+
try {
|
|
94
|
+
const { updateFeature } = await import('../../core/state/state-manager.js');
|
|
95
|
+
await updateFeature(options.feature, 'threadType', type);
|
|
96
|
+
console.log(chalk.green(`\n ✓ Thread type set: ${type} for feature: ${options.feature}`));
|
|
97
|
+
console.log(` ${info.name}: ${info.description}`);
|
|
98
|
+
console.log('');
|
|
99
|
+
} catch (err) {
|
|
100
|
+
console.error(chalk.red(` Error updating state: ${err.message}`));
|
|
101
|
+
process.exit(1);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Threads CLI command — Thread lifecycle management
|
|
3
|
+
*
|
|
4
|
+
* Usage:
|
|
5
|
+
* morph-spec threads list [--feature=<f>] [--status=<s>]
|
|
6
|
+
* morph-spec threads status <id>
|
|
7
|
+
* morph-spec threads kill <id>
|
|
8
|
+
* morph-spec threads analytics [--feature=<f>]
|
|
9
|
+
* morph-spec threads wait-all <feature>
|
|
10
|
+
* morph-spec threads wait-any <feature>
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import chalk from 'chalk';
|
|
14
|
+
import {
|
|
15
|
+
listThreads, getThread, killThread, getThreadAnalytics,
|
|
16
|
+
THREAD_STATUS, THREAD_TYPES
|
|
17
|
+
} from '../../lib/threads/thread-manager.js';
|
|
18
|
+
import { generateAsciiChart, generateTimelineChart } from '../../lib/analytics/analytics-engine.js';
|
|
19
|
+
|
|
20
|
+
const STATUS_COLORS = {
|
|
21
|
+
[THREAD_STATUS.PENDING]: chalk.yellow,
|
|
22
|
+
[THREAD_STATUS.RUNNING]: chalk.cyan,
|
|
23
|
+
[THREAD_STATUS.COMPLETED]: chalk.green,
|
|
24
|
+
[THREAD_STATUS.FAILED]: chalk.red,
|
|
25
|
+
[THREAD_STATUS.KILLED]: chalk.gray
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
const TYPE_ICONS = {
|
|
29
|
+
[THREAD_TYPES.BASE]: '◆',
|
|
30
|
+
[THREAD_TYPES.PARALLEL]: '⫸',
|
|
31
|
+
[THREAD_TYPES.FUSION]: '⊕',
|
|
32
|
+
[THREAD_TYPES.LONG_RUNNING]: '∞',
|
|
33
|
+
[THREAD_TYPES.ZERO_TOUCH]: '⚡'
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
function formatDuration(seconds) {
|
|
37
|
+
if (!seconds) return '—';
|
|
38
|
+
if (seconds < 60) return `${seconds}s`;
|
|
39
|
+
if (seconds < 3600) return `${Math.floor(seconds / 60)}m ${seconds % 60}s`;
|
|
40
|
+
return `${Math.floor(seconds / 3600)}h ${Math.floor((seconds % 3600) / 60)}m`;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* List threads
|
|
45
|
+
*/
|
|
46
|
+
export async function threadsListCommand(options) {
|
|
47
|
+
try {
|
|
48
|
+
const threads = listThreads({
|
|
49
|
+
feature: options.feature,
|
|
50
|
+
status: options.status,
|
|
51
|
+
type: options.type
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
if (threads.length === 0) {
|
|
55
|
+
console.log(chalk.gray('No threads found.'));
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
console.log(chalk.cyan(`\n Threads (${threads.length})\n`));
|
|
60
|
+
console.log(
|
|
61
|
+
' ' + 'ID'.padEnd(10) + ' ' +
|
|
62
|
+
'Type'.padEnd(14) + ' ' +
|
|
63
|
+
'Status'.padEnd(12) + ' ' +
|
|
64
|
+
'Feature'.padEnd(20) + ' ' +
|
|
65
|
+
'Agent'.padEnd(20) + ' ' +
|
|
66
|
+
'Duration'
|
|
67
|
+
);
|
|
68
|
+
console.log(' ' + '─'.repeat(90));
|
|
69
|
+
|
|
70
|
+
for (const t of threads) {
|
|
71
|
+
const icon = TYPE_ICONS[t.type] || '◆';
|
|
72
|
+
const colorFn = STATUS_COLORS[t.status] || chalk.white;
|
|
73
|
+
const shortId = t.id.substring(0, 8);
|
|
74
|
+
|
|
75
|
+
console.log(
|
|
76
|
+
' ' +
|
|
77
|
+
chalk.gray(shortId) + ' ' +
|
|
78
|
+
`${icon} ${t.type}`.padEnd(14) + ' ' +
|
|
79
|
+
colorFn(t.status.padEnd(12)) + ' ' +
|
|
80
|
+
(t.feature || '—').padEnd(20) + ' ' +
|
|
81
|
+
(t.agent || '—').padEnd(20) + ' ' +
|
|
82
|
+
formatDuration(t.duration)
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
console.log('');
|
|
86
|
+
} catch (err) {
|
|
87
|
+
console.error(chalk.red(`Error: ${err.message}`));
|
|
88
|
+
process.exit(1);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Show thread status detail
|
|
94
|
+
*/
|
|
95
|
+
export async function threadsStatusCommand(id) {
|
|
96
|
+
try {
|
|
97
|
+
const thread = getThread(id);
|
|
98
|
+
if (!thread) {
|
|
99
|
+
console.error(chalk.red(`Thread not found: ${id}`));
|
|
100
|
+
process.exit(1);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
const colorFn = STATUS_COLORS[thread.status] || chalk.white;
|
|
104
|
+
const icon = TYPE_ICONS[thread.type] || '◆';
|
|
105
|
+
|
|
106
|
+
console.log(chalk.cyan('\n Thread Detail\n'));
|
|
107
|
+
console.log(` ID: ${chalk.gray(thread.id)}`);
|
|
108
|
+
console.log(` Type: ${icon} ${thread.type}`);
|
|
109
|
+
console.log(` Status: ${colorFn(thread.status)}`);
|
|
110
|
+
console.log(` Feature: ${thread.feature || '—'}`);
|
|
111
|
+
console.log(` Agent: ${thread.agent || '—'}`);
|
|
112
|
+
console.log(` Mission: ${thread.mission || '—'}`);
|
|
113
|
+
console.log(` Created: ${thread.createdAt}`);
|
|
114
|
+
console.log(` Started: ${thread.startedAt || '—'}`);
|
|
115
|
+
console.log(` Ended: ${thread.completedAt || '—'}`);
|
|
116
|
+
console.log(` Duration: ${formatDuration(thread.duration)}`);
|
|
117
|
+
|
|
118
|
+
if (thread.metrics) {
|
|
119
|
+
console.log('\n Metrics:');
|
|
120
|
+
console.log(` Tool calls: ${thread.metrics.toolCalls || 0}`);
|
|
121
|
+
console.log(` Tokens used: ${(thread.metrics.tokensUsed || 0).toLocaleString()}`);
|
|
122
|
+
console.log(` Checkpoints OK: ${thread.metrics.checkpointsPassed || 0}`);
|
|
123
|
+
console.log(` Checkpoints KO: ${thread.metrics.checkpointsFailed || 0}`);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
if (thread.events?.length > 0) {
|
|
127
|
+
console.log(`\n Recent events (${thread.events.length}):`);
|
|
128
|
+
thread.events.slice(-5).forEach(e => {
|
|
129
|
+
console.log(` ${chalk.gray(e.timestamp)} ${e.type}`);
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
if (thread.failureReason) {
|
|
134
|
+
console.log(`\n ${chalk.red('Failure:')} ${thread.failureReason}`);
|
|
135
|
+
}
|
|
136
|
+
console.log('');
|
|
137
|
+
} catch (err) {
|
|
138
|
+
console.error(chalk.red(`Error: ${err.message}`));
|
|
139
|
+
process.exit(1);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Kill a thread
|
|
145
|
+
*/
|
|
146
|
+
export async function threadsKillCommand(id) {
|
|
147
|
+
try {
|
|
148
|
+
const thread = killThread(id);
|
|
149
|
+
console.log(chalk.yellow(`✓ Thread ${id.substring(0, 8)} killed.`));
|
|
150
|
+
console.log(` Status: ${thread.status} | Duration: ${formatDuration(thread.duration)}`);
|
|
151
|
+
} catch (err) {
|
|
152
|
+
console.error(chalk.red(`Error: ${err.message}`));
|
|
153
|
+
process.exit(1);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Show threads analytics dashboard
|
|
159
|
+
*/
|
|
160
|
+
export async function threadsAnalyticsCommand(options) {
|
|
161
|
+
try {
|
|
162
|
+
const feature = options.feature;
|
|
163
|
+
if (!feature) {
|
|
164
|
+
console.error(chalk.red('--feature is required for analytics'));
|
|
165
|
+
process.exit(1);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
const analytics = getThreadAnalytics(feature);
|
|
169
|
+
|
|
170
|
+
console.log(chalk.cyan(`\n Thread Analytics — ${feature}\n`));
|
|
171
|
+
console.log(` Total threads: ${analytics.total}`);
|
|
172
|
+
console.log(` By status:`);
|
|
173
|
+
for (const [status, count] of Object.entries(analytics.byStatus)) {
|
|
174
|
+
const colorFn = STATUS_COLORS[status] || chalk.white;
|
|
175
|
+
console.log(` ${colorFn(status.padEnd(12))} ${count}`);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
console.log('\n By type:');
|
|
179
|
+
for (const [type, count] of Object.entries(analytics.byType)) {
|
|
180
|
+
const icon = TYPE_ICONS[type] || '◆';
|
|
181
|
+
console.log(` ${icon} ${type.padEnd(14)} ${count}`);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
console.log(`\n Avg duration: ${formatDuration(analytics.avgDuration)}`);
|
|
185
|
+
console.log(` Total tool calls: ${analytics.totalToolCalls}`);
|
|
186
|
+
console.log(` Checkpoint pass rate: ${Math.round(analytics.checkpointPassRate * 100)}%`);
|
|
187
|
+
|
|
188
|
+
if (analytics.total > 0) {
|
|
189
|
+
const statusChart = generateAsciiChart(analytics.byStatus, { title: 'Threads by Status' });
|
|
190
|
+
console.log('\n' + statusChart);
|
|
191
|
+
}
|
|
192
|
+
console.log('');
|
|
193
|
+
} catch (err) {
|
|
194
|
+
console.error(chalk.red(`Error: ${err.message}`));
|
|
195
|
+
process.exit(1);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* Wait for all threads in a feature to complete
|
|
201
|
+
*/
|
|
202
|
+
export async function threadsWaitAllCommand(feature, options) {
|
|
203
|
+
const timeoutMs = (options.timeout || 60) * 60 * 1000;
|
|
204
|
+
const pollInterval = 5000;
|
|
205
|
+
const start = Date.now();
|
|
206
|
+
|
|
207
|
+
console.log(chalk.cyan(`\n Waiting for all threads in: ${feature}\n`));
|
|
208
|
+
|
|
209
|
+
while (Date.now() - start < timeoutMs) {
|
|
210
|
+
const threads = listThreads({ feature });
|
|
211
|
+
const active = threads.filter(t =>
|
|
212
|
+
t.status === THREAD_STATUS.PENDING || t.status === THREAD_STATUS.RUNNING
|
|
213
|
+
);
|
|
214
|
+
|
|
215
|
+
if (active.length === 0) {
|
|
216
|
+
const failed = threads.filter(t => t.status === THREAD_STATUS.FAILED);
|
|
217
|
+
if (failed.length > 0) {
|
|
218
|
+
console.log(chalk.yellow(` ⚠ ${failed.length} thread(s) failed`));
|
|
219
|
+
process.exit(1);
|
|
220
|
+
}
|
|
221
|
+
console.log(chalk.green(` ✓ All ${threads.length} threads completed`));
|
|
222
|
+
return;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
process.stdout.write(`\r Still running: ${active.length} thread(s)...`);
|
|
226
|
+
await new Promise(r => setTimeout(r, pollInterval));
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
console.error(chalk.red('\n Timeout waiting for threads'));
|
|
230
|
+
process.exit(1);
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
/**
|
|
234
|
+
* Wait for any thread to complete
|
|
235
|
+
*/
|
|
236
|
+
export async function threadsWaitAnyCommand(feature, options) {
|
|
237
|
+
const timeoutMs = (options.timeout || 60) * 60 * 1000;
|
|
238
|
+
const pollInterval = 3000;
|
|
239
|
+
const start = Date.now();
|
|
240
|
+
|
|
241
|
+
console.log(chalk.cyan(`\n Waiting for first thread to complete in: ${feature}\n`));
|
|
242
|
+
|
|
243
|
+
while (Date.now() - start < timeoutMs) {
|
|
244
|
+
const threads = listThreads({ feature });
|
|
245
|
+
const done = threads.find(t =>
|
|
246
|
+
t.status === THREAD_STATUS.COMPLETED || t.status === THREAD_STATUS.FAILED
|
|
247
|
+
);
|
|
248
|
+
|
|
249
|
+
if (done) {
|
|
250
|
+
const colorFn = STATUS_COLORS[done.status] || chalk.white;
|
|
251
|
+
console.log(` ${colorFn('✓')} Thread ${done.id.substring(0, 8)} ${done.status}`);
|
|
252
|
+
if (done.agent) console.log(` Agent: ${done.agent}`);
|
|
253
|
+
return;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
await new Promise(r => setTimeout(r, pollInterval));
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
console.error(chalk.red('\n Timeout waiting for thread'));
|
|
260
|
+
process.exit(1);
|
|
261
|
+
}
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Trust CLI — Trust level management for zero-touch execution
|
|
3
|
+
*
|
|
4
|
+
* Usage:
|
|
5
|
+
* morph-spec trust status [feature]
|
|
6
|
+
* morph-spec trust set <feature> <level> [reason]
|
|
7
|
+
* morph-spec trust history
|
|
8
|
+
* morph-spec trust auto-calculate <feature>
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import chalk from 'chalk';
|
|
12
|
+
import {
|
|
13
|
+
getTrust,
|
|
14
|
+
setTrust,
|
|
15
|
+
clearTrustOverride,
|
|
16
|
+
getTrustHistory,
|
|
17
|
+
autoCalculateTrust,
|
|
18
|
+
TRUST_THRESHOLDS,
|
|
19
|
+
AUTO_APPROVE_GATES
|
|
20
|
+
} from '../../lib/trust/trust-manager.js';
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Trust status — current trust level for a feature or all features
|
|
24
|
+
*/
|
|
25
|
+
export async function trustStatusCommand(featureName, options) {
|
|
26
|
+
if (featureName) {
|
|
27
|
+
const trust = getTrust(featureName);
|
|
28
|
+
|
|
29
|
+
console.log(chalk.bold(`\n Trust Status — ${featureName}`));
|
|
30
|
+
console.log(' ' + '─'.repeat(50));
|
|
31
|
+
|
|
32
|
+
const levelColor = trust.level === 'maximum' ? chalk.green
|
|
33
|
+
: trust.level === 'high' ? chalk.cyan
|
|
34
|
+
: trust.level === 'medium' ? chalk.yellow
|
|
35
|
+
: chalk.red;
|
|
36
|
+
|
|
37
|
+
console.log(` Level: ${levelColor(trust.level.toUpperCase())}`);
|
|
38
|
+
console.log(` Pass Rate: ${Math.round((trust.passRate || 0) * 100)}%`);
|
|
39
|
+
console.log(` Checkpoints: ${trust.passed || 0}/${trust.total || 0} passed`);
|
|
40
|
+
console.log(` Source: ${trust.source || 'calculated'}`);
|
|
41
|
+
|
|
42
|
+
if (trust.source === 'manual') {
|
|
43
|
+
console.log(chalk.yellow(` Override: ${trust.overrideReason || 'No reason provided'}`));
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
console.log(`\n Auto-approved gates:`);
|
|
47
|
+
if (trust.autoApprove.length === 0) {
|
|
48
|
+
console.log(chalk.gray(' (none — manual approval required for all gates)'));
|
|
49
|
+
} else {
|
|
50
|
+
trust.autoApprove.forEach(g => console.log(chalk.green(` ✓ ${g}`)));
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
console.log(`\n Trust thresholds:`);
|
|
54
|
+
for (const [level, threshold] of Object.entries(TRUST_THRESHOLDS)) {
|
|
55
|
+
const gates = AUTO_APPROVE_GATES[level] || [];
|
|
56
|
+
const marker = trust.level === level ? chalk.bold(' ← current') : '';
|
|
57
|
+
console.log(` ${level.padEnd(10)} ≥ ${Math.round(threshold * 100)}% auto-approves: ${gates.join(', ') || 'none'}${marker}`);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
console.log();
|
|
61
|
+
} else {
|
|
62
|
+
// Show all features
|
|
63
|
+
const history = getTrustHistory();
|
|
64
|
+
if (history.length === 0) {
|
|
65
|
+
console.log(chalk.yellow('\n No features found.\n'));
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
console.log(chalk.bold('\n Trust Overview'));
|
|
70
|
+
console.log(' ' + '─'.repeat(70));
|
|
71
|
+
console.log(` ${'Feature'.padEnd(25)} ${'Level'.padEnd(10)} ${'Pass%'.padEnd(8)} ${'CPs'.padEnd(8)} Phase`);
|
|
72
|
+
console.log(' ' + '─'.repeat(70));
|
|
73
|
+
|
|
74
|
+
for (const f of history) {
|
|
75
|
+
const levelColor = f.level === 'maximum' ? chalk.green
|
|
76
|
+
: f.level === 'high' ? chalk.cyan
|
|
77
|
+
: f.level === 'medium' ? chalk.yellow
|
|
78
|
+
: chalk.red;
|
|
79
|
+
|
|
80
|
+
console.log(
|
|
81
|
+
` ${f.feature.padEnd(25)} ` +
|
|
82
|
+
`${levelColor(f.level.padEnd(10))} ` +
|
|
83
|
+
`${String(Math.round(f.passRate * 100) + '%').padEnd(8)} ` +
|
|
84
|
+
`${String(f.checkpointsTotal).padEnd(8)} ` +
|
|
85
|
+
`${f.phase || 'N/A'}`
|
|
86
|
+
);
|
|
87
|
+
}
|
|
88
|
+
console.log();
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Trust set — manually override trust level
|
|
94
|
+
*/
|
|
95
|
+
export async function trustSetCommand(featureName, level, reason, options) {
|
|
96
|
+
if (!featureName || !level) {
|
|
97
|
+
console.error(chalk.red('Usage: morph-spec trust set <feature> <level> [reason]'));
|
|
98
|
+
console.error(chalk.gray('Levels: low, medium, high, maximum'));
|
|
99
|
+
process.exit(1);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
const effectiveReason = reason || `Manual override to ${level}`;
|
|
103
|
+
|
|
104
|
+
try {
|
|
105
|
+
const result = setTrust(featureName, level, effectiveReason);
|
|
106
|
+
|
|
107
|
+
console.log(chalk.green(`\n✓ Trust updated for ${featureName}`));
|
|
108
|
+
console.log(` Level: ${result.level}`);
|
|
109
|
+
console.log(` Auto-approves: ${result.autoApprove.join(', ') || 'none'}`);
|
|
110
|
+
console.log(` Reason: ${result.reason}`);
|
|
111
|
+
console.log(chalk.gray('\n Note: Use "trust auto-calculate" to revert to calculated trust.\n'));
|
|
112
|
+
} catch (err) {
|
|
113
|
+
console.error(chalk.red(`Error: ${err.message}`));
|
|
114
|
+
process.exit(1);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Trust history — table of all features with checkpoint pass rates
|
|
120
|
+
*/
|
|
121
|
+
export async function trustHistoryCommand(options) {
|
|
122
|
+
const history = getTrustHistory();
|
|
123
|
+
|
|
124
|
+
console.log(chalk.bold('\n Trust History'));
|
|
125
|
+
console.log(' ' + '─'.repeat(80));
|
|
126
|
+
|
|
127
|
+
if (history.length === 0) {
|
|
128
|
+
console.log(chalk.gray(' No features found.\n'));
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
for (const f of history) {
|
|
133
|
+
const levelColor = f.level === 'maximum' ? chalk.green
|
|
134
|
+
: f.level === 'high' ? chalk.cyan
|
|
135
|
+
: f.level === 'medium' ? chalk.yellow
|
|
136
|
+
: chalk.red;
|
|
137
|
+
|
|
138
|
+
console.log(`\n ${chalk.bold(f.feature)}`);
|
|
139
|
+
console.log(` Trust: ${levelColor(f.level)} (${Math.round(f.passRate * 100)}% pass rate)`);
|
|
140
|
+
console.log(` Checkpoints: ${f.checkpointsPassed}/${f.checkpointsTotal} passed`);
|
|
141
|
+
console.log(` Phase: ${f.phase || 'N/A'} | Status: ${f.status || 'N/A'}`);
|
|
142
|
+
console.log(` Source: ${f.source}`);
|
|
143
|
+
|
|
144
|
+
if (f.autoApprove.length > 0) {
|
|
145
|
+
console.log(` Auto-approves: ${chalk.green(f.autoApprove.join(', '))}`);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
console.log('\n ' + '─'.repeat(80));
|
|
150
|
+
console.log(chalk.gray(` Total features: ${history.length}\n`));
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Trust auto-calculate — recalculate from checkpoint history
|
|
155
|
+
*/
|
|
156
|
+
export async function trustAutoCalculateCommand(featureName, options) {
|
|
157
|
+
if (!featureName) {
|
|
158
|
+
console.error(chalk.red('Usage: morph-spec trust auto-calculate <feature>'));
|
|
159
|
+
process.exit(1);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
try {
|
|
163
|
+
const result = autoCalculateTrust(featureName);
|
|
164
|
+
|
|
165
|
+
const levelColor = result.level === 'maximum' ? chalk.green
|
|
166
|
+
: result.level === 'high' ? chalk.cyan
|
|
167
|
+
: result.level === 'medium' ? chalk.yellow
|
|
168
|
+
: chalk.red;
|
|
169
|
+
|
|
170
|
+
console.log(chalk.bold(`\n Trust Calculated — ${featureName}`));
|
|
171
|
+
console.log(' ' + '─'.repeat(40));
|
|
172
|
+
console.log(` Level: ${levelColor(result.level.toUpperCase())}`);
|
|
173
|
+
console.log(` Pass Rate: ${Math.round(result.passRate * 100)}%`);
|
|
174
|
+
console.log(` Checkpoints: ${result.passed}/${result.total} passed`);
|
|
175
|
+
console.log(` Auto-approves: ${result.autoApprove.join(', ') || 'none'}`);
|
|
176
|
+
|
|
177
|
+
if (result.level === 'maximum') {
|
|
178
|
+
console.log(chalk.green('\n ✓ Feature is eligible for zero-touch execution!'));
|
|
179
|
+
console.log(chalk.gray(' All gates will be auto-approved.\n'));
|
|
180
|
+
} else {
|
|
181
|
+
const nextLevel = result.passRate < TRUST_THRESHOLDS.medium ? 'medium'
|
|
182
|
+
: result.passRate < TRUST_THRESHOLDS.high ? 'high'
|
|
183
|
+
: 'maximum';
|
|
184
|
+
const needed = Math.ceil(TRUST_THRESHOLDS[nextLevel] * result.total) - result.passed;
|
|
185
|
+
console.log(chalk.gray(`\n Next level: ${nextLevel} (need ${needed} more passing checkpoints)\n`));
|
|
186
|
+
}
|
|
187
|
+
} catch (err) {
|
|
188
|
+
console.error(chalk.red(`Error: ${err.message}`));
|
|
189
|
+
process.exit(1);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* Trust clear — remove manual override
|
|
195
|
+
*/
|
|
196
|
+
export async function trustClearCommand(featureName, options) {
|
|
197
|
+
if (!featureName) {
|
|
198
|
+
console.error(chalk.red('Usage: morph-spec trust clear <feature>'));
|
|
199
|
+
process.exit(1);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
clearTrustOverride(featureName);
|
|
203
|
+
console.log(chalk.green(`\n✓ Manual trust override cleared for ${featureName}`));
|
|
204
|
+
console.log(chalk.gray(' Trust will now be calculated from checkpoint history.\n'));
|
|
205
|
+
}
|
|
@@ -4,18 +4,18 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import chalk from 'chalk';
|
|
7
|
-
import { ProjectScanner } from '
|
|
8
|
-
import { ContextSanitizer } from '
|
|
9
|
-
import { LLMAnalyzer } from '
|
|
10
|
-
import { ConfigGenerator } from '
|
|
11
|
-
import { UserReview } from '
|
|
12
|
-
import { InteractiveWizard } from '
|
|
13
|
-
import { FileWriter } from '
|
|
7
|
+
import { ProjectScanner } from '../scanner/project-scanner.js';
|
|
8
|
+
import { ContextSanitizer } from '../sanitizer/context-sanitizer.js';
|
|
9
|
+
import { LLMAnalyzer } from '../llm/analyzer.js';
|
|
10
|
+
import { ConfigGenerator } from '../generator/config-generator.js';
|
|
11
|
+
import { UserReview } from '../ui/user-review.js';
|
|
12
|
+
import { InteractiveWizard } from '../ui/interactive-wizard.js';
|
|
13
|
+
import { FileWriter } from '../writer/file-writer.js';
|
|
14
14
|
import { readFile, access } from 'fs/promises';
|
|
15
15
|
import { join } from 'path';
|
|
16
16
|
|
|
17
17
|
/**
|
|
18
|
-
* @typedef {import('
|
|
18
|
+
* @typedef {import('../types/index.js').GeneratedConfigs} GeneratedConfigs
|
|
19
19
|
*/
|
|
20
20
|
|
|
21
21
|
/**
|